Compare commits
190 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e72ea5ddc | |||
| f8ed7db472 | |||
| 41caf1cdfa | |||
| f6ec2b5946 | |||
| e15d5de0a6 | |||
| cf2710e0b6 | |||
| 941602ae4f | |||
| 34e4c6f732 | |||
| 2fbb3fb532 | |||
| df9471b1b5 | |||
| bd1402487b | |||
| 4703b7d092 | |||
| 404ddadbd4 | |||
| fd6beda14b | |||
| 48f5e52728 | |||
| b458cbb601 | |||
| 6593b340ff | |||
| 0de7da1998 | |||
| 6d98c55b56 | |||
| e3eefe00dd | |||
| ecaa021759 | |||
| 7d24afa0de | |||
| 077f9b14f1 | |||
| c5a0ed7b43 | |||
| 8741ca0819 | |||
| 586b2b2a54 | |||
| e1b55a5af9 | |||
| 0507e6e388 | |||
| 9c3eef8c0d | |||
| af35432400 | |||
| cadfdd4e09 | |||
| 5ef9c89977 | |||
| d72ca8f810 | |||
| 2f755cdc3a | |||
| 4c86b2db0f | |||
| 1344b540d9 | |||
| 5b7048d5af | |||
| 7da33383c7 | |||
| c327bd0354 | |||
| 1085eee098 | |||
| eccb42eb0e | |||
| bb24c75b41 | |||
| 54bfc9435f | |||
| d79ce8a459 | |||
| 7c6256234c | |||
| c34ff12c59 | |||
| d60a503b4c | |||
| 05665e9de9 | |||
| efe474af97 | |||
| 6fa46d0e06 | |||
| 2386943f19 | |||
| 18970dac18 | |||
| 38af125238 | |||
| b23f92b286 | |||
| eeb8506c18 | |||
| d081df0a5d | |||
| 09d8e696dc | |||
| 20c118faec | |||
| fefe24ddf8 | |||
| 09f87094bd | |||
| ee8f926027 | |||
| 4ed784d1e8 | |||
| a7f3b0f85b | |||
| c598fdd10c | |||
| 0e7a7e57cc | |||
| 4aaf45e246 | |||
| 89b04f3786 | |||
| 31079226f7 | |||
| 7c492a250b | |||
| e6d3c57204 | |||
| 294cd87afc | |||
| 18ec0d4a34 | |||
| bebe2d8be8 | |||
| 3731703dbb | |||
| 2526668556 | |||
| 33087dbf30 | |||
| b8337932b3 | |||
| 00208479fd | |||
| f765aec406 | |||
| e212493358 | |||
| df903fe056 | |||
| 0462499051 | |||
| 79dac84b31 | |||
| b834f629cc | |||
| c83386cbe5 | |||
| 0445cd1020 | |||
| fa0763eb34 | |||
| c72953a4bc | |||
| c4439fb134 | |||
| 61f2ee6ab8 | |||
| 1550771a6a | |||
| 9a1a4822e8 | |||
| a0693f21fc | |||
| 433af7ab93 | |||
| 32ca0dbcdf | |||
| 12b205c637 | |||
| 4f59d09648 | |||
| f722d91fa8 | |||
| 5d783d5c84 | |||
| e09e451a48 | |||
| 325420616f | |||
| 0e4afddadf | |||
| 7e60106d15 | |||
| 8292aa7a18 | |||
| a8c43830f2 | |||
| 0e93237b17 | |||
| f0c9bc596e | |||
| 788ade3487 | |||
| 538ad6ce58 | |||
| d1122a4c0f | |||
| a40cae7802 | |||
| e871779f7e | |||
| 11a088b7eb | |||
| 07305e3a3a | |||
| ebf9702b34 | |||
| f4744ff1ff | |||
| cbea8d5c3f | |||
| 0f78aafec8 | |||
| 1002bcff43 | |||
| 1aa94b5821 | |||
| 5b80dbe6b3 | |||
| c52c00f670 | |||
| e8ba446a9a | |||
| 2eb9adb564 | |||
| 5b9b7cba22 | |||
| 0901571f0a | |||
| 9c0d777a9f | |||
| 72814933b9 | |||
| 01508c814c | |||
| aeb62886c5 | |||
| d059774365 | |||
| 9b4e7898d7 | |||
| 78bc1339ac | |||
| 2ae4531c89 | |||
| f3ea92cceb | |||
| 2ad1e92858 | |||
| 19ca99eea4 | |||
| 8d5fe073d2 | |||
| b11daa50f9 | |||
| b95c1d0ac9 | |||
| 6c290ccd49 | |||
| 4c3ab545a9 | |||
| 297472a2fc | |||
| d3a4dbe4b8 | |||
| 84a231eb61 | |||
| 3afd5b6d65 | |||
| 99ac2324aa | |||
| 317b7416a6 | |||
| d591a5b93d | |||
| fed13d50a9 | |||
| ec14ef80b0 | |||
| ddc6bd9f21 | |||
| 23afc2c4ec | |||
| c859f0267c | |||
| f8e195159f | |||
| 0868d58e2c | |||
| dfa6289153 | |||
| 35b771e221 | |||
| 5b27ecafbc | |||
| b065eceb56 | |||
| 99200b2f07 | |||
| 14602eafa7 | |||
| 0309fb919a | |||
| 3ac612dd7d | |||
| 642e950e63 | |||
| 6e6dfd6a23 | |||
| 46435a04fd | |||
| 5d8daf184d | |||
| 0a42e9913b | |||
| 4f2f6c74ca | |||
| 2469350ad9 | |||
| 2c26adb873 | |||
| db2a33a3dd | |||
| 5749e1ee43 | |||
| d737feeacf | |||
| 0526db32e2 | |||
| 06915d0145 | |||
| 0221cacea7 | |||
| 6f4e5ee4c9 | |||
| 1d40237bc8 | |||
| ae7ede4a4f | |||
| 366b419d00 | |||
| c494fdb580 | |||
| b6d108f0b3 | |||
| 495ce22d49 | |||
| 73a50fa42c | |||
| d21d5b21db | |||
| 1278ac411c | |||
| d59afcfbfe | |||
| 0389d5f8d0 |
@@ -454,6 +454,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/spellfix.c \
|
||||
$(TOP)/ext/misc/stmtrand.c \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
|
||||
@@ -1596,6 +1596,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\spellfix.c \
|
||||
$(TOP)\ext\misc\stmtrand.c \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c \
|
||||
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.46.0])
|
||||
AC_INIT([sqlite],[3.47.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.46.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.47.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.46.0'
|
||||
PACKAGE_STRING='sqlite 3.46.0'
|
||||
PACKAGE_VERSION='3.47.0'
|
||||
PACKAGE_STRING='sqlite 3.47.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1472,7 +1472,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.46.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.47.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1537,7 +1537,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.46.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.47.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1668,7 +1668,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.46.0
|
||||
sqlite configure 3.47.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2087,7 +2087,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.46.0, which was
|
||||
It was created by sqlite $as_me 3.47.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -12481,7 +12481,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.46.0, which was
|
||||
This file was extended by sqlite $as_me 3.47.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12547,7 +12547,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.46.0
|
||||
sqlite config.status 3.47.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -446,7 +446,7 @@ static void fts3SnippetDetails(
|
||||
}
|
||||
mCover |= mPhrase;
|
||||
|
||||
for(j=0; j<pPhrase->nToken; j++){
|
||||
for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
|
||||
mHighlight |= (mPos>>j);
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -142,6 +142,15 @@ struct Fts5Colset {
|
||||
*/
|
||||
|
||||
typedef struct Fts5Config Fts5Config;
|
||||
typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
|
||||
|
||||
struct Fts5TokenizerConfig {
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
const char **azArg;
|
||||
int nArg;
|
||||
int ePattern; /* FTS_PATTERN_XXX constant */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the following structure encodes all information that can
|
||||
@@ -184,6 +193,7 @@ typedef struct Fts5Config Fts5Config;
|
||||
*/
|
||||
struct Fts5Config {
|
||||
sqlite3 *db; /* Database handle */
|
||||
Fts5Global *pGlobal; /* Global fts5 object for handle db */
|
||||
char *zDb; /* Database holding FTS index (e.g. "main") */
|
||||
char *zName; /* Name of FTS index */
|
||||
int nCol; /* Number of columns */
|
||||
@@ -199,10 +209,8 @@ struct Fts5Config {
|
||||
int bTokendata; /* "tokendata=" option value (dflt==0) */
|
||||
int eDetail; /* FTS5_DETAIL_XXX value */
|
||||
char *zContentExprlist;
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
Fts5TokenizerConfig t;
|
||||
int bLock; /* True when table is preparing statement */
|
||||
int ePattern; /* FTS_PATTERN_XXX constant */
|
||||
|
||||
/* Values loaded from the %_config table */
|
||||
int iVersion; /* fts5 file format 'version' */
|
||||
@@ -597,13 +605,7 @@ struct Fts5Table {
|
||||
Fts5Index *pIndex; /* Full-text index */
|
||||
};
|
||||
|
||||
int sqlite3Fts5GetTokenizer(
|
||||
Fts5Global*,
|
||||
const char **azArg,
|
||||
int nArg,
|
||||
Fts5Config*,
|
||||
char **pzErr
|
||||
);
|
||||
int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);
|
||||
|
||||
Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
|
||||
|
||||
@@ -866,6 +868,7 @@ int sqlite3Fts5TokenizerPattern(
|
||||
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
|
||||
Fts5Tokenizer *pTok
|
||||
);
|
||||
int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
|
||||
/*
|
||||
** End of interface to code in fts5_tokenizer.c.
|
||||
**************************************************************************/
|
||||
|
||||
+25
-36
@@ -234,7 +234,6 @@ static int fts5ConfigSetEnum(
|
||||
** eventually free any such error message using sqlite3_free().
|
||||
*/
|
||||
static int fts5ConfigParseSpecial(
|
||||
Fts5Global *pGlobal,
|
||||
Fts5Config *pConfig, /* Configuration object to update */
|
||||
const char *zCmd, /* Special command to parse */
|
||||
const char *zArg, /* Argument to parse */
|
||||
@@ -298,12 +297,11 @@ static int fts5ConfigParseSpecial(
|
||||
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
|
||||
const char *p = (const char*)zArg;
|
||||
sqlite3_int64 nArg = strlen(zArg) + 1;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
|
||||
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
|
||||
char *pSpace = pDel;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);
|
||||
|
||||
if( azArg && pSpace ){
|
||||
if( pConfig->pTok ){
|
||||
if( azArg ){
|
||||
char *pSpace = (char*)&azArg[nArg];
|
||||
if( pConfig->t.azArg ){
|
||||
*pzErr = sqlite3_mprintf("multiple tokenize=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
@@ -326,16 +324,14 @@ static int fts5ConfigParseSpecial(
|
||||
*pzErr = sqlite3_mprintf("parse error in tokenize directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = sqlite3Fts5GetTokenizer(pGlobal,
|
||||
(const char**)azArg, (int)nArg, pConfig,
|
||||
pzErr
|
||||
);
|
||||
pConfig->t.azArg = (const char**)azArg;
|
||||
pConfig->t.nArg = nArg;
|
||||
azArg = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_free(azArg);
|
||||
sqlite3_free(pDel);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -412,16 +408,6 @@ static int fts5ConfigParseSpecial(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate an instance of the default tokenizer ("simple") at
|
||||
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
|
||||
** code if an error occurs.
|
||||
*/
|
||||
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
|
||||
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
|
||||
return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Gobble up the first bareword or quoted word from the input buffer zIn.
|
||||
** Return a pointer to the character immediately following the last in
|
||||
@@ -554,6 +540,7 @@ int sqlite3Fts5ConfigParse(
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
|
||||
if( pRet==0 ) return SQLITE_NOMEM;
|
||||
memset(pRet, 0, sizeof(Fts5Config));
|
||||
pRet->pGlobal = pGlobal;
|
||||
pRet->db = db;
|
||||
pRet->iCookie = -1;
|
||||
|
||||
@@ -602,7 +589,7 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
if( bOption ){
|
||||
rc = fts5ConfigParseSpecial(pGlobal, pRet,
|
||||
rc = fts5ConfigParseSpecial(pRet,
|
||||
ALWAYS(zOne)?zOne:"",
|
||||
zTwo?zTwo:"",
|
||||
pzErr
|
||||
@@ -640,13 +627,6 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* If a tokenizer= option was successfully parsed, the tokenizer has
|
||||
** already been allocated. Otherwise, allocate an instance of the default
|
||||
** tokenizer (unicode61) now. */
|
||||
if( rc==SQLITE_OK && pRet->pTok==0 ){
|
||||
rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
|
||||
}
|
||||
|
||||
/* If no zContent option was specified, fill in the default values. */
|
||||
if( rc==SQLITE_OK && pRet->zContent==0 ){
|
||||
const char *zTail = 0;
|
||||
@@ -688,9 +668,10 @@ int sqlite3Fts5ConfigParse(
|
||||
void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
|
||||
if( pConfig ){
|
||||
int i;
|
||||
if( pConfig->pTok ){
|
||||
pConfig->pTokApi->xDelete(pConfig->pTok);
|
||||
if( pConfig->t.pTok ){
|
||||
pConfig->t.pTokApi->xDelete(pConfig->t.pTok);
|
||||
}
|
||||
sqlite3_free((char*)pConfig->t.azArg);
|
||||
sqlite3_free(pConfig->zDb);
|
||||
sqlite3_free(pConfig->zName);
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
@@ -765,10 +746,18 @@ int sqlite3Fts5Tokenize(
|
||||
void *pCtx, /* Context passed to xToken() */
|
||||
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
||||
){
|
||||
if( pText==0 ) return SQLITE_OK;
|
||||
return pConfig->pTokApi->xTokenize(
|
||||
pConfig->pTok, pCtx, flags, pText, nText, xToken
|
||||
);
|
||||
int rc = SQLITE_OK;
|
||||
if( pText ){
|
||||
if( pConfig->t.pTok==0 ){
|
||||
rc = sqlite3Fts5LoadTokenizer(pConfig);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pConfig->t.pTokApi->xTokenize(
|
||||
pConfig->t.pTok, pCtx, flags, pText, nText, xToken
|
||||
);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -324,7 +324,11 @@ int sqlite3Fts5ExprNew(
|
||||
}
|
||||
|
||||
sqlite3_free(sParse.apPhrase);
|
||||
*pzErr = sParse.zErr;
|
||||
if( 0==*pzErr ){
|
||||
*pzErr = sParse.zErr;
|
||||
}else{
|
||||
sqlite3_free(sParse.zErr);
|
||||
}
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
|
||||
+61
-38
@@ -377,8 +377,12 @@ static int fts5InitVtab(
|
||||
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pConfig->pzErrmsg = pzErr;
|
||||
pTab->p.pConfig = pConfig;
|
||||
pTab->pGlobal = pGlobal;
|
||||
if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){
|
||||
rc = sqlite3Fts5LoadTokenizer(pConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the index sub-system */
|
||||
@@ -400,11 +404,8 @@ static int fts5InitVtab(
|
||||
|
||||
/* Load the initial configuration */
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pConfig->pzErrmsg==0 );
|
||||
pConfig->pzErrmsg = pzErr;
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
sqlite3Fts5IndexRollback(pTab->p.pIndex);
|
||||
pConfig->pzErrmsg = 0;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
@@ -414,6 +415,7 @@ static int fts5InitVtab(
|
||||
rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
||||
}
|
||||
|
||||
if( pConfig ) pConfig->pzErrmsg = 0;
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5FreeVtab(pTab);
|
||||
pTab = 0;
|
||||
@@ -481,10 +483,10 @@ static int fts5UsePatternMatch(
|
||||
){
|
||||
assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
|
||||
assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
|
||||
if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
|
||||
if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
|
||||
return 1;
|
||||
}
|
||||
if( pConfig->ePattern==FTS5_PATTERN_LIKE
|
||||
if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
|
||||
&& (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
|
||||
){
|
||||
return 1;
|
||||
@@ -531,10 +533,10 @@ static int fts5UsePatternMatch(
|
||||
** This function ensures that there is at most one "r" or "=". And that if
|
||||
** there exists an "=" then there is no "<" or ">".
|
||||
**
|
||||
** Costs are assigned as follows:
|
||||
** If an unusable MATCH operator is present in the WHERE clause, then
|
||||
** SQLITE_CONSTRAINT is returned.
|
||||
**
|
||||
** a) If an unusable MATCH operator is present in the WHERE clause, the
|
||||
** cost is unconditionally set to 1e50 (a really big number).
|
||||
** Costs are assigned as follows:
|
||||
**
|
||||
** a) If a MATCH operator is present, the cost depends on the other
|
||||
** constraints also present. As follows:
|
||||
@@ -567,7 +569,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
int bSeenEq = 0;
|
||||
int bSeenGt = 0;
|
||||
int bSeenLt = 0;
|
||||
int bSeenMatch = 0;
|
||||
int nSeenMatch = 0;
|
||||
int bSeenRank = 0;
|
||||
|
||||
|
||||
@@ -598,18 +600,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
/* A MATCH operator or equivalent */
|
||||
if( p->usable==0 || iCol<0 ){
|
||||
/* As there exists an unusable MATCH constraint this is an
|
||||
** unusable plan. Set a prohibitively high cost. */
|
||||
pInfo->estimatedCost = 1e50;
|
||||
assert( iIdxStr < pInfo->nConstraint*6 + 1 );
|
||||
idxStr[iIdxStr] = 0;
|
||||
return SQLITE_OK;
|
||||
** unusable plan. Return SQLITE_CONSTRAINT. */
|
||||
return SQLITE_CONSTRAINT;
|
||||
}else{
|
||||
if( iCol==nCol+1 ){
|
||||
if( bSeenRank ) continue;
|
||||
idxStr[iIdxStr++] = 'r';
|
||||
bSeenRank = 1;
|
||||
}else if( iCol>=0 ){
|
||||
bSeenMatch = 1;
|
||||
nSeenMatch++;
|
||||
idxStr[iIdxStr++] = 'M';
|
||||
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
|
||||
idxStr += strlen(&idxStr[iIdxStr]);
|
||||
@@ -626,6 +625,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
idxStr += strlen(&idxStr[iIdxStr]);
|
||||
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||
assert( idxStr[iIdxStr]=='\0' );
|
||||
nSeenMatch++;
|
||||
}else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
|
||||
idxStr[iIdxStr++] = '=';
|
||||
bSeenEq = 1;
|
||||
@@ -662,7 +662,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
*/
|
||||
if( pInfo->nOrderBy==1 ){
|
||||
int iSort = pInfo->aOrderBy[0].iColumn;
|
||||
if( iSort==(pConfig->nCol+1) && bSeenMatch ){
|
||||
if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
|
||||
idxFlags |= FTS5_BI_ORDER_RANK;
|
||||
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
|
||||
idxFlags |= FTS5_BI_ORDER_ROWID;
|
||||
@@ -677,14 +677,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
|
||||
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
||||
if( bSeenEq ){
|
||||
pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
|
||||
if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||
pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
|
||||
if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||
}else if( bSeenLt && bSeenGt ){
|
||||
pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
|
||||
pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
|
||||
}else if( bSeenLt || bSeenGt ){
|
||||
pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
|
||||
pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
|
||||
}else{
|
||||
pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
|
||||
pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
|
||||
}
|
||||
for(i=1; i<nSeenMatch; i++){
|
||||
pInfo->estimatedCost *= 0.4;
|
||||
}
|
||||
|
||||
pInfo->idxNum = idxFlags;
|
||||
@@ -1700,6 +1703,7 @@ static int fts5UpdateMethod(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = fts5SpecialDelete(pTab, apVal);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
@@ -2860,7 +2864,7 @@ static int fts5FindTokenizer(
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3Fts5GetTokenizer(
|
||||
int fts5GetTokenizer(
|
||||
Fts5Global *pGlobal,
|
||||
const char **azArg,
|
||||
int nArg,
|
||||
@@ -2874,29 +2878,42 @@ int sqlite3Fts5GetTokenizer(
|
||||
if( pMod==0 ){
|
||||
assert( nArg>0 );
|
||||
rc = SQLITE_ERROR;
|
||||
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
}else{
|
||||
rc = pMod->x.xCreate(
|
||||
pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
|
||||
pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok
|
||||
);
|
||||
pConfig->pTokApi = &pMod->x;
|
||||
pConfig->t.pTokApi = &pMod->x;
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
|
||||
if( pzErr && rc!=SQLITE_NOMEM ){
|
||||
*pzErr = sqlite3_mprintf("error in tokenizer constructor");
|
||||
}
|
||||
}else{
|
||||
pConfig->ePattern = sqlite3Fts5TokenizerPattern(
|
||||
pMod->x.xCreate, pConfig->pTok
|
||||
pConfig->t.ePattern = sqlite3Fts5TokenizerPattern(
|
||||
pMod->x.xCreate, pConfig->t.pTok
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
pConfig->pTokApi = 0;
|
||||
pConfig->pTok = 0;
|
||||
pConfig->t.pTokApi = 0;
|
||||
pConfig->t.pTok = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to instantiate the tokenizer.
|
||||
*/
|
||||
int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){
|
||||
return fts5GetTokenizer(
|
||||
pConfig->pGlobal, pConfig->t.azArg, pConfig->t.nArg,
|
||||
pConfig, pConfig->pzErrmsg
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static void fts5ModuleDestroy(void *pCtx){
|
||||
Fts5TokenizerModule *pTok, *pNextTok;
|
||||
Fts5Auxiliary *pAux, *pNextAux;
|
||||
@@ -2975,17 +2992,23 @@ static int fts5IntegrityMethod(
|
||||
|
||||
assert( pzErr!=0 && *pzErr==0 );
|
||||
UNUSED_PARAM(isQuick);
|
||||
assert( pTab->p.pConfig->pzErrmsg==0 );
|
||||
pTab->p.pConfig->pzErrmsg = pzErr;
|
||||
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
if( *pzErr==0 && rc!=SQLITE_OK ){
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else{
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
||||
pTab->p.pConfig->pzErrmsg = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1428,6 +1428,16 @@ int sqlite3Fts5TokenizerPattern(
|
||||
return FTS5_PATTERN_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the tokenizer described by p->azArg[] is the trigram
|
||||
** tokenizer. This tokenizer needs to be loaded before xBestIndex is
|
||||
** called for the first time in order to correctly handle LIKE/GLOB.
|
||||
*/
|
||||
int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
|
||||
return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register all built-in tokenizers with FTS5.
|
||||
*/
|
||||
|
||||
+24
-8
@@ -64,6 +64,7 @@ struct Fts5VocabCursor {
|
||||
|
||||
int nLeTerm; /* Size of zLeTerm in bytes */
|
||||
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||
int colUsed; /* Copy of sqlite3_index_info.colUsed */
|
||||
|
||||
/* These are used by 'col' tables only */
|
||||
int iCol;
|
||||
@@ -90,9 +91,11 @@ struct Fts5VocabCursor {
|
||||
/*
|
||||
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
|
||||
*/
|
||||
#define FTS5_VOCAB_TERM_EQ 0x01
|
||||
#define FTS5_VOCAB_TERM_GE 0x02
|
||||
#define FTS5_VOCAB_TERM_LE 0x04
|
||||
#define FTS5_VOCAB_TERM_EQ 0x0100
|
||||
#define FTS5_VOCAB_TERM_GE 0x0200
|
||||
#define FTS5_VOCAB_TERM_LE 0x0400
|
||||
|
||||
#define FTS5_VOCAB_COLUSED_MASK 0xFF
|
||||
|
||||
|
||||
/*
|
||||
@@ -269,11 +272,13 @@ static int fts5VocabBestIndexMethod(
|
||||
int iTermEq = -1;
|
||||
int iTermGe = -1;
|
||||
int iTermLe = -1;
|
||||
int idxNum = 0;
|
||||
int idxNum = (int)pInfo->colUsed;
|
||||
int nArg = 0;
|
||||
|
||||
UNUSED_PARAM(pUnused);
|
||||
|
||||
assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
|
||||
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
if( p->usable==0 ) continue;
|
||||
@@ -365,7 +370,7 @@ static int fts5VocabOpenMethod(
|
||||
if( rc==SQLITE_OK ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}else{
|
||||
@@ -525,9 +530,19 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
switch( pTab->eType ){
|
||||
case FTS5_VOCAB_ROW:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
pCsr->aCnt[0]++;
|
||||
/* Do not bother counting the number of instances if the "cnt"
|
||||
** column is not being read (according to colUsed). */
|
||||
if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
|
||||
while( iPos<nPos ){
|
||||
u32 ii;
|
||||
fts5FastGetVarint32(pPos, iPos, ii);
|
||||
if( ii==1 ){
|
||||
/* New column in the position list */
|
||||
fts5FastGetVarint32(pPos, iPos, ii);
|
||||
}else{
|
||||
/* An instance - increment pCsr->aCnt[] */
|
||||
pCsr->aCnt[0]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pCsr->aDoc[0]++;
|
||||
@@ -625,6 +640,7 @@ static int fts5VocabFilterMethod(
|
||||
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
|
||||
pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
|
||||
|
||||
if( pEq ){
|
||||
zTerm = (const char *)sqlite3_value_text(pEq);
|
||||
|
||||
@@ -377,4 +377,28 @@ do_catchsql_test 12.3.3 {
|
||||
SELECT fts5_collist(t1, 1) FROM t1('one AND two');
|
||||
} {0 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=ascii);
|
||||
INSERT INTO t1 VALUES('a b c'), ('d e f');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_catchsql_test 13.2 {
|
||||
SELECT highlight(t1, 0, '[', ']') FROM t1
|
||||
} {0 {{a b c} {d e f}}}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema SET sql = 'CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=blah)'
|
||||
WHERE name = 't1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 13.4 {
|
||||
SELECT highlight(t1, 0, '[', ']') FROM t1
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -79,7 +79,7 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM t1 WHERE rowid MATCH 'a'
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
} {1 {no query solution}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -380,5 +380,32 @@ do_execsql_test 12.3 {
|
||||
} {ok}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=ascii);
|
||||
INSERT INTO t1 VALUES('a b c'), ('d e f');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 13.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {0 ok}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema SET sql = 'CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=blah)'
|
||||
WHERE name = 't1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
breakpoint
|
||||
do_catchsql_test 13.4 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -535,5 +535,36 @@ do_execsql_test 19.0 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 20.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a);
|
||||
INSERT INTO x1(rowid, a) VALUES
|
||||
(1, 'a b c d'),
|
||||
(2, 'x b c d'),
|
||||
(3, 'x y z d'),
|
||||
(4, 'a y c x');
|
||||
}
|
||||
|
||||
do_execsql_test 20.1 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' AND x1 MATCH 'b';
|
||||
} {1}
|
||||
|
||||
do_execsql_test 20.2 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' AND x1 MATCH 'y';
|
||||
} {4}
|
||||
|
||||
do_execsql_test 20.3 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' OR x1 MATCH 'y';
|
||||
} {1 4 3}
|
||||
|
||||
do_execsql_test 20.4 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' OR (x1 MATCH 'y' AND x1 MATCH 'd');
|
||||
} {1 4 3}
|
||||
|
||||
do_execsql_test 20.5 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'z' OR (x1 MATCH 'a' AND x1 MATCH 'd');
|
||||
} {3 1}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -42,6 +42,22 @@ do_execsql_test 1.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE xyz USING fts5 (
|
||||
name,
|
||||
content=''
|
||||
);
|
||||
|
||||
INSERT INTO xyz(xyz, rank) VALUES('secure-delete', 1);
|
||||
INSERT INTO xyz (rowid, name) VALUES(1, 'A');
|
||||
INSERT INTO xyz (rowid, name) VALUES(2, 'A');
|
||||
INSERT INTO xyz(xyz, rowid, name) VALUES('delete', 2, 'A');
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
pragma quick_check;
|
||||
} {ok}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -300,5 +300,75 @@ set ::flags [list]
|
||||
do_execsql_test 9.5.1 { SELECT * FROM t1('"abc xyz*"'); } {}
|
||||
do_test 9.5.2 { set ::flags } {query}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 10.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x, tokenize=unicode61);
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema
|
||||
SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(x, tokenize="unicode61 error");'
|
||||
WHERE name = 'x1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 10.2 {
|
||||
SELECT * FROM x1('abc');
|
||||
} {1 {error in tokenizer constructor}}
|
||||
|
||||
do_catchsql_test 10.3 {
|
||||
INSERT INTO x1 VALUES('abc');
|
||||
} {1 {error in tokenizer constructor}}
|
||||
|
||||
do_execsql_test 10.4 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema
|
||||
SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(x, tokenize="nosuch error");'
|
||||
WHERE name = 'x1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 10.5 {
|
||||
SELECT * FROM x1('abc');
|
||||
} {1 {no such tokenizer: nosuch}}
|
||||
do_catchsql_test 10.6 {
|
||||
INSERT INTO x1 VALUES('abc');
|
||||
} {1 {no such tokenizer: nosuch}}
|
||||
|
||||
do_execsql_test 10.7 {
|
||||
DROP TABLE x1;
|
||||
SELECT * FROM sqlite_schema;
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 10.8 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x, tokenize=unicode61);
|
||||
INSERT INTO x1 VALUES('a b c'), ('d e f'), ('a b c');
|
||||
CREATE VIRTUAL TABLE x1v USING fts5vocab(x1, row);
|
||||
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema
|
||||
SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(x, tokenize=simplify);'
|
||||
WHERE name = 'x1';
|
||||
}
|
||||
|
||||
do_execsql_test 10.9 {
|
||||
SELECT * FROM x1v
|
||||
} {
|
||||
a 2 2 b 2 2 c 2 2 d 1 1 e 1 1 f 1 1
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_execsql_test 10.10 {
|
||||
SELECT * FROM x1v
|
||||
} {
|
||||
a 2 2 b 2 2 c 2 2 d 1 1 e 1 1 f 1 1
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -101,9 +101,20 @@ do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts5(z, tokenize=trigram);
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 4.1 {
|
||||
INSERT INTO t4 VALUES('ABCD');
|
||||
INSERT INTO t4 VALUES('DEFG');
|
||||
} {}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_eqp_test 4.1 {
|
||||
SELECT rowid FROM t4 WHERE z LIKE '%abc%'
|
||||
} {VIRTUAL TABLE INDEX 0:L0}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
SELECT rowid FROM t4 WHERE z LIKE '%abc%'
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -499,7 +499,7 @@ static void icuLoadCollation(
|
||||
{ "QUARTERNARY", UCOL_QUATERNARY },
|
||||
{ "IDENTICAL", UCOL_IDENTICAL },
|
||||
};
|
||||
int i;
|
||||
unsigned int i;
|
||||
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
|
||||
if( sqlite3_stricmp(zOption,aStrength[i].zName)==0 ){
|
||||
ucol_setStrength(pUCollator, aStrength[i].val);
|
||||
|
||||
@@ -92,8 +92,9 @@ static int testIntckCmd(
|
||||
|
||||
case 3: assert( 0==strcmp("error", aCmd[iIdx].zName) ); {
|
||||
const char *zErr = 0;
|
||||
Tcl_Obj *pRes;
|
||||
rc = sqlite3_intck_error(p->intck, 0);
|
||||
Tcl_Obj *pRes = Tcl_NewObj();
|
||||
pRes = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(
|
||||
interp, pRes, Tcl_NewStringObj(sqlite3ErrName(rc), -1)
|
||||
);
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ static void uncompressFunc(
|
||||
unsigned int nIn;
|
||||
unsigned long int nOut;
|
||||
int rc;
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
pIn = sqlite3_value_blob(argv[0]);
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
|
||||
+16
-8
@@ -372,7 +372,9 @@ static int writeFile(
|
||||
#if !defined(_WIN32) && !defined(WIN32)
|
||||
if( S_ISLNK(mode) ){
|
||||
const char *zTo = (const char*)sqlite3_value_text(pData);
|
||||
if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
|
||||
if( zTo==0 ) return 1;
|
||||
unlink(zFile);
|
||||
if( symlink(zTo, zFile)<0 ) return 1;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
@@ -458,13 +460,19 @@ static int writeFile(
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
/* Legacy unix */
|
||||
struct timeval times[2];
|
||||
times[0].tv_usec = times[1].tv_usec = 0;
|
||||
times[0].tv_sec = time(0);
|
||||
times[1].tv_sec = mtime;
|
||||
if( utimes(zFile, times) ){
|
||||
return 1;
|
||||
/* Legacy unix.
|
||||
**
|
||||
** Do not use utimes() on a symbolic link - it sees through the link and
|
||||
** modifies the timestamps on the target. Or fails if the target does
|
||||
** not exist. */
|
||||
if( 0==S_ISLNK(mode) ){
|
||||
struct timeval times[2];
|
||||
times[0].tv_usec = times[1].tv_usec = 0;
|
||||
times[0].tv_sec = time(0);
|
||||
times[1].tv_sec = mtime;
|
||||
if( utimes(zFile, times) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+77
-25
@@ -376,13 +376,13 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
|
||||
** parameter. (idxStr is not used in this implementation.) idxNum
|
||||
** is a bitmask showing which constraints are available:
|
||||
**
|
||||
** 1: start=VALUE
|
||||
** 2: stop=VALUE
|
||||
** 4: step=VALUE
|
||||
**
|
||||
** Also, if bit 8 is set, that means that the series should be output
|
||||
** in descending order rather than in ascending order. If bit 16 is
|
||||
** set, then output must appear in ascending order.
|
||||
** 0x01: start=VALUE
|
||||
** 0x02: stop=VALUE
|
||||
** 0x04: step=VALUE
|
||||
** 0x08: descending order
|
||||
** 0x10: ascending order
|
||||
** 0x20: LIMIT VALUE
|
||||
** 0x40: OFFSET VALUE
|
||||
**
|
||||
** This routine should initialize the cursor and position it so that it
|
||||
** is pointing at the first row, or pointing off the end of the table
|
||||
@@ -396,26 +396,44 @@ static int seriesFilter(
|
||||
series_cursor *pCur = (series_cursor *)pVtabCursor;
|
||||
int i = 0;
|
||||
(void)idxStrUnused;
|
||||
if( idxNum & 1 ){
|
||||
if( idxNum & 0x01 ){
|
||||
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
|
||||
}else{
|
||||
pCur->ss.iBase = 0;
|
||||
}
|
||||
if( idxNum & 2 ){
|
||||
if( idxNum & 0x02 ){
|
||||
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
|
||||
}else{
|
||||
pCur->ss.iTerm = 0xffffffff;
|
||||
}
|
||||
if( idxNum & 4 ){
|
||||
if( idxNum & 0x04 ){
|
||||
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
|
||||
if( pCur->ss.iStep==0 ){
|
||||
pCur->ss.iStep = 1;
|
||||
}else if( pCur->ss.iStep<0 ){
|
||||
if( (idxNum & 16)==0 ) idxNum |= 8;
|
||||
if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
|
||||
}
|
||||
}else{
|
||||
pCur->ss.iStep = 1;
|
||||
}
|
||||
if( idxNum & 0x20 ){
|
||||
sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
|
||||
sqlite3_int64 iTerm;
|
||||
if( idxNum & 0x40 ){
|
||||
sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
|
||||
if( iOffset>0 ){
|
||||
pCur->ss.iBase += pCur->ss.iStep*iOffset;
|
||||
}
|
||||
}
|
||||
if( iLimit>=0 ){
|
||||
iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
|
||||
if( pCur->ss.iStep<0 ){
|
||||
if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
|
||||
}else{
|
||||
if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<argc; i++){
|
||||
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
|
||||
/* If any of the constraints have a NULL value, then return no rows.
|
||||
@@ -426,7 +444,7 @@ static int seriesFilter(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( idxNum & 8 ){
|
||||
if( idxNum & 0x08 ){
|
||||
pCur->ss.isReversing = pCur->ss.iStep > 0;
|
||||
}else{
|
||||
pCur->ss.isReversing = pCur->ss.iStep < 0;
|
||||
@@ -446,10 +464,13 @@ static int seriesFilter(
|
||||
**
|
||||
** The query plan is represented by bits in idxNum:
|
||||
**
|
||||
** (1) start = $value -- constraint exists
|
||||
** (2) stop = $value -- constraint exists
|
||||
** (4) step = $value -- constraint exists
|
||||
** (8) output in descending order
|
||||
** 0x01 start = $value -- constraint exists
|
||||
** 0x02 stop = $value -- constraint exists
|
||||
** 0x04 step = $value -- constraint exists
|
||||
** 0x08 output is in descending order
|
||||
** 0x10 output is in ascending order
|
||||
** 0x20 LIMIT $value -- constraint exists
|
||||
** 0x40 OFFSET $value -- constraint exists
|
||||
*/
|
||||
static int seriesBestIndex(
|
||||
sqlite3_vtab *pVTab,
|
||||
@@ -457,10 +478,12 @@ static int seriesBestIndex(
|
||||
){
|
||||
int i, j; /* Loop over constraints */
|
||||
int idxNum = 0; /* The query plan bitmask */
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
int bStartSeen = 0; /* EQ constraint seen on the START column */
|
||||
#endif
|
||||
int unusableMask = 0; /* Mask of unusable constraints */
|
||||
int nArg = 0; /* Number of arguments that seriesFilter() expects */
|
||||
int aIdx[3]; /* Constraints on start, stop, and step */
|
||||
int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
|
||||
/* This implementation assumes that the start, stop, and step columns
|
||||
@@ -468,28 +491,54 @@ static int seriesBestIndex(
|
||||
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
|
||||
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
|
||||
|
||||
aIdx[0] = aIdx[1] = aIdx[2] = -1;
|
||||
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
int iCol; /* 0 for start, 1 for stop, 2 for step */
|
||||
int iMask; /* bitmask for those column */
|
||||
int op = pConstraint->op;
|
||||
if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
|
||||
&& op<=SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
){
|
||||
if( pConstraint->usable==0 ){
|
||||
/* do nothing */
|
||||
}else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
|
||||
aIdx[3] = i;
|
||||
idxNum |= 0x20;
|
||||
}else{
|
||||
assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
|
||||
aIdx[4] = i;
|
||||
idxNum |= 0x40;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
|
||||
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
|
||||
assert( iCol>=0 && iCol<=2 );
|
||||
iMask = 1 << iCol;
|
||||
if( iCol==0 ) bStartSeen = 1;
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
bStartSeen = 1;
|
||||
}
|
||||
#endif
|
||||
if( pConstraint->usable==0 ){
|
||||
unusableMask |= iMask;
|
||||
continue;
|
||||
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
}else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
idxNum |= iMask;
|
||||
aIdx[iCol] = i;
|
||||
}
|
||||
}
|
||||
for(i=0; i<3; i++){
|
||||
if( aIdx[3]==0 ){
|
||||
/* Ignore OFFSET if LIMIT is omitted */
|
||||
idxNum &= ~0x60;
|
||||
aIdx[4] = 0;
|
||||
}
|
||||
for(i=0; i<5; i++){
|
||||
if( (j = aIdx[i])>=0 ){
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
|
||||
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
pIdxInfo->aConstraintUsage[j].omit =
|
||||
!SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
|
||||
}
|
||||
}
|
||||
/* The current generate_column() implementation requires at least one
|
||||
@@ -510,19 +559,22 @@ static int seriesBestIndex(
|
||||
** this plan is unusable */
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
if( (idxNum & 3)==3 ){
|
||||
if( (idxNum & 0x03)==0x03 ){
|
||||
/* Both start= and stop= boundaries are available. This is the
|
||||
** the preferred case */
|
||||
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
|
||||
pIdxInfo->estimatedRows = 1000;
|
||||
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
|
||||
if( pIdxInfo->aOrderBy[0].desc ){
|
||||
idxNum |= 8;
|
||||
idxNum |= 0x08;
|
||||
}else{
|
||||
idxNum |= 16;
|
||||
idxNum |= 0x10;
|
||||
}
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
}else if( (idxNum & 0x21)==0x21 ){
|
||||
/* We have start= and LIMIT */
|
||||
pIdxInfo->estimatedRows = 2500;
|
||||
}else{
|
||||
/* If either boundary is missing, we have to generate a huge span
|
||||
** of numbers. Make this case very expensive so that the query
|
||||
|
||||
+4
-3
@@ -81,7 +81,7 @@ static void sqlarUncompressFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
uLong nData;
|
||||
uLongf sz;
|
||||
sqlite3_int64 sz;
|
||||
|
||||
assert( argc==2 );
|
||||
sz = sqlite3_value_int(argv[1]);
|
||||
@@ -89,14 +89,15 @@ static void sqlarUncompressFunc(
|
||||
if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
|
||||
sqlite3_result_value(context, argv[0]);
|
||||
}else{
|
||||
uLongf szf = sz;
|
||||
const Bytef *pData= sqlite3_value_blob(argv[0]);
|
||||
Bytef *pOut = sqlite3_malloc(sz);
|
||||
if( pOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
|
||||
}else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
|
||||
sqlite3_result_error(context, "error in uncompress()", -1);
|
||||
}else{
|
||||
sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
|
||||
sqlite3_result_blob(context, pOut, szf, SQLITE_TRANSIENT);
|
||||
}
|
||||
sqlite3_free(pOut);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
** 2024-05-24
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** An SQL function that return pseudo-random non-negative integers.
|
||||
**
|
||||
** SELECT stmtrand(123);
|
||||
**
|
||||
** A special feature of this function is that the same sequence of random
|
||||
** integers is returned for each invocation of the statement. This makes
|
||||
** the results repeatable, and hence useful for testing. The argument is
|
||||
** an integer which is the seed for the random number sequence. The seed
|
||||
** is used by the first invocation of this function only and is ignored
|
||||
** for all subsequent calls within the same statement.
|
||||
**
|
||||
** Resetting a statement (sqlite3_reset()) also resets the random number
|
||||
** sequence.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* State of the pseudo-random number generator */
|
||||
typedef struct Stmtrand {
|
||||
unsigned int x, y;
|
||||
} Stmtrand;
|
||||
|
||||
/* auxdata key */
|
||||
#define STMTRAND_KEY (-4418371)
|
||||
|
||||
/*
|
||||
** Function: stmtrand(SEED)
|
||||
**
|
||||
** Return a pseudo-random number.
|
||||
*/
|
||||
static void stmtrandFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
Stmtrand *p;
|
||||
|
||||
p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
|
||||
if( p==0 ){
|
||||
unsigned int seed;
|
||||
p = sqlite3_malloc( sizeof(*p) );
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
if( argc>=1 ){
|
||||
seed = (unsigned int)sqlite3_value_int(argv[0]);
|
||||
}else{
|
||||
seed = 0;
|
||||
}
|
||||
p->x = seed | 1;
|
||||
p->y = seed;
|
||||
sqlite3_set_auxdata(context, STMTRAND_KEY, p, sqlite3_free);
|
||||
p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
|
||||
p->y = p->y*1103515245 + 12345;
|
||||
sqlite3_result_int(context, (int)((p->x ^ p->y)&0x7fffffff));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_stmtrand_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "stmtrand", 1, SQLITE_UTF8, 0,
|
||||
stmtrandFunc, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
|
||||
stmtrandFunc, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
+3
-1
@@ -29,7 +29,9 @@ SQLITE_EXTENSION_INIT1
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#ifndef SQLITE_NO_STDINT
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
+143
-81
@@ -88,6 +88,15 @@ typedef unsigned int u32;
|
||||
|
||||
typedef struct DbdataTable DbdataTable;
|
||||
typedef struct DbdataCursor DbdataCursor;
|
||||
typedef struct DbdataBuffer DbdataBuffer;
|
||||
|
||||
/*
|
||||
** Buffer type.
|
||||
*/
|
||||
struct DbdataBuffer {
|
||||
u8 *aBuf;
|
||||
sqlite3_int64 nBuf;
|
||||
};
|
||||
|
||||
/* Cursor object */
|
||||
struct DbdataCursor {
|
||||
@@ -104,7 +113,7 @@ struct DbdataCursor {
|
||||
sqlite3_int64 iRowid;
|
||||
|
||||
/* Only for the sqlite_dbdata table */
|
||||
u8 *pRec; /* Buffer containing current record */
|
||||
DbdataBuffer rec;
|
||||
sqlite3_int64 nRec; /* Size of pRec[] in bytes */
|
||||
sqlite3_int64 nHdr; /* Size of header in bytes */
|
||||
int iField; /* Current field number */
|
||||
@@ -149,6 +158,31 @@ struct DbdataTable {
|
||||
" schema TEXT HIDDEN" \
|
||||
")"
|
||||
|
||||
/*
|
||||
** Ensure the buffer passed as the first argument is at least nMin bytes
|
||||
** in size. If an error occurs while attempting to resize the buffer,
|
||||
** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
|
||||
*/
|
||||
static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
|
||||
if( nMin>pBuf->nBuf ){
|
||||
sqlite3_int64 nNew = nMin+16384;
|
||||
u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
|
||||
|
||||
if( aNew==0 ) return SQLITE_NOMEM;
|
||||
pBuf->aBuf = aNew;
|
||||
pBuf->nBuf = nNew;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Release the allocation managed by buffer pBuf.
|
||||
*/
|
||||
static void dbdataBufferFree(DbdataBuffer *pBuf){
|
||||
sqlite3_free(pBuf->aBuf);
|
||||
memset(pBuf, 0, sizeof(*pBuf));
|
||||
}
|
||||
|
||||
/*
|
||||
** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
|
||||
** table.
|
||||
@@ -289,9 +323,9 @@ static void dbdataResetCursor(DbdataCursor *pCsr){
|
||||
pCsr->iField = 0;
|
||||
pCsr->bOnePage = 0;
|
||||
sqlite3_free(pCsr->aPage);
|
||||
sqlite3_free(pCsr->pRec);
|
||||
pCsr->pRec = 0;
|
||||
dbdataBufferFree(&pCsr->rec);
|
||||
pCsr->aPage = 0;
|
||||
pCsr->nRec = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -433,67 +467,88 @@ static void dbdataValue(
|
||||
u8 *pData,
|
||||
sqlite3_int64 nData
|
||||
){
|
||||
if( eType>=0 && dbdataValueBytes(eType)<=nData ){
|
||||
switch( eType ){
|
||||
case 0:
|
||||
case 10:
|
||||
case 11:
|
||||
sqlite3_result_null(pCtx);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
sqlite3_result_int(pCtx, 0);
|
||||
break;
|
||||
case 9:
|
||||
sqlite3_result_int(pCtx, 1);
|
||||
break;
|
||||
|
||||
case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
|
||||
sqlite3_uint64 v = (signed char)pData[0];
|
||||
pData++;
|
||||
switch( eType ){
|
||||
case 7:
|
||||
case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
|
||||
case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
|
||||
case 4: v = (v<<8) + pData[0]; pData++;
|
||||
case 3: v = (v<<8) + pData[0]; pData++;
|
||||
case 2: v = (v<<8) + pData[0]; pData++;
|
||||
}
|
||||
|
||||
if( eType==7 ){
|
||||
double r;
|
||||
memcpy(&r, &v, sizeof(r));
|
||||
sqlite3_result_double(pCtx, r);
|
||||
}else{
|
||||
sqlite3_result_int64(pCtx, (sqlite3_int64)v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
int n = ((eType-12) / 2);
|
||||
if( eType % 2 ){
|
||||
switch( enc ){
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
case SQLITE_UTF16BE:
|
||||
sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
case SQLITE_UTF16LE:
|
||||
sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
if( eType>=0 ){
|
||||
if( dbdataValueBytes(eType)<=nData ){
|
||||
switch( eType ){
|
||||
case 0:
|
||||
case 10:
|
||||
case 11:
|
||||
sqlite3_result_null(pCtx);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
sqlite3_result_int(pCtx, 0);
|
||||
break;
|
||||
case 9:
|
||||
sqlite3_result_int(pCtx, 1);
|
||||
break;
|
||||
|
||||
case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
|
||||
sqlite3_uint64 v = (signed char)pData[0];
|
||||
pData++;
|
||||
switch( eType ){
|
||||
case 7:
|
||||
case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
|
||||
case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
|
||||
case 4: v = (v<<8) + pData[0]; pData++;
|
||||
case 3: v = (v<<8) + pData[0]; pData++;
|
||||
case 2: v = (v<<8) + pData[0]; pData++;
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
|
||||
|
||||
if( eType==7 ){
|
||||
double r;
|
||||
memcpy(&r, &v, sizeof(r));
|
||||
sqlite3_result_double(pCtx, r);
|
||||
}else{
|
||||
sqlite3_result_int64(pCtx, (sqlite3_int64)v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
int n = ((eType-12) / 2);
|
||||
if( eType % 2 ){
|
||||
switch( enc ){
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
case SQLITE_UTF16BE:
|
||||
sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
case SQLITE_UTF16LE:
|
||||
sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( eType==7 ){
|
||||
sqlite3_result_double(pCtx, 0.0);
|
||||
}else if( eType<7 ){
|
||||
sqlite3_result_int(pCtx, 0);
|
||||
}else if( eType%2 ){
|
||||
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
|
||||
}else{
|
||||
sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
|
||||
** a page-size, it returns the maximum number of cells that may be present
|
||||
** on the page. */
|
||||
#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
|
||||
|
||||
/* Maximum number of fields that may appear in a single record. This is
|
||||
** the "hard-limit", according to comments in sqliteLimit.h. */
|
||||
#define DBDATA_MX_FIELD 32676
|
||||
|
||||
/*
|
||||
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
|
||||
*/
|
||||
@@ -522,6 +577,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
assert( iOff+3+2<=pCsr->nPage );
|
||||
pCsr->iCell = pTab->bPtr ? -2 : 0;
|
||||
pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
|
||||
if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
|
||||
pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
|
||||
}
|
||||
}
|
||||
|
||||
if( pTab->bPtr ){
|
||||
@@ -539,7 +597,8 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
}else{
|
||||
/* If there is no record loaded, load it now. */
|
||||
if( pCsr->pRec==0 ){
|
||||
assert( pCsr->rec.aBuf!=0 || pCsr->nRec==0 );
|
||||
if( pCsr->nRec==0 ){
|
||||
int bHasRowid = 0;
|
||||
int nPointer = 0;
|
||||
sqlite3_int64 nPayload = 0;
|
||||
@@ -566,23 +625,24 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
if( pCsr->iCell>=pCsr->nCell ){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
|
||||
|
||||
iOff += 8 + nPointer + pCsr->iCell*2;
|
||||
if( iOff>pCsr->nPage ){
|
||||
if( iCellPtr>pCsr->nPage ){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
iOff = get_uint16(&pCsr->aPage[iOff]);
|
||||
iOff = get_uint16(&pCsr->aPage[iCellPtr]);
|
||||
}
|
||||
|
||||
/* For an interior node cell, skip past the child-page number */
|
||||
iOff += nPointer;
|
||||
|
||||
/* Load the "byte of payload including overflow" field */
|
||||
if( bNextPage || iOff>pCsr->nPage ){
|
||||
if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
|
||||
if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
|
||||
if( nPayload==0 ) nPayload = 1;
|
||||
}
|
||||
|
||||
/* If this is a leaf intkey cell, load the rowid */
|
||||
@@ -617,13 +677,12 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
/* Allocate space for payload. And a bit more to catch small buffer
|
||||
** overruns caused by attempting to read a varint or similar from
|
||||
** near the end of a corrupt record. */
|
||||
pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
|
||||
if( pCsr->pRec==0 ) return SQLITE_NOMEM;
|
||||
memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
|
||||
pCsr->nRec = nPayload;
|
||||
rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
assert( nPayload!=0 );
|
||||
|
||||
/* Load the nLocal bytes of payload */
|
||||
memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
|
||||
memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
|
||||
iOff += nLocal;
|
||||
|
||||
/* Load content from overflow pages */
|
||||
@@ -641,19 +700,22 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
nCopy = U-4;
|
||||
if( nCopy>nRem ) nCopy = nRem;
|
||||
memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
|
||||
memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
|
||||
nRem -= nCopy;
|
||||
|
||||
pgnoOvfl = get_uint32(aOvfl);
|
||||
sqlite3_free(aOvfl);
|
||||
}
|
||||
nPayload -= nRem;
|
||||
}
|
||||
memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
|
||||
pCsr->nRec = nPayload;
|
||||
|
||||
iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
|
||||
iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
|
||||
if( nHdr>nPayload ) nHdr = 0;
|
||||
pCsr->nHdr = nHdr;
|
||||
pCsr->pHdrPtr = &pCsr->pRec[iHdr];
|
||||
pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
|
||||
pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
|
||||
pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
|
||||
pCsr->iField = (bHasRowid ? -1 : 0);
|
||||
}
|
||||
}
|
||||
@@ -661,14 +723,16 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
pCsr->iField++;
|
||||
if( pCsr->iField>0 ){
|
||||
sqlite3_int64 iType;
|
||||
if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
|
||||
if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec]
|
||||
|| pCsr->iField>=DBDATA_MX_FIELD
|
||||
){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
int szField = 0;
|
||||
pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
|
||||
szField = dbdataValueBytes(iType);
|
||||
if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
|
||||
pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
|
||||
if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
|
||||
pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
|
||||
}else{
|
||||
pCsr->pPtr += szField;
|
||||
}
|
||||
@@ -678,20 +742,18 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
if( bNextPage ){
|
||||
sqlite3_free(pCsr->aPage);
|
||||
sqlite3_free(pCsr->pRec);
|
||||
pCsr->aPage = 0;
|
||||
pCsr->pRec = 0;
|
||||
pCsr->nRec = 0;
|
||||
if( pCsr->bOnePage ) return SQLITE_OK;
|
||||
pCsr->iPgno++;
|
||||
}else{
|
||||
if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
|
||||
if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Advance to the next cell. The next iteration of the loop will load
|
||||
** the record and so on. */
|
||||
sqlite3_free(pCsr->pRec);
|
||||
pCsr->pRec = 0;
|
||||
pCsr->nRec = 0;
|
||||
pCsr->iCell++;
|
||||
}
|
||||
}
|
||||
@@ -881,12 +943,12 @@ static int dbdataColumn(
|
||||
case DBDATA_COLUMN_VALUE: {
|
||||
if( pCsr->iField<0 ){
|
||||
sqlite3_result_int64(ctx, pCsr->iIntkey);
|
||||
}else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
|
||||
}else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
|
||||
sqlite3_int64 iType;
|
||||
dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
|
||||
dbdataValue(
|
||||
ctx, pCsr->enc, iType, pCsr->pPtr,
|
||||
&pCsr->pRec[pCsr->nRec] - pCsr->pPtr
|
||||
&pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -342,7 +342,7 @@ foreach enc {utf8 utf16 utf16le utf16be} {
|
||||
DELETE FROM sqlite_schema WHERE name='t1';
|
||||
}
|
||||
|
||||
proc my_sql_hook {sql} {
|
||||
proc my_sql_hook2 {sql} {
|
||||
if {[string match "INSERT INTO lostandfound*" $sql]} {
|
||||
lappend ::script $sql
|
||||
}
|
||||
@@ -350,7 +350,7 @@ foreach enc {utf8 utf16 utf16le utf16be} {
|
||||
}
|
||||
do_test 18.$enc.2 {
|
||||
set ::script [list]
|
||||
set R [sqlite3_recover_init_sql db main my_sql_hook]
|
||||
set R [sqlite3_recover_init_sql db main my_sql_hook2]
|
||||
$R config lostandfound lostandfound
|
||||
$R run
|
||||
$R finish
|
||||
@@ -358,7 +358,18 @@ foreach enc {utf8 utf16 utf16le utf16be} {
|
||||
} {{INSERT INTO lostandfound VALUES(2, 2, 2, 1, 'abc', 'def')}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 19.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
|
||||
ALTER TABLE t1 ADD COLUMN c NOT NULL DEFAULT 13;
|
||||
INSERT INTO t1 VALUES(3, 'three', 'hello world');
|
||||
}
|
||||
|
||||
do_recover_test 19.1
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -524,5 +524,33 @@ do_test 7.1 {
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {1 {file is not a database}}
|
||||
|
||||
reset_db
|
||||
breakpoint
|
||||
do_test 8.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 8192 pagesize 4096 filename db.sqlite
|
||||
| page 1 offset 0
|
||||
| 0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00 ...vte format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
|
||||
| 96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00 ..v.............
|
||||
| 4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19 ...........3....
|
||||
| 4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61 ..CtableTable0Ta
|
||||
| 4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c ble0.CREATE TABL
|
||||
| 4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29 E Table0 (Col0 )
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| end db.sqlite
|
||||
}]} {}
|
||||
|
||||
do_test 8.1 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
catch { $R run }
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,549 @@
|
||||
# 2024 May 1
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] recover_common.tcl]
|
||||
set testprefix recovercorrupt3
|
||||
|
||||
#| 0: d5 d5 9b d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 ................
|
||||
#| 16: 04 00 00 00 1d 00 00 00 00 00 00 00 5f 5f 5f 5f ............____
|
||||
#| 32: 5f 5f 5f 5f 5f 5f 5f 5f 71 5f 5f 5f 02 02 02 02 ________q___....
|
||||
#| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
#| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
#| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
#| 96: 02 02 02 02
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 1.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 3821 pagesize 1024 filename clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
|
||||
| 96: 00 2e 7a 70 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 a0 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 29 29 ..............))
|
||||
| 464: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 480: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 496: 29 29 29 dd dd dd dd dd dd dd dd dd dd dd dd dd ))).............
|
||||
| 512: dd dd dd dd dd dd dd dd dd 6e 69 d2 e9 e9 e9 d2 .........ni.....
|
||||
| 528: d2 d2 d2 d2 dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 544: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 560: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 576: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 592: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 608: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 624: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 640: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 656: dd dd dd dd dd dd dd da dd dd dd dd dd dd dd dd ................
|
||||
| 672: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 688: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 704: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 720: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 736: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 752: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 768: dd dd dd dd dd dd dd dd dd dd dd dd dd 29 29 29 .............)))
|
||||
| 784: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 800: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 816: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 832: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 848: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 864: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 880: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 896: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 912: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 928: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 944: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 960: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 976: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 992: 29 29 29 29 29 29 29 29 29 29 dd dd dd dd dd dd ))))))))))......
|
||||
| 1008: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| page 2 offset 1024
|
||||
| 0: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 16: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 32: dd dd 6e 69 d2 e9 e9 e9 d2 d2 d2 d2 d2 dd dd dd ..ni............
|
||||
| 48: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 64: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 80: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 96: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 112: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 128: dd dd dd dd dd dd 29 29 29 29 29 29 29 29 29 29 ......))))))))))
|
||||
| 144: 29 29 29 29 29 29 29 29 29 ad a5 29 29 29 29 00 )))))))))..)))).
|
||||
| 160: 75 9c 11 00 5b e5 64 28 7c ca 09 69 28 2d 69 00 u...[.d(|..i(-i.
|
||||
| 176: 85 88 6c 81 48 83 a0 93 c0 c0 82 8b 81 84 85 f9 ..l.H...........
|
||||
| 192: 88 7a 00 7f 00 96 40 7b 12 4b 84 75 a0 00 99 a0 .z....@..K.u....
|
||||
| 208: df a0 7e 81 c6 90 8f 7f 84 85 cc 84 82 90 88 60 ..~............`
|
||||
| 224: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 240: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 256: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 272: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 288: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 832: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 848: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 864: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 880: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 896: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 912: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 928: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 944: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 960: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| page 3 offset 2048
|
||||
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 832: 02 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 848: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 864: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 880: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 896: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 912: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 928: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 944: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 960: 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| page 4 offset 3072
|
||||
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 736: 5f 5f 5f 5f 5f 5f 5f 00 d5 fe fe fe 08 00 00 00 _______.........
|
||||
| end clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
|
||||
}]} {}
|
||||
|
||||
sqlite3_dbdata_init db
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA writable_schema = 1;
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R run
|
||||
$R finish
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 2.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 3821 pagesize 1024 filename clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 04 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
|
||||
| 96: 00 2e 7a 70 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 a0 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 29 29 ..............))
|
||||
| 464: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 480: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 496: 29 29 29 dd dd dd dd dd dd dd dd dd dd dd dd dd ))).............
|
||||
| 512: dd dd dd dd dd dd dd dd dd 6e 69 d2 e9 e9 e9 d2 .........ni.....
|
||||
| 528: d2 d2 d2 d2 dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 544: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 560: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 576: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 592: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 608: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 624: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 640: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 656: dd dd dd dd dd dd dd da dd dd dd dd dd dd dd dd ................
|
||||
| 672: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 688: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 704: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 720: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 736: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 752: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 768: dd dd dd dd dd dd dd dd dd dd dd dd dd 29 29 29 .............)))
|
||||
| 784: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 800: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 816: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 832: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 848: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 864: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 880: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 896: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 912: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 928: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 944: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 960: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 976: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
|
||||
| 992: 29 29 29 29 29 29 29 29 29 29 dd dd dd dd dd dd ))))))))))......
|
||||
| 1008: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| page 2 offset 1024
|
||||
| 0: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 16: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 32: dd dd 6e 69 d2 e9 e9 e9 d2 d2 d2 d2 d2 dd dd dd ..ni............
|
||||
| 48: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 64: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 80: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 96: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 112: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
|
||||
| 128: dd dd dd dd dd dd 29 29 29 29 29 29 29 29 29 29 ......))))))))))
|
||||
| 144: 29 29 29 29 29 29 29 29 29 ad a5 29 29 29 29 00 )))))))))..)))).
|
||||
| 160: 75 9c 11 00 5b e5 64 28 7c ca 09 69 28 2d 69 00 u...[.d(|..i(-i.
|
||||
| 176: 85 88 6c 81 48 83 a0 93 c0 c0 82 8b 81 84 85 f9 ..l.H...........
|
||||
| 192: 88 7a 00 7f 00 96 40 7b 12 4b 84 75 a0 00 99 a0 .z....@..K.u....
|
||||
| 208: df a0 7e 81 c6 90 8f 7f 84 85 cc 84 82 90 88 60 ..~............`
|
||||
| 224: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 240: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 256: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 272: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 288: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 832: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 848: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 864: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 880: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 896: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 912: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 928: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 944: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 960: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| page 3 offset 2048
|
||||
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 832: 02 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 848: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 864: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 880: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 896: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 912: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 928: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 944: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 960: 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| page 4 offset 3072
|
||||
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 736: 5f 5f 5f 5f 5f 5f 5f 00 d5 fe fe fe 08 00 00 00 _______.........
|
||||
| end clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
|
||||
}]} {}
|
||||
|
||||
sqlite3_dbdata_init db
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA writable_schema = 1;
|
||||
}
|
||||
|
||||
do_test 2.2 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R run
|
||||
$R finish
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# 2024 May 15
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] recover_common.tcl]
|
||||
set testprefix recovercorrupt4
|
||||
|
||||
database_may_be_corrupt
|
||||
|
||||
if {[permutation]!="inmemory_journal"} {
|
||||
# This test cannot be run with the inmemory_journal permutation, as it
|
||||
# must open a truncated, corrupt, database file. With the inmemory_journal
|
||||
# permutation, this fails (SQLITE_CORRUPT error) when the [sqlite3] wrapper
|
||||
# executes "PRAGMA journal_mode = memory".
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE rows(indexed INTEGER NOT NULL, unindexed INTEGER NOT NULL, filler BLOB NOT NULL DEFAULT 13);
|
||||
-- CREATE UNIQUE INDEX rows_index ON rows(indexed);
|
||||
INSERT INTO rows(indexed, unindexed, filler) VALUES(1, 1, x'31');
|
||||
INSERT INTO rows(indexed, unindexed, filler) VALUES(2, 2, x'32');
|
||||
INSERT INTO rows(indexed, unindexed, filler) VALUES(4, 4, x'34');
|
||||
INSERT INTO rows(indexed, unindexed, filler) VALUES(8, 8, randomblob(2048));
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
do_test 1.1 {
|
||||
set sz [expr [file size test.db] - 1024]
|
||||
set fd [open test.db]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
|
||||
set data [read $fd $sz]
|
||||
set fd2 [open test.db2 w]
|
||||
fconfigure $fd2 -encoding binary -translation binary
|
||||
puts -nonewline $fd2 $data
|
||||
close $fd2
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
forcedelete test.db3
|
||||
sqlite3 db test.db2
|
||||
set R [sqlite3_recover_init db main test.db3]
|
||||
$R run
|
||||
$R finish
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
sqlite3 db test.db3
|
||||
execsql {
|
||||
SELECT indexed, unindexed FROM rows
|
||||
}
|
||||
} {1 1 2 2 4 4 8 8}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
if( bTable && !bVirtual ){
|
||||
if( SQLITE_ROW==sqlite3_step(pTblname) ){
|
||||
const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
|
||||
recoverAddTable(p, zTbl, iRoot);
|
||||
if( zTbl ) recoverAddTable(p, zTbl, iRoot);
|
||||
}
|
||||
recoverReset(p, pTblname);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# 2011 March 07
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionchange
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
set C [changeset_from_sql {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(10, 20, 30);
|
||||
}]
|
||||
|
||||
set res [list]
|
||||
set iter [sqlite3changeset_start $C]
|
||||
while {[$iter next]=="SQLITE_ROW"} {
|
||||
lappend res [$iter data]
|
||||
}
|
||||
$iter finalize
|
||||
|
||||
set res
|
||||
} [list \
|
||||
{INSERT t1 0 X.. {} {i 10 i 20 i 30}} \
|
||||
{INSERT t1 0 X.. {} {i 1 i 2 i 3}} \
|
||||
]
|
||||
|
||||
|
||||
do_test 1.2 {
|
||||
sqlite3changegroup grp
|
||||
set iter [sqlite3changeset_start $C]
|
||||
while {[$iter next]=="SQLITE_ROW"} {
|
||||
grp add_change $iter
|
||||
}
|
||||
$iter finalize
|
||||
|
||||
set res [list]
|
||||
grp output
|
||||
sqlite3session_foreach c [grp output] { lappend res $c }
|
||||
grp delete
|
||||
set res
|
||||
} [list \
|
||||
{INSERT t1 0 X.. {} {i 10 i 20 i 30}} \
|
||||
{INSERT t1 0 X.. {} {i 1 i 2 i 3}} \
|
||||
]
|
||||
|
||||
do_test 1.3.1 {
|
||||
set iter [sqlite3changeset_start $C]
|
||||
sqlite3changegroup grp
|
||||
list [catch { grp add_change $iter } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
do_test 1.3.2 {
|
||||
while {[$iter next]=="SQLITE_ROW"} { }
|
||||
list [catch { grp add_change $iter } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
grp delete
|
||||
$iter finalize
|
||||
|
||||
do_test 1.4 {
|
||||
set res [list]
|
||||
set iter [sqlite3changeset_start -invert $C]
|
||||
while {[$iter next]=="SQLITE_ROW"} {
|
||||
lappend res [$iter data]
|
||||
}
|
||||
$iter finalize
|
||||
set res
|
||||
} [list \
|
||||
{DELETE t1 0 X.. {i 10 i 20 i 30} {}} \
|
||||
{DELETE t1 0 X.. {i 1 i 2 i 3} {}} \
|
||||
]
|
||||
|
||||
do_test 1.5 {
|
||||
sqlite3changegroup grp
|
||||
set iter [sqlite3changeset_start -invert $C]
|
||||
$iter next
|
||||
list [catch { grp add_change $iter } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
$iter finalize
|
||||
grp delete
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,76 @@
|
||||
# 2011 March 07
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionconflict
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log log
|
||||
proc log {code msg} { puts "LOG $code $msg" }
|
||||
sqlite3 db test.db
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 1.1 {
|
||||
INSERT INTO t1 VALUES(6, 6, 6);
|
||||
}
|
||||
|
||||
proc xConflict {args} {
|
||||
return "ABORT"
|
||||
}
|
||||
|
||||
|
||||
do_test 1.2 {
|
||||
set chng [changeset_from_sql {
|
||||
UPDATE t1 SET b=10, c=10 WHERE a=1;
|
||||
UPDATE t1 SET b=444 WHERE a=2;
|
||||
INSERT INTO t1 VALUES(4, 4, 4);
|
||||
INSERT INTO t1 VALUES(5, 5, 5);
|
||||
INSERT INTO t1 VALUES(6, 6, 6);
|
||||
}]
|
||||
|
||||
execsql BEGIN db2
|
||||
set res [list [catch { sqlite3changeset_apply db2 $chng xConflict } msg] $msg]
|
||||
execsql ROLLBACK db2
|
||||
set res
|
||||
} {1 SQLITE_ABORT}
|
||||
|
||||
do_execsql_test -db db2 1.3 {
|
||||
SELECT * FROM t1;
|
||||
} {
|
||||
1 1 1
|
||||
2 2 2
|
||||
3 3 3
|
||||
6 6 6
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
+159
-97
@@ -3685,14 +3685,14 @@ static int sessionChangesetNextOne(
|
||||
p->rc = sessionInputBuffer(&p->in, 2);
|
||||
if( p->rc!=SQLITE_OK ) return p->rc;
|
||||
|
||||
sessionDiscardData(&p->in);
|
||||
p->in.iCurrent = p->in.iNext;
|
||||
|
||||
/* If the iterator is already at the end of the changeset, return DONE. */
|
||||
if( p->in.iNext>=p->in.nData ){
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
|
||||
sessionDiscardData(&p->in);
|
||||
p->in.iCurrent = p->in.iNext;
|
||||
|
||||
op = p->in.aData[p->in.iNext++];
|
||||
while( op=='T' || op=='P' ){
|
||||
if( pbNew ) *pbNew = 1;
|
||||
@@ -5427,6 +5427,7 @@ struct sqlite3_changegroup {
|
||||
int rc; /* Error code */
|
||||
int bPatch; /* True to accumulate patchsets */
|
||||
SessionTable *pList; /* List of tables in current patch */
|
||||
SessionBuffer rec;
|
||||
|
||||
sqlite3 *db; /* Configured by changegroup_schema() */
|
||||
char *zDb; /* Configured by changegroup_schema() */
|
||||
@@ -5725,108 +5726,128 @@ static int sessionChangesetExtendRecord(
|
||||
}
|
||||
|
||||
/*
|
||||
** Add all changes in the changeset traversed by the iterator passed as
|
||||
** the first argument to the changegroup hash tables.
|
||||
** Locate or create a SessionTable object that may be used to add the
|
||||
** change currently pointed to by iterator pIter to changegroup pGrp.
|
||||
** If successful, set output variable (*ppTab) to point to the table
|
||||
** object and return SQLITE_OK. Otherwise, if some error occurs, return
|
||||
** an SQLite error code and leave (*ppTab) set to NULL.
|
||||
*/
|
||||
static int sessionChangesetToHash(
|
||||
sqlite3_changeset_iter *pIter, /* Iterator to read from */
|
||||
sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
|
||||
int bRebase /* True if hash table is for rebasing */
|
||||
static int sessionChangesetFindTable(
|
||||
sqlite3_changegroup *pGrp,
|
||||
const char *zTab,
|
||||
sqlite3_changeset_iter *pIter,
|
||||
SessionTable **ppTab
|
||||
){
|
||||
u8 *aRec;
|
||||
int nRec;
|
||||
int rc = SQLITE_OK;
|
||||
SessionTable *pTab = 0;
|
||||
SessionBuffer rec = {0, 0, 0};
|
||||
int nTab = (int)strlen(zTab);
|
||||
u8 *abPK = 0;
|
||||
int nCol = 0;
|
||||
|
||||
while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){
|
||||
const char *zNew;
|
||||
int nCol;
|
||||
int op;
|
||||
int iHash;
|
||||
int bIndirect;
|
||||
SessionChange *pChange;
|
||||
SessionChange *pExist = 0;
|
||||
SessionChange **pp;
|
||||
*ppTab = 0;
|
||||
sqlite3changeset_pk(pIter, &abPK, &nCol);
|
||||
|
||||
/* Ensure that only changesets, or only patchsets, but not a mixture
|
||||
** of both, are being combined. It is an error to try to combine a
|
||||
** changeset and a patchset. */
|
||||
if( pGrp->pList==0 ){
|
||||
pGrp->bPatch = pIter->bPatchset;
|
||||
}else if( pIter->bPatchset!=pGrp->bPatch ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
/* Search the list for an existing table */
|
||||
for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
|
||||
if( 0==sqlite3_strnicmp(pTab->zName, zTab, nTab+1) ) break;
|
||||
}
|
||||
|
||||
/* If one was not found above, create a new table now */
|
||||
if( !pTab ){
|
||||
SessionTable **ppNew;
|
||||
|
||||
pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nTab+1);
|
||||
if( !pTab ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(pTab, 0, sizeof(SessionTable));
|
||||
pTab->nCol = nCol;
|
||||
pTab->abPK = (u8*)&pTab[1];
|
||||
memcpy(pTab->abPK, abPK, nCol);
|
||||
pTab->zName = (char*)&pTab->abPK[nCol];
|
||||
memcpy(pTab->zName, zTab, nTab+1);
|
||||
|
||||
sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect);
|
||||
if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){
|
||||
/* Search the list for a matching table */
|
||||
int nNew = (int)strlen(zNew);
|
||||
u8 *abPK;
|
||||
|
||||
sqlite3changeset_pk(pIter, &abPK, 0);
|
||||
for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
|
||||
if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break;
|
||||
}
|
||||
if( !pTab ){
|
||||
SessionTable **ppTab;
|
||||
|
||||
pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
|
||||
if( !pTab ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
memset(pTab, 0, sizeof(SessionTable));
|
||||
pTab->nCol = nCol;
|
||||
pTab->abPK = (u8*)&pTab[1];
|
||||
memcpy(pTab->abPK, abPK, nCol);
|
||||
pTab->zName = (char*)&pTab->abPK[nCol];
|
||||
memcpy(pTab->zName, zNew, nNew+1);
|
||||
|
||||
if( pGrp->db ){
|
||||
pTab->nCol = 0;
|
||||
rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
|
||||
if( rc ){
|
||||
assert( pTab->azCol==0 );
|
||||
sqlite3_free(pTab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The new object must be linked on to the end of the list, not
|
||||
** simply added to the start of it. This is to ensure that the
|
||||
** tables within the output of sqlite3changegroup_output() are in
|
||||
** the right order. */
|
||||
for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext);
|
||||
*ppTab = pTab;
|
||||
}
|
||||
|
||||
if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
|
||||
rc = SQLITE_SCHEMA;
|
||||
break;
|
||||
if( pGrp->db ){
|
||||
pTab->nCol = 0;
|
||||
rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
|
||||
if( rc ){
|
||||
assert( pTab->azCol==0 );
|
||||
sqlite3_free(pTab);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if( nCol<pTab->nCol ){
|
||||
assert( pGrp->db );
|
||||
rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, &rec);
|
||||
if( rc ) break;
|
||||
aRec = rec.aBuf;
|
||||
nRec = rec.nBuf;
|
||||
}
|
||||
/* The new object must be linked on to the end of the list, not
|
||||
** simply added to the start of it. This is to ensure that the
|
||||
** tables within the output of sqlite3changegroup_output() are in
|
||||
** the right order. */
|
||||
for(ppNew=&pGrp->pList; *ppNew; ppNew=&(*ppNew)->pNext);
|
||||
*ppNew = pTab;
|
||||
}
|
||||
|
||||
if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
/* Check that the table is compatible. */
|
||||
if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
|
||||
rc = SQLITE_SCHEMA;
|
||||
}
|
||||
|
||||
*ppTab = pTab;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add the change currently indicated by iterator pIter to the hash table
|
||||
** belonging to changegroup pGrp.
|
||||
*/
|
||||
static int sessionOneChangeToHash(
|
||||
sqlite3_changegroup *pGrp,
|
||||
sqlite3_changeset_iter *pIter,
|
||||
int bRebase
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nCol = 0;
|
||||
int op = 0;
|
||||
int iHash = 0;
|
||||
int bIndirect = 0;
|
||||
SessionChange *pChange = 0;
|
||||
SessionChange *pExist = 0;
|
||||
SessionChange **pp = 0;
|
||||
SessionTable *pTab = 0;
|
||||
u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
|
||||
int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
|
||||
|
||||
/* Ensure that only changesets, or only patchsets, but not a mixture
|
||||
** of both, are being combined. It is an error to try to combine a
|
||||
** changeset and a patchset. */
|
||||
if( pGrp->pList==0 ){
|
||||
pGrp->bPatch = pIter->bPatchset;
|
||||
}else if( pIter->bPatchset!=pGrp->bPatch ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zTab = 0;
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
|
||||
rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && nCol<pTab->nCol ){
|
||||
SessionBuffer *pBuf = &pGrp->rec;
|
||||
rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, pBuf);
|
||||
aRec = pBuf->aBuf;
|
||||
nRec = pBuf->nBuf;
|
||||
assert( pGrp->db );
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && sessionGrowHash(0, pIter->bPatchset, pTab) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Search for existing entry. If found, remove it from the hash table.
|
||||
** Code below may link it back in. */
|
||||
iHash = sessionChangeHash(
|
||||
pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
|
||||
);
|
||||
|
||||
/* Search for existing entry. If found, remove it from the hash table.
|
||||
** Code below may link it back in.
|
||||
*/
|
||||
for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){
|
||||
int bPkOnly1 = 0;
|
||||
int bPkOnly2 = 0;
|
||||
@@ -5841,19 +5862,41 @@ static int sessionChangesetToHash(
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionChangeMerge(pTab, bRebase,
|
||||
pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
|
||||
);
|
||||
if( rc ) break;
|
||||
if( pChange ){
|
||||
pChange->pNext = pTab->apChange[iHash];
|
||||
pTab->apChange[iHash] = pChange;
|
||||
pTab->nEntry++;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && pChange ){
|
||||
pChange->pNext = pTab->apChange[iHash];
|
||||
pTab->apChange[iHash] = pChange;
|
||||
pTab->nEntry++;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ) rc = pIter->rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add all changes in the changeset traversed by the iterator passed as
|
||||
** the first argument to the changegroup hash tables.
|
||||
*/
|
||||
static int sessionChangesetToHash(
|
||||
sqlite3_changeset_iter *pIter, /* Iterator to read from */
|
||||
sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
|
||||
int bRebase /* True if hash table is for rebasing */
|
||||
){
|
||||
u8 *aRec;
|
||||
int nRec;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
|
||||
rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
|
||||
sqlite3_free(rec.aBuf);
|
||||
if( rc==SQLITE_OK ) rc = pIter->rc;
|
||||
return rc;
|
||||
}
|
||||
@@ -5981,6 +6024,23 @@ int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a single change to a changeset-group.
|
||||
*/
|
||||
int sqlite3changegroup_add_change(
|
||||
sqlite3_changegroup *pGrp,
|
||||
sqlite3_changeset_iter *pIter
|
||||
){
|
||||
if( pIter->in.iCurrent==pIter->in.iNext
|
||||
|| pIter->rc!=SQLITE_OK
|
||||
|| pIter->bInvert
|
||||
){
|
||||
/* Iterator does not point to any valid entry or is an INVERT iterator. */
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
return sessionOneChangeToHash(pGrp, pIter, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Obtain a buffer containing a changeset representing the concatenation
|
||||
** of all changesets added to the group so far.
|
||||
@@ -6030,6 +6090,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
|
||||
if( pGrp ){
|
||||
sqlite3_free(pGrp->zDb);
|
||||
sessionDeleteTable(0, pGrp->pList);
|
||||
sqlite3_free(pGrp->rec.aBuf);
|
||||
sqlite3_free(pGrp);
|
||||
}
|
||||
}
|
||||
@@ -6431,6 +6492,7 @@ int sqlite3rebaser_rebase_strm(
|
||||
void sqlite3rebaser_delete(sqlite3_rebaser *p){
|
||||
if( p ){
|
||||
sessionDeleteTable(0, p->grp.pList);
|
||||
sqlite3_free(p->grp.rec.aBuf);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,6 +1057,30 @@ int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);
|
||||
*/
|
||||
int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add A Single Change To A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
**
|
||||
** This function adds the single change currently indicated by the iterator
|
||||
** passed as the second argument to the changegroup object. The rules for
|
||||
** adding the change are just as described for [sqlite3changegroup_add()].
|
||||
**
|
||||
** If the change is successfully added to the changegroup, SQLITE_OK is
|
||||
** returned. Otherwise, an SQLite error code is returned.
|
||||
**
|
||||
** The iterator must point to a valid entry when this function is called.
|
||||
** If it does not, SQLITE_ERROR is returned and no change is added to the
|
||||
** changegroup. Additionally, the iterator must not have been opened with
|
||||
** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
|
||||
** returned.
|
||||
*/
|
||||
int sqlite3changegroup_add_change(
|
||||
sqlite3_changegroup*,
|
||||
sqlite3_changeset_iter*
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
|
||||
+195
-61
@@ -1038,6 +1038,64 @@ static int SQLITE_TCLAPI test_sqlite3changeset_concat(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Tcl_Obj *testIterData(sqlite3_changeset_iter *pIter){
|
||||
Tcl_Obj *pVar = 0;
|
||||
int nCol; /* Number of columns in table */
|
||||
int nCol2; /* Number of columns in table */
|
||||
int op; /* SQLITE_INSERT, UPDATE or DELETE */
|
||||
const char *zTab; /* Name of table change applies to */
|
||||
Tcl_Obj *pOld; /* Vector of old.* values */
|
||||
Tcl_Obj *pNew; /* Vector of new.* values */
|
||||
int bIndirect;
|
||||
|
||||
char *zPK;
|
||||
unsigned char *abPK;
|
||||
int i;
|
||||
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
|
||||
pVar = Tcl_NewObj();
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
|
||||
op==SQLITE_INSERT ? "INSERT" :
|
||||
op==SQLITE_UPDATE ? "UPDATE" :
|
||||
"DELETE", -1
|
||||
));
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
|
||||
|
||||
zPK = ckalloc(nCol+1);
|
||||
memset(zPK, 0, nCol+1);
|
||||
sqlite3changeset_pk(pIter, &abPK, &nCol2);
|
||||
assert( nCol==nCol2 );
|
||||
for(i=0; i<nCol; i++){
|
||||
zPK[i] = (abPK[i] ? 'X' : '.');
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
|
||||
ckfree(zPK);
|
||||
|
||||
pOld = Tcl_NewObj();
|
||||
if( op!=SQLITE_INSERT ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
test_append_value(pOld, pVal);
|
||||
}
|
||||
}
|
||||
pNew = Tcl_NewObj();
|
||||
if( op!=SQLITE_DELETE ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
test_append_value(pNew, pVal);
|
||||
}
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, pOld);
|
||||
Tcl_ListObjAppendElement(0, pVar, pNew);
|
||||
|
||||
return pVar;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3session_foreach VARNAME CHANGESET SCRIPT
|
||||
*/
|
||||
@@ -1111,67 +1169,8 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach(
|
||||
}
|
||||
|
||||
while( SQLITE_ROW==sqlite3changeset_next(pIter) ){
|
||||
int nCol; /* Number of columns in table */
|
||||
int nCol2; /* Number of columns in table */
|
||||
int op; /* SQLITE_INSERT, UPDATE or DELETE */
|
||||
const char *zTab; /* Name of table change applies to */
|
||||
Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */
|
||||
Tcl_Obj *pOld; /* Vector of old.* values */
|
||||
Tcl_Obj *pNew; /* Vector of new.* values */
|
||||
int bIndirect;
|
||||
|
||||
char *zPK;
|
||||
unsigned char *abPK;
|
||||
int i;
|
||||
|
||||
/* Test that _fk_conflicts() returns SQLITE_MISUSE if called on this
|
||||
** iterator. */
|
||||
int nDummy;
|
||||
if( SQLITE_MISUSE!=sqlite3changeset_fk_conflicts(pIter, &nDummy) ){
|
||||
sqlite3changeset_finalize(pIter);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
|
||||
pVar = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
|
||||
op==SQLITE_INSERT ? "INSERT" :
|
||||
op==SQLITE_UPDATE ? "UPDATE" :
|
||||
"DELETE", -1
|
||||
));
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
|
||||
|
||||
zPK = ckalloc(nCol+1);
|
||||
memset(zPK, 0, nCol+1);
|
||||
sqlite3changeset_pk(pIter, &abPK, &nCol2);
|
||||
assert( nCol==nCol2 );
|
||||
for(i=0; i<nCol; i++){
|
||||
zPK[i] = (abPK[i] ? 'X' : '.');
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
|
||||
ckfree(zPK);
|
||||
|
||||
pOld = Tcl_NewObj();
|
||||
if( op!=SQLITE_INSERT ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
test_append_value(pOld, pVal);
|
||||
}
|
||||
}
|
||||
pNew = Tcl_NewObj();
|
||||
if( op!=SQLITE_DELETE ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
test_append_value(pNew, pVal);
|
||||
}
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, pOld);
|
||||
Tcl_ListObjAppendElement(0, pVar, pNew);
|
||||
|
||||
Tcl_Obj *pVar = 0; /* Tcl value to set $VARNAME to */
|
||||
pVar = testIterData(pIter);
|
||||
Tcl_ObjSetVar2(interp, pVarname, 0, pVar, 0);
|
||||
rc = Tcl_EvalObjEx(interp, pScript, 0);
|
||||
if( rc!=TCL_OK && rc!=TCL_CONTINUE ){
|
||||
@@ -1459,6 +1458,12 @@ struct TestChangegroup {
|
||||
sqlite3_changegroup *pGrp;
|
||||
};
|
||||
|
||||
typedef struct TestChangeIter TestChangeIter;
|
||||
struct TestChangeIter {
|
||||
sqlite3_changeset_iter *pIter;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Destructor for Tcl changegroup command object.
|
||||
*/
|
||||
@@ -1491,6 +1496,7 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
{ "add", 1, "CHANGESET", }, /* 1 */
|
||||
{ "output", 0, "", }, /* 2 */
|
||||
{ "delete", 0, "", }, /* 3 */
|
||||
{ "add_change", 1, "ITERATOR", }, /* 4 */
|
||||
{ 0 }
|
||||
};
|
||||
int rc = TCL_OK;
|
||||
@@ -1542,6 +1548,24 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
break;
|
||||
};
|
||||
|
||||
case 4: { /* add_change */
|
||||
Tcl_CmdInfo cmdInfo; /* Database Tcl command (objv[2]) info */
|
||||
TestChangeIter *pIter = 0;
|
||||
const char *zIter = Tcl_GetString(objv[2]);
|
||||
if( 0==Tcl_GetCommandInfo(interp, zIter, &cmdInfo) ){
|
||||
Tcl_AppendResult(interp, "no such iter: ", Tcl_GetString(objv[2]), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
pIter = (struct TestChangeIter*)cmdInfo.objClientData;
|
||||
|
||||
rc = sqlite3changegroup_add_change(p->pGrp, pIter->pIter);
|
||||
if( rc!=SQLITE_OK ){
|
||||
rc = test_session_error(interp, rc, 0);
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
default: { /* delete */
|
||||
assert( iSub==3 );
|
||||
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
|
||||
@@ -1585,6 +1609,115 @@ static int SQLITE_TCLAPI test_sqlite3changegroup(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
extern const char *sqlite3ErrName(int);
|
||||
|
||||
/*
|
||||
** Destructor for Tcl iterator command object.
|
||||
*/
|
||||
static void test_iter_del(void *clientData){
|
||||
TestChangeIter *p = (TestChangeIter*)clientData;
|
||||
sqlite3changeset_finalize(p->pIter);
|
||||
ckfree(p);
|
||||
}
|
||||
|
||||
static int SQLITE_TCLAPI test_iter_cmd(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
static const char *aSub[] = {
|
||||
"next", /* 0 */
|
||||
"data", /* 1 */
|
||||
"finalize", /* 2 */
|
||||
0
|
||||
};
|
||||
int iSub = 0;
|
||||
|
||||
TestChangeIter *p = (TestChangeIter*)clientData;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( objc<2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CMD");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( Tcl_GetIndexFromObj(interp, objv[1], aSub, "sub-command", 0, &iSub) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch( iSub ){
|
||||
case 0:
|
||||
rc = sqlite3changeset_next(p->pIter);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
break;
|
||||
case 1:
|
||||
Tcl_SetObjResult(interp, testIterData(p->pIter));
|
||||
break;
|
||||
case 2:
|
||||
rc = sqlite3changeset_finalize(p->pIter);
|
||||
p->pIter = 0;
|
||||
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: sqlite3changeset_start ?-invert? CHANGESET
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_sqlite3changeset_start(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int isInvert = 0;
|
||||
void *pChangeset = 0; /* Buffer containing changeset */
|
||||
int nChangeset = 0; /* Size of buffer aChangeset in bytes */
|
||||
TestChangeIter *pNew = 0;
|
||||
sqlite3_changeset_iter *pIter = 0;
|
||||
int flags = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
static int iCmd = 1;
|
||||
char zCmd[64];
|
||||
|
||||
if( objc==3 ){
|
||||
int n = 0;
|
||||
const char *z = Tcl_GetStringFromObj(objv[1], &n);
|
||||
isInvert = (n>=2 && sqlite3_strnicmp(z, "-invert", n)==0);
|
||||
}
|
||||
|
||||
if( objc!=2 && (objc!=3 || !isInvert) ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-invert? CHANGESET");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
flags = isInvert ? SQLITE_CHANGESETSTART_INVERT : 0;
|
||||
pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[objc-1], &nChangeset);
|
||||
rc = sqlite3changeset_start_v2(&pIter, nChangeset, pChangeset, flags);
|
||||
if( rc!=SQLITE_OK ){
|
||||
char *zErr = sqlite3_mprintf(
|
||||
"error in sqlite3changeset_start_v2() - %d", rc
|
||||
);
|
||||
Tcl_AppendResult(interp, zErr, (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
pNew = (TestChangeIter*)ckalloc(sizeof(TestChangeIter));
|
||||
pNew->pIter = pIter;
|
||||
|
||||
sprintf(zCmd, "csiter%d", iCmd++);
|
||||
Tcl_CreateObjCommand(interp, zCmd, test_iter_cmd, (void*)pNew, test_iter_del);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zCmd, -1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int TestSession_Init(Tcl_Interp *interp){
|
||||
struct Cmd {
|
||||
const char *zCmd;
|
||||
@@ -1592,6 +1725,7 @@ int TestSession_Init(Tcl_Interp *interp){
|
||||
} aCmd[] = {
|
||||
{ "sqlite3session", test_sqlite3session },
|
||||
{ "sqlite3changegroup", test_sqlite3changegroup },
|
||||
{ "sqlite3changeset_start", test_sqlite3changeset_start },
|
||||
{ "sqlite3session_foreach", test_sqlite3session_foreach },
|
||||
{ "sqlite3changeset_invert", test_sqlite3changeset_invert },
|
||||
{ "sqlite3changeset_concat", test_sqlite3changeset_concat },
|
||||
|
||||
+14
-1
@@ -289,6 +289,12 @@ endif
|
||||
# embedding in the JS files and in building the distribution zip file.
|
||||
# It must NOT be in $(dir.tmp) because we need it to survive the
|
||||
# cleanup process for the dist build to work properly.
|
||||
#
|
||||
# Slight caveat: this uses the version info from the in-tree
|
||||
# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
|
||||
# end result is that the generated JS files may have static version
|
||||
# info from $(bin.version-info) which differ from their runtime-emited
|
||||
# version info (e.g. from sqlite3_libversion()).
|
||||
bin.version-info := $(dir.top)/version-info
|
||||
.NOTPARALLEL: $(bin.version-info)
|
||||
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
@@ -335,19 +341,26 @@ DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
#
|
||||
# Note that the SQLITE_... build flags used here have NO EFFECT on the
|
||||
# JS/WASM build. They are solely for use with $(bin.c-pp) itself.
|
||||
#
|
||||
# -D... flags which should be included in all invocations should be
|
||||
# appended to $(C-PP.FILTER.global).
|
||||
bin.c-pp := ./c-pp
|
||||
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
|
||||
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
|
||||
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
C-PP.FILTER.global ?=
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
C-PP.FILTER.global += -Denable-see
|
||||
endif
|
||||
define C-PP.FILTER
|
||||
# Create $2 from $1 using $(bin.c-pp)
|
||||
# $1 = Input file: c-pp -f $(1).js
|
||||
# $2 = Output file: c-pp -o $(2).js
|
||||
# $3 = optional c-pp -D... flags
|
||||
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global)
|
||||
CLEAN_FILES += $(2)
|
||||
endef
|
||||
# /end C-PP.FILTER
|
||||
|
||||
@@ -329,7 +329,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
||||
}
|
||||
|
||||
if(wasm.exports.sqlite3_activate_see instanceof Function){
|
||||
//#if enable-see
|
||||
if(wasm.exports.sqlite3_key_v2 instanceof Function){
|
||||
/**
|
||||
This code is capable of using an SEE build but note that an SEE
|
||||
WASM build is generally incompatible with SEE's license
|
||||
@@ -346,6 +347,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_activate_see", undefined, "string"]
|
||||
);
|
||||
}
|
||||
//#endif enable-see
|
||||
|
||||
/**
|
||||
Functions which require BigInt (int64) support are separated from
|
||||
the others because we need to conditionally bind them or apply
|
||||
@@ -624,10 +627,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.bindingSignatures.wasmInternal = [
|
||||
["sqlite3__wasm_db_reset", "int", "sqlite3*"],
|
||||
["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
||||
["sqlite3__wasm_vfs_create_file", "int",
|
||||
"sqlite3_vfs*","string","*", "int"],
|
||||
[/* DO NOT USE. This is deprecated since 2023-08-11 because it can
|
||||
trigger assert() in debug builds when used with file sizes
|
||||
which are not sizes to a multiple of a valid db page size. */
|
||||
"sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
|
||||
],
|
||||
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
|
||||
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
|
||||
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
|
||||
["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
+167
-16
@@ -87,6 +87,104 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
*/
|
||||
const __vfsPostOpenSql = Object.create(null);
|
||||
|
||||
//#if enable-see
|
||||
/**
|
||||
Converts ArrayBuffer or Uint8Array ba into a string of hex
|
||||
digits.
|
||||
*/
|
||||
const byteArrayToHex = function(ba){
|
||||
if( ba instanceof ArrayBuffer ){
|
||||
ba = new Uint8Array(ba);
|
||||
}
|
||||
const li = [];
|
||||
const digits = "0123456789abcdef";
|
||||
for( const d of ba ){
|
||||
li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] );
|
||||
}
|
||||
return li.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
Internal helper to apply an SEE key to a just-opened
|
||||
database. Requires that db be-a DB object which has just been
|
||||
opened, opt be the options object processed by its ctor, and opt
|
||||
must have either the key, hexkey, or textkey properties, either
|
||||
as a string, an ArrayBuffer, or a Uint8Array.
|
||||
|
||||
This is a no-op in non-SEE builds. It throws on error and returns
|
||||
without side effects if none of the key/textkey/hexkey options
|
||||
are set. It throws if more than one is set or if any are set to
|
||||
values of an invalid type.
|
||||
|
||||
Returns true if it applies the key, else an unspecified falsy value.
|
||||
*/
|
||||
const dbCtorApplySEEKey = function(db,opt){
|
||||
if( !capi.sqlite3_key_v2 ) return;
|
||||
let keytype;
|
||||
let key;
|
||||
const check = (opt.key ? 1 : 0) + (opt.hexkey ? 1 : 0) + (opt.textkey ? 1 : 0);
|
||||
if( !check ) return;
|
||||
else if( check>1 ){
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Only ONE of (key, hexkey, textkey) may be provided.");
|
||||
}
|
||||
if( opt.key ){
|
||||
/* It is not legal to bind an argument to PRAGMA key=?, so we
|
||||
convert it to a hexkey... */
|
||||
keytype = 'key';
|
||||
key = opt.key;
|
||||
if('string'===typeof key){
|
||||
key = new TextEncoder('utf-8').encode(key);
|
||||
}
|
||||
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
|
||||
key = byteArrayToHex(key);
|
||||
keytype = 'hexkey';
|
||||
}else{
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Invalid value for the 'key' option. Expecting a string,",
|
||||
"ArrayBuffer, or Uint8Array.");
|
||||
return;
|
||||
}
|
||||
}else if( opt.textkey ){
|
||||
/* For textkey we need it to be in string form, so convert it to
|
||||
a string if it's a byte array... */
|
||||
keytype = 'textkey';
|
||||
key = opt.textkey;
|
||||
if(key instanceof ArrayBuffer){
|
||||
key = new Uint8Array(key);
|
||||
}
|
||||
if(key instanceof Uint8Array){
|
||||
key = new TextDecoder('utf-8').decode(key);
|
||||
}else if('string'!==typeof key){
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Invalid value for the 'textkey' option. Expecting a string,",
|
||||
"ArrayBuffer, or Uint8Array.");
|
||||
}
|
||||
}else if( opt.hexkey ){
|
||||
keytype = 'hexkey';
|
||||
key = opt.hexkey;
|
||||
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
|
||||
key = byteArrayToHex(key);
|
||||
}else if('string'!==typeof key){
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Invalid value for the 'hexkey' option. Expecting a string,",
|
||||
"ArrayBuffer, or Uint8Array.");
|
||||
}
|
||||
/* else assume it's valid hex codes */
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
let stmt;
|
||||
try{
|
||||
stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1));
|
||||
stmt.step();
|
||||
}finally{
|
||||
if(stmt) stmt.finalize();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
//#endif enable-see
|
||||
|
||||
/**
|
||||
A proxy for DB class constructors. It must be called with the
|
||||
being-construct DB object as its "this". See the DB constructor
|
||||
@@ -175,16 +273,28 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
__ptrMap.set(this, pDb);
|
||||
__stmtMap.set(this, Object.create(null));
|
||||
try{
|
||||
//#if enable-see
|
||||
dbCtorApplySEEKey(this,opt);
|
||||
//#endif
|
||||
// Check for per-VFS post-open SQL/callback...
|
||||
const pVfs = capi.sqlite3_js_db_vfs(pDb);
|
||||
if(!pVfs) toss3("Internal error: cannot get VFS for new db handle.");
|
||||
const pVfs = capi.sqlite3_js_db_vfs(pDb)
|
||||
|| toss3("Internal error: cannot get VFS for new db handle.");
|
||||
const postInitSql = __vfsPostOpenSql[pVfs];
|
||||
if(postInitSql instanceof Function){
|
||||
postInitSql(this, sqlite3);
|
||||
}else if(postInitSql){
|
||||
checkSqlite3Rc(
|
||||
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
|
||||
);
|
||||
if(postInitSql){
|
||||
/**
|
||||
Reminder: if this db is encrypted and the client did _not_ pass
|
||||
in the key, any init code will fail, causing the ctor to throw.
|
||||
We don't actually know whether the db is encrypted, so we cannot
|
||||
sensibly apply any heuristics which skip the init code only for
|
||||
encrypted databases for which no key has yet been supplied.
|
||||
*/
|
||||
if(postInitSql instanceof Function){
|
||||
postInitSql(this, sqlite3);
|
||||
}else{
|
||||
checkSqlite3Rc(
|
||||
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
this.close();
|
||||
@@ -280,6 +390,36 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
- `flags`: open-mode flags
|
||||
- `vfs`: the VFS fname
|
||||
|
||||
//#if enable-see
|
||||
|
||||
SEE-capable builds optionally support ONE of the following
|
||||
additional options:
|
||||
|
||||
- `key`, `hexkey`, or `textkey`: encryption key as a string,
|
||||
ArrayBuffer, or Uint8Array. These flags function as documented
|
||||
for the SEE pragmas of the same names. Using a byte array for
|
||||
`hexkey` is equivalent to the same series of hex codes in
|
||||
string form, so `'666f6f'` is equivalent to
|
||||
`Uint8Array([0x66,0x6f,0x6f])`. A `textkey` byte array is
|
||||
assumed to be UTF-8. A `key` string is transformed into a UTF-8
|
||||
byte array, and a `key` byte array is transformed into a
|
||||
`hexkey` with the same bytes.
|
||||
|
||||
In non-SEE builds, these options are ignored. In SEE builds,
|
||||
`PRAGMA key/textkey/hexkey=X` is executed immediately after
|
||||
opening the db. If more than one of the options is provided,
|
||||
or any option has an invalid argument type, an exception is
|
||||
thrown.
|
||||
|
||||
Note that some DB subclasses may run post-initialization SQL
|
||||
code, e.g. to set a busy-handler timeout or tweak the page cache
|
||||
size. Such code is run _after_ the SEE key is applied. If no key
|
||||
is supplied and the database is encrypted, execution of the
|
||||
post-initialization SQL will fail, causing the constructor to
|
||||
throw.
|
||||
|
||||
//#endif enable-see
|
||||
|
||||
The `filename` and `vfs` arguments may be either JS strings or
|
||||
C-strings allocated via WASM. `flags` is required to be a JS
|
||||
string (because it's specific to this API, which is specific
|
||||
@@ -288,7 +428,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
For purposes of passing a DB instance to C-style sqlite3
|
||||
functions, the DB object's read-only `pointer` property holds its
|
||||
`sqlite3*` pointer value. That property can also be used to check
|
||||
whether this DB instance is still open.
|
||||
whether this DB instance is still open: it will evaluate to
|
||||
`undefined` after the DB object's close() method is called.
|
||||
|
||||
In the main window thread, the filenames `":localStorage:"` and
|
||||
`":sessionStorage:"` are special: they cause the db to use either
|
||||
@@ -1543,7 +1684,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
they are larger than 32 bits, else double or int32, depending
|
||||
on whether they have a fractional part. Booleans are bound as
|
||||
integer 0 or 1. It is not expected the distinction of binding
|
||||
doubles which have no fractional parts is integers is
|
||||
doubles which have no fractional parts and integers is
|
||||
significant for the majority of clients due to sqlite3's data
|
||||
typing model. If [BigInt] support is enabled then this
|
||||
routine will bind BigInt values as 64-bit integers if they'll
|
||||
@@ -1727,7 +1868,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
an exception is thrown.
|
||||
|
||||
By default it will determine the data type of the result
|
||||
automatically. If passed a second arugment, it must be one
|
||||
automatically. If passed a second argument, it must be one
|
||||
of the enumeration values for sqlite3 types, which are
|
||||
defined as members of the sqlite3 module: SQLITE_INTEGER,
|
||||
SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value,
|
||||
@@ -1927,16 +2068,26 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
Functionally equivalent to DB(storageName,'c','kvvfs') except
|
||||
that it throws if the given storage name is not one of 'local'
|
||||
or 'session'.
|
||||
|
||||
As of version 3.46, the argument may optionally be an options
|
||||
object in the form:
|
||||
|
||||
{
|
||||
filename: 'session'|'local',
|
||||
... etc. (all options supported by the DB ctor)
|
||||
}
|
||||
|
||||
noting that the 'vfs' option supported by main DB
|
||||
constructor is ignored here: the vfs is always 'kvvfs'.
|
||||
*/
|
||||
sqlite3.oo1.JsStorageDb = function(storageName='session'){
|
||||
const opt = dbCtorHelper.normalizeArgs(...arguments);
|
||||
storageName = opt.filename;
|
||||
if('session'!==storageName && 'local'!==storageName){
|
||||
toss3("JsStorageDb db name must be one of 'session' or 'local'.");
|
||||
}
|
||||
dbCtorHelper.call(this, {
|
||||
filename: storageName,
|
||||
flags: 'c',
|
||||
vfs: "kvvfs"
|
||||
});
|
||||
opt.vfs = 'kvvfs';
|
||||
dbCtorHelper.call(this, opt);
|
||||
};
|
||||
const jdb = sqlite3.oo1.JsStorageDb;
|
||||
jdb.prototype = Object.create(DB.prototype);
|
||||
|
||||
@@ -245,7 +245,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
|
||||
The exception's message is created by concatenating its
|
||||
arguments with a space between each, except for the
|
||||
two-args-with-an-objec form and that the first argument will
|
||||
two-args-with-an-object form and that the first argument will
|
||||
get coerced to a string, as described above, if it's an
|
||||
integer.
|
||||
|
||||
@@ -1838,7 +1838,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
/**
|
||||
Calls either sqlite3_result_error_nomem(), if e is-a
|
||||
WasmAllocError, or sqlite3_result_error(). In the latter case,
|
||||
the second arugment is coerced to a string to create the error
|
||||
the second argument is coerced to a string to create the error
|
||||
message.
|
||||
|
||||
The first argument is a (sqlite3_context*). Returns void.
|
||||
|
||||
@@ -459,11 +459,6 @@ sqlite3.initWorker1API = function(){
|
||||
return wState.dbList[0] && getDbId(wState.dbList[0]);
|
||||
};
|
||||
|
||||
const guessVfs = function(filename){
|
||||
const m = /^file:.+(vfs=(\w+))/.exec(filename);
|
||||
return sqlite3.capi.sqlite3_vfs_find(m ? m[2] : 0);
|
||||
};
|
||||
|
||||
const isSpecialDbFilename = (n)=>{
|
||||
return ""===n || ':'===n[0];
|
||||
};
|
||||
@@ -485,36 +480,8 @@ sqlite3.initWorker1API = function(){
|
||||
toss("Throwing because of simulateError flag.");
|
||||
}
|
||||
const rc = Object.create(null);
|
||||
let byteArray, pVfs;
|
||||
oargs.vfs = args.vfs;
|
||||
if(isSpecialDbFilename(args.filename)){
|
||||
oargs.filename = args.filename || "";
|
||||
}else{
|
||||
oargs.filename = args.filename;
|
||||
byteArray = args.byteArray;
|
||||
if(byteArray) pVfs = guessVfs(args.filename);
|
||||
}
|
||||
if(pVfs){
|
||||
/* 2022-11-02: this feature is as-yet untested except that
|
||||
sqlite3__wasm_vfs_create_file() has been tested from the
|
||||
browser dev console. */
|
||||
let pMem;
|
||||
try{
|
||||
pMem = sqlite3.wasm.allocFromTypedArray(byteArray);
|
||||
const rc = util.sqlite3__wasm_vfs_create_file(
|
||||
pVfs, oargs.filename, pMem, byteArray.byteLength
|
||||
);
|
||||
if(rc) sqlite3.SQLite3Error.toss(rc);
|
||||
}catch(e){
|
||||
throw new sqlite3.SQLite3Error(
|
||||
e.name+' creating '+args.filename+": "+e.message, {
|
||||
cause: e
|
||||
}
|
||||
);
|
||||
}finally{
|
||||
if(pMem) sqlite3.wasm.dealloc(pMem);
|
||||
}
|
||||
}
|
||||
oargs.filename = args.filename || "";
|
||||
const db = wState.open(oargs);
|
||||
rc.filename = db.filename;
|
||||
rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs");
|
||||
@@ -604,7 +571,6 @@ sqlite3.initWorker1API = function(){
|
||||
});
|
||||
rc.version = sqlite3.version;
|
||||
rc.vfsList = sqlite3.capi.sqlite3_js_vfs_list();
|
||||
rc.opfsEnabled = !!sqlite3.opfs;
|
||||
return rc;
|
||||
},
|
||||
|
||||
@@ -631,12 +597,6 @@ sqlite3.initWorker1API = function(){
|
||||
|
||||
toss: function(ev){
|
||||
toss("Testing worker exception");
|
||||
},
|
||||
|
||||
'opfs-tree': async function(ev){
|
||||
if(!sqlite3.opfs) toss("OPFS support is unavailable.");
|
||||
const response = await sqlite3.opfs.treeList();
|
||||
return response;
|
||||
}
|
||||
}/*wMsgHandler*/;
|
||||
|
||||
|
||||
@@ -38,10 +38,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
Significant notes and limitations:
|
||||
|
||||
- As of this writing, OPFS is still very much in flux and only
|
||||
available in bleeding-edge versions of Chrome (v102+, noting that
|
||||
that number will increase as the OPFS API matures).
|
||||
|
||||
- The OPFS features used here are only available in dedicated Worker
|
||||
threads. This file tries to detect that case, resulting in a
|
||||
rejected Promise if those features do not seem to be available.
|
||||
@@ -62,15 +58,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
The argument may optionally be a plain object with the following
|
||||
configuration options:
|
||||
|
||||
- proxyUri: as described above
|
||||
- proxyUri: name of the async proxy JS file.
|
||||
|
||||
- verbose (=2): an integer 0-3. 0 disables all logging, 1 enables
|
||||
logging of errors. 2 enables logging of warnings and errors. 3
|
||||
additionally enables debugging info.
|
||||
additionally enables debugging info. Logging is performed
|
||||
via the sqlite3.config.{log|warn|error}() functions.
|
||||
|
||||
- sanityChecks (=false): if true, some basic sanity tests are
|
||||
run on the OPFS VFS API after it's initialized, before the
|
||||
returned Promise resolves.
|
||||
- sanityChecks (=false): if true, some basic sanity tests are run on
|
||||
the OPFS VFS API after it's initialized, before the returned
|
||||
Promise resolves. This is only intended for testing and
|
||||
development of the VFS, not client-side use.
|
||||
|
||||
On success, the Promise resolves to the top-most sqlite3 namespace
|
||||
object and that object gets a new object installed in its
|
||||
@@ -994,7 +992,9 @@ const installOpfsVfs = function callee(options){
|
||||
};
|
||||
/**
|
||||
Checks whether the given OPFS filesystem entry exists,
|
||||
returning true if it does, false if it doesn't.
|
||||
returning true if it does, false if it doesn't or if an
|
||||
exception is intercepted while trying to make the
|
||||
determination.
|
||||
*/
|
||||
opfsUtil.entryExists = async function(fsEntryName){
|
||||
try {
|
||||
@@ -1110,9 +1110,9 @@ const installOpfsVfs = function callee(options){
|
||||
};
|
||||
|
||||
/**
|
||||
Traverses the OPFS filesystem, calling a callback for each one.
|
||||
The argument may be either a callback function or an options object
|
||||
with any of the following properties:
|
||||
Traverses the OPFS filesystem, calling a callback for each
|
||||
entry. The argument may be either a callback function or an
|
||||
options object with any of the following properties:
|
||||
|
||||
- `callback`: function which gets called for each filesystem
|
||||
entry. It gets passed 3 arguments: 1) the
|
||||
@@ -1142,11 +1142,6 @@ const installOpfsVfs = function callee(options){
|
||||
but that promise has no specific meaning: the traversal it
|
||||
performs is synchronous. The promise must be used to catch any
|
||||
exceptions propagated by the callback, however.
|
||||
|
||||
TODO: add an option which specifies whether to traverse
|
||||
depth-first or breadth-first. We currently do depth-first but
|
||||
an incremental file browsing widget would benefit more from
|
||||
breadth-first.
|
||||
*/
|
||||
opfsUtil.traverse = async function(opt){
|
||||
const defaultOpt = {
|
||||
|
||||
+12
-23
@@ -1678,35 +1678,24 @@ int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){
|
||||
return sqlite3_config(op, arg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Pending removal after verification of a workaround discussed in the
|
||||
// forum post linked to below.
|
||||
/*
|
||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||
** for use by the sqlite project's own JS/WASM bindings.
|
||||
**
|
||||
** Returns a pointer to sqlite3_free(). In compliant browsers the
|
||||
** return value, when passed to sqlite3.wasm.exports.functionEntry(),
|
||||
** must resolve to the same function as
|
||||
** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where
|
||||
** sqlite3 is exported globally, the following must be true:
|
||||
**
|
||||
** ```
|
||||
** sqlite3.wasm.functionEntry(
|
||||
** sqlite3.wasm.exports.sqlite3__wasm_ptr_to_sqlite3_free()
|
||||
** ) === sqlite3.wasm.exports.sqlite3_free
|
||||
** ```
|
||||
**
|
||||
** Using a function to return this pointer, as opposed to exporting it
|
||||
** via sqlite3__wasm_enum_json(), is an attempt to work around a
|
||||
** Safari-specific quirk covered at
|
||||
** https://sqlite.org/forum/info/e5b20e1feb37a19a.
|
||||
**/
|
||||
** If z is not NULL, returns the result of passing z to
|
||||
** sqlite3_mprintf()'s %Q modifier (if addQuotes is true) or %q (if
|
||||
** addQuotes is 0). Returns NULL if z is NULL or on OOM.
|
||||
*/
|
||||
SQLITE_WASM_EXPORT
|
||||
void * sqlite3__wasm_ptr_to_sqlite3_free(void){
|
||||
return (void*)sqlite3_free;
|
||||
char * sqlite3__wasm_qfmt_token(char *z, int addQuotes){
|
||||
char * rc = 0;
|
||||
if( z ){
|
||||
rc = addQuotes
|
||||
? sqlite3_mprintf("%Q", z)
|
||||
: sqlite3_mprintf("%q", z);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
|
||||
#include <emscripten/wasmfs.h>
|
||||
|
||||
@@ -207,7 +207,7 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
msg.args = arguments[1];
|
||||
msg.dbId = msg.args.dbId;
|
||||
}else{
|
||||
toss("Invalid arugments for sqlite3Worker1Promiser()-created factory.");
|
||||
toss("Invalid arguments for sqlite3Worker1Promiser()-created factory.");
|
||||
}
|
||||
if(!msg.dbId && msg.type!=='open') msg.dbId = dbId;
|
||||
msg.messageId = genMsgId(msg);
|
||||
@@ -285,7 +285,7 @@ globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
}/*defaultConfig*/;
|
||||
|
||||
/**
|
||||
sqlite3Worker1Promiser.v2() works identically to
|
||||
sqlite3Worker1Promiser.v2(), added in 3.46, works identically to
|
||||
sqlite3Worker1Promiser() except that it returns a Promise instead
|
||||
of relying an an onready callback in the config object. The Promise
|
||||
resolves to the same factory function which
|
||||
|
||||
@@ -1382,15 +1382,19 @@ globalThis.WhWasmUtilInstaller = function(target){
|
||||
conversion of argument or return types, but see xWrap() and
|
||||
xCallWrapped() for variants which do.
|
||||
|
||||
If the first argument is a function is is assumed to be
|
||||
a WASM-bound function and is used as-is instead of looking up
|
||||
the function via xGet().
|
||||
|
||||
As a special case, if passed only 1 argument after the name and
|
||||
that argument in an Array, that array's entries become the
|
||||
function arguments. (This is not an ambiguous case because it's
|
||||
not legal to pass an Array object to a WASM function.)
|
||||
*/
|
||||
target.xCall = function(fname, ...args){
|
||||
const f = target.xGet(fname);
|
||||
const f = (fname instanceof Function) ? fname : target.xGet(fname);
|
||||
if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function.");
|
||||
if(f.length!==args.length) __argcMismatch(fname,f.length)
|
||||
if(f.length!==args.length) __argcMismatch(((f===fname) ? f.name : fname),f.length)
|
||||
/* This is arguably over-pedantic but we want to help clients keep
|
||||
from shooting themselves in the foot when calling C APIs. */;
|
||||
return (2===arguments.length && Array.isArray(arguments[1]))
|
||||
@@ -1537,7 +1541,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
||||
jsFuncToWasm().
|
||||
|
||||
- bindScope (string): one of ('transient', 'context',
|
||||
'singleton'). Bind scopes are:
|
||||
'singleton', 'permanent'). Bind scopes are:
|
||||
|
||||
- 'transient': it will convert JS functions to WASM only for
|
||||
the duration of the xWrap()'d function call, using
|
||||
@@ -1787,11 +1791,29 @@ globalThis.WhWasmUtilInstaller = function(target){
|
||||
const __xResultAdapterCheck =
|
||||
(t)=>xResult.get(t) || toss("Result adapter not found:",t);
|
||||
|
||||
/**
|
||||
Fetches the xWrap() argument adapter mapped to t, calls it,
|
||||
passing in all remaining arguments, and returns the result.
|
||||
Throws if t is not mapped to an argument converter.
|
||||
*/
|
||||
cache.xWrap.convertArg = (t,...args)=>__xArgAdapterCheck(t)(...args);
|
||||
/**
|
||||
Identical to convertArg() except that it does not perform
|
||||
an is-defined check on the mapping to t before invoking it.
|
||||
*/
|
||||
cache.xWrap.convertArgNoCheck = (t,...args)=>xArg.get(t)(...args);
|
||||
|
||||
/**
|
||||
Fetches the xWrap() result adapter mapped to t, calls it, passing
|
||||
it v, and returns the result. Throws if t is not mapped to an
|
||||
argument converter.
|
||||
*/
|
||||
cache.xWrap.convertResult =
|
||||
(t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined));
|
||||
/**
|
||||
Identical to convertResult() except that it does not perform an
|
||||
is-defined check on the mapping to t before invoking it.
|
||||
*/
|
||||
cache.xWrap.convertResultNoCheck =
|
||||
(t,v)=>(null===t ? v : (t ? xResult.get(t)(v) : undefined));
|
||||
|
||||
@@ -1903,15 +1925,15 @@ globalThis.WhWasmUtilInstaller = function(target){
|
||||
const C-string, encoded as UTF-8, copies it to a JS string,
|
||||
and returns that JS string.
|
||||
|
||||
- `string:dealloc` or `utf8:dealloc) (results): treats the result value
|
||||
as a non-const UTF-8 C-string, ownership of which has just been
|
||||
transfered to the caller. It copies the C-string to a JS
|
||||
string, frees the C-string, and returns the JS string. If such
|
||||
a result value is NULL, the JS result is `null`. Achtung: when
|
||||
using an API which returns results from a specific allocator,
|
||||
e.g. `my_malloc()`, this conversion _is not legal_. Instead, an
|
||||
equivalent conversion which uses the appropriate deallocator is
|
||||
required. For example:
|
||||
- `string:dealloc` or `utf8:dealloc` (results): treats the result
|
||||
value as a non-const UTF-8 C-string, ownership of which has
|
||||
just been transfered to the caller. It copies the C-string to a
|
||||
JS string, frees the C-string, and returns the JS string. If
|
||||
such a result value is NULL, the JS result is `null`. Achtung:
|
||||
when using an API which returns results from a specific
|
||||
allocator, e.g. `my_malloc()`, this conversion _is not
|
||||
legal_. Instead, an equivalent conversion which uses the
|
||||
appropriate deallocator is required. For example:
|
||||
|
||||
```js
|
||||
target.xWrap.resultAdapter('string:my_free',(i)=>{
|
||||
@@ -2012,8 +2034,12 @@ globalThis.WhWasmUtilInstaller = function(target){
|
||||
arguments may be passed in after that one, and what those
|
||||
arguments are, is _not_ part of the public interface and is
|
||||
_not_ stable.
|
||||
|
||||
Maintenance reminder: the Ember framework modifies the core
|
||||
Array type, breaking for-in loops.
|
||||
*/
|
||||
for(const i in args) args[i] = cxw.convertArgNoCheck(
|
||||
let i = 0;
|
||||
for(; i < args.length; ++i) args[i] = cxw.convertArgNoCheck(
|
||||
argTypes[i], args[i], args, i
|
||||
);
|
||||
return cxw.convertResultNoCheck(resultType, xf.apply(null,args));
|
||||
|
||||
+8
-3
@@ -19,10 +19,15 @@ MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))
|
||||
# built, and won't be built until we expand the dependencies. Thus we
|
||||
# have to use a temporary name for the archive until we can get
|
||||
# that binary built.
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-wasm
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
dist-name-extra := -see
|
||||
else
|
||||
dist-name-prefix := sqlite-wasm-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||
dist-name-extra :=
|
||||
endif
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-wasm$(dist-name-extra)
|
||||
else
|
||||
dist-name-prefix := sqlite-wasm$(dist-name-extra)-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||
endif
|
||||
dist-name := $(dist-name-prefix)-TEMP
|
||||
|
||||
|
||||
@@ -1482,7 +1482,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
/*step() skipped intentionally*/.reset(true);
|
||||
} finally {
|
||||
T.assert(0===st.finalize())
|
||||
.assert(undefined===st.finalize());
|
||||
.assert(undefined===st.finalize());
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -2587,7 +2587,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
const pVfs = capi.sqlite3_vfs_find('kvvfs');
|
||||
T.assert(pVfs);
|
||||
const JDb = this.JDb = sqlite3.oo1.JsStorageDb;
|
||||
const unlink = this.kvvfsUnlink = ()=>{JDb.clearStorage(filename)};
|
||||
const unlink = this.kvvfsUnlink = ()=>JDb.clearStorage(this.kvvfsDbFile);
|
||||
unlink();
|
||||
let db = new JDb(filename);
|
||||
try {
|
||||
@@ -2605,6 +2605,60 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
}
|
||||
}/*kvvfs sanity checks*/)
|
||||
//#if enable-see
|
||||
.t({
|
||||
name: 'kvvfs with SEE encryption',
|
||||
predicate: ()=>(isUIThread()
|
||||
|| "Only available in main thread."),
|
||||
test: function(sqlite3){
|
||||
this.kvvfsUnlink();
|
||||
let db;
|
||||
const encOpt1 = 1
|
||||
? {textkey: 'foo'}
|
||||
: {key: 'foo'};
|
||||
const encOpt2 = encOpt1.textkey
|
||||
? encOpt1
|
||||
: {hexkey: new Uint8Array([0x66,0x6f,0x6f]/*==>"foo"*/)}
|
||||
try{
|
||||
db = new this.JDb({
|
||||
filename: this.kvvfsDbFile,
|
||||
...encOpt1
|
||||
});
|
||||
db.exec([
|
||||
"create table t(a,b);",
|
||||
"insert into t(a,b) values(1,2),(3,4)"
|
||||
]);
|
||||
db.close();
|
||||
let err;
|
||||
try{
|
||||
db = new this.JDb({
|
||||
filename: this.kvvfsDbFile,
|
||||
flags: 'ct'
|
||||
});
|
||||
T.assert(db) /* opening is fine, but... */;
|
||||
db.exec("select 1 from sqlite_schema");
|
||||
console.warn("sessionStorage =",sessionStorage);
|
||||
}catch(e){
|
||||
err = e;
|
||||
}finally{
|
||||
db.close();
|
||||
}
|
||||
T.assert(err,"Expecting an exception")
|
||||
.assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
|
||||
"Expecting NOTADB");
|
||||
db = new sqlite3.oo1.DB({
|
||||
filename: this.kvvfsDbFile,
|
||||
vfs: 'kvvfs',
|
||||
...encOpt2
|
||||
});
|
||||
T.assert( 4===db.selectValue('select sum(a) from t') );
|
||||
}finally{
|
||||
if( db ) db.close();
|
||||
this.kvvfsUnlink();
|
||||
}
|
||||
}
|
||||
})/*kvvfs with SEE*/
|
||||
//#endif enable-see
|
||||
;/* end kvvfs tests */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -364,6 +364,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/spellfix.c \
|
||||
$(TOP)/ext/misc/stmtrand.c \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
C Enhancements\sto\sthe\sfuzzer\sinvariant\schecker\sto\sturn\soptimizations\son\sand\noff.
|
||||
D 2024-04-08T06:37:19.669
|
||||
C Omit\stests\sthat\sdepend\son\ssqlite3_release_memory()\sin\slock5.test\swhen\srunning\sthe\smemsubsys1\sor\smemsubsys2\spermutations.
|
||||
D 2024-06-12T15:29:37.134
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 993a7874e3d3721df61846f03dda4a9ef7490da11953ae36ba1bb0c0346eaf4a
|
||||
F Makefile.in 58c2cc5010aa5fd5e8eef6fe24d4ebcec7dc2e8c56f135d4f49e90a099bbc531
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc e64a52619310d3067f6c38f56eedd15918a82dade70954197d6da486ad99d7f4
|
||||
F Makefile.msc 993f8addade63bcac7192416e7161ceee60edcee2376299ea48b2a74c66ac2d5
|
||||
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
|
||||
F VERSION c84541c6a9e8426462176fbb1f9ecb5cfd7d1bb56228053ff7eeba8841673eb6
|
||||
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
@@ -24,7 +24,7 @@ F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d
|
||||
F autoconf/tea/Makefile.in 106a96f2f745d41a0f6193f1de98d7355830b65d45032c18cd7c90295ec24196
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
F autoconf/tea/configure.ac 9e74135563a901d9b1a019bad1c9d73a6659fa32325f6a565bef72bfb0ec7297
|
||||
F autoconf/tea/configure.ac 0deb5d6c49c8119f75f436488219fc043127d72057af5dfba2c9ce096a5734bc
|
||||
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
|
||||
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
|
||||
F autoconf/tea/pkgIndex.tcl.in b9eb6dd37f64e08e637d576b3c83259814b9cddd78bec4af2e5abfc6c5c750ce
|
||||
@@ -35,7 +35,7 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
|
||||
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
|
||||
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
|
||||
F configure 40f7af9ed5ca0d44a4b9bc7ad34f1ee4867bb4eeb19e75036be6bed66193a498 x
|
||||
F configure 27d144c2edfa993ac155a2ad5e6b431e4ec811159598ef55a59f345bc2e5e533 x
|
||||
F configure.ac f25bd7843120f2c2b8bc9db5a92b0502bbdd28e68907415c3d42fc8e57c657b9
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
@@ -74,7 +74,7 @@ F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
|
||||
F ext/fts3/fts3_porter.c e19807ce0ae31c1c6e9898e89ecc93183d7ec224ea101af039722a4f49e5f2b8
|
||||
F ext/fts3/fts3_snippet.c 4d6523e3eddeb7b46e7a82b3476a0a86a0c04821e0e2b8dd40f45ee28057cb13
|
||||
F ext/fts3/fts3_snippet.c 610328fe128c047c6b0eba77768982ccf3933daae095d497949a75c9dfd47409
|
||||
F ext/fts3/fts3_term.c 845f0e2456b1be42f7f1bec1da1dfc05bc347531eff90775ffc6698902c281de
|
||||
F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
|
||||
F ext/fts3/fts3_tokenize_vtab.c 7fd9ef364f257b97218b9c331f2378e307375c592f70fd541f714e747d944962
|
||||
@@ -93,22 +93,22 @@ F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6d
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl bc3a0ca78be7d3df08e7602c00ca48021ebae40682d75eb001bfdf6e54ffb44e
|
||||
F ext/fts5/fts5.h 8856e11a5f0269cd346754cea0765efe8089635b80cad3222e8bfdb08cd5348a
|
||||
F ext/fts5/fts5Int.h defa43c0932265138ee910ca416e6baccf8b774e0f3d610e74be1ab2880e9834
|
||||
F ext/fts5/fts5Int.h 407ee36addad0ae6df5d37a811f0bd509ab6708b29640884ed5c7509e5f75143
|
||||
F ext/fts5/fts5_aux.c 4584e88878e54828bf7d4d0d83deedd232ec60628b7731be02bad6adb62304b1
|
||||
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
|
||||
F ext/fts5/fts5_config.c 8072a207034b51ae9b7694121d1b5715c794e94b275e088f70ae532378ca5cdf
|
||||
F ext/fts5/fts5_expr.c e91156ebdcc08d837f4f324168f69f3c0d7fdef0e521fd561efb48ef3297b696
|
||||
F ext/fts5/fts5_config.c 68cb87a49215f8e7028000b681df4057c430a4a6afbd676463886da94c9e1c37
|
||||
F ext/fts5/fts5_expr.c 85789f6fb01995f2578b60a360057ed754335a890b1ab2e57e238b3670a9ae6c
|
||||
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
|
||||
F ext/fts5/fts5_index.c ee0f4d50bc0c58a7c5ef7d645e7e38e1e59315b8ea9d722ae00c5f949ee65379
|
||||
F ext/fts5/fts5_main.c d68bd9533d5a638b7f6fae61c3cb0a15257dcdcccedaf3d0b3c9f55940c85048
|
||||
F ext/fts5/fts5_main.c 21ddeb331ae6c9e990a18299c977156a9dac9ee92f372cfe7928d04433295042
|
||||
F ext/fts5/fts5_storage.c f9e31b0d155e9b2c92d5d3a09ad7a56b937fbf1c7f962e10f4ca6281349f3934
|
||||
F ext/fts5/fts5_tcl.c fdf7e2bb9a9186cfcaf2d2ce11d338309342b7a7593c2812bc54455db53da5d2
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
F ext/fts5/fts5_tokenize.c 83cfcede3898001cab84432a36ce1503e3080cf9b1c682b022ec82e267ea4c13
|
||||
F ext/fts5/fts5_tokenize.c fa5493075101540270f572038fc1723d44fcc97bfbf237c8530013b8a27860be
|
||||
F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c 209e0c151e108d5f3621fa24b91e9b02f3750ee6c3f9ccec312df39481b68a09
|
||||
F ext/fts5/fts5_vocab.c e4830b00809e5da53bc10f93adc59e321407b0f801c7f4167c0e47f5552267e0
|
||||
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl 3378732aae2a7d9a4b9b5c40bde678d4259ca16bd490883325aecc4747bcb384
|
||||
@@ -126,14 +126,14 @@ F ext/fts5/test/fts5ak.test f459a64c9d38698af72a7c657ab6349bca96150241dd69fcce75
|
||||
F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
|
||||
F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
|
||||
F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
|
||||
F ext/fts5/test/fts5aux.test ed3596469f85a6cff5f6060e0cd9e3f9602051d8db2b497f5d12c85d39f20a62
|
||||
F ext/fts5/test/fts5aux.test f3b4aa403cb672b0d79af1a87519e5896b309ab026de6425fa179589da55d7a5
|
||||
F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
|
||||
F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
|
||||
F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
|
||||
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
|
||||
F ext/fts5/test/fts5cat.test daba0b80659460b0cb60bd1f40b402478a761fe7ea414c3c94c2be25568cc33a
|
||||
F ext/fts5/test/fts5circref.test f880dfd0d99f6fb73b88ccacb0927d18e833672fd906cc47d6b4e529419eaa62
|
||||
F ext/fts5/test/fts5colset.test 7031ce84fb4d312df5a99fc4e7b324e660ccb513c97eccdef469bfd52d3d0f8f
|
||||
F ext/fts5/test/fts5colset.test 544f4998cdbfe06a3123887fc0221612e8aa8192cdaff152872f1aadb10e6897
|
||||
F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
|
||||
F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
|
||||
F ext/fts5/test/fts5conflict.test bf6030a77dbb1bedfcc42e589ed7980846c995765d77460551e448b56d741244
|
||||
@@ -178,7 +178,7 @@ F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b99
|
||||
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
F ext/fts5/test/fts5hash.test dc7bc7e0cdeb42cfce31294ad2f8fcf43192bfd0145bb7f3ecc5465d8c72696f
|
||||
F ext/fts5/test/fts5integrity.test f1723fe9fb9381b26c946ab4d7505041434df2c449d1cd53f45c7bf8c098dfa2
|
||||
F ext/fts5/test/fts5integrity.test e1af628af123669d018e84a649283ca41944429dfeb279ceaed9f3f480597153
|
||||
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
|
||||
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
@@ -186,7 +186,7 @@ F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fc
|
||||
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
|
||||
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test 89dc46e37951b7f6653809f4abf6b1ca2f1fa62259efaf719339288f76fb6be9
|
||||
F ext/fts5/test/fts5misc.test b88aa28ff20238b394495b0795cddca1a62b98fa09b99e462a8abc572d04ee88
|
||||
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
|
||||
@@ -218,7 +218,7 @@ F ext/fts5/test/fts5secure4.test 0d10a80590c07891478700af7793b232962042677432b98
|
||||
F ext/fts5/test/fts5secure5.test c07a68ced5951567ac116c22f2d2aafae497e47fe9fcb6a335c22f9c7a4f2c3a
|
||||
F ext/fts5/test/fts5secure6.test 74bf04733cc523bccca519bb03d3b4e2ed6f6e3db7c59bf6be82c88a0ac857fd
|
||||
F ext/fts5/test/fts5secure7.test fd03d0868d64340a1db8615b02e5508fea409de13910114e4f19eaefc120777a
|
||||
F ext/fts5/test/fts5secure8.test eb3579e9d58b0acad97e8082dee1f99b2d393198f03500b453c2b25761c0c298
|
||||
F ext/fts5/test/fts5secure8.test e68c0ac4447f415ff3e4e82531e99548289286f9f3a29c8cd53036113fe28602
|
||||
F ext/fts5/test/fts5securefault.test dbca2b6a1c16700017f5051138991b705410889933f2a37c57ae8a23b296b10b
|
||||
F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
|
||||
F ext/fts5/test/fts5simple2.test 8dd2389ee75e21a1429fe87e5f8c7d9a97ad1470304a8a2d3ba4b8c3c345fecd
|
||||
@@ -227,10 +227,10 @@ F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074
|
||||
F ext/fts5/test/fts5synonym2.test e2f6ff68c4fbe12a866a3a87510f553d9dac99bcb74c10b56487c4c0a562fcf5
|
||||
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
|
||||
F ext/fts5/test/fts5tokenizer.test abeb8b2d00415e5c8eae48d2dcb91357b7f7e1fddbb2b650f00b589a7bea9659
|
||||
F ext/fts5/test/fts5tokenizer2.test cb5428c7cfb3b6a74b7adfcde65506e329112003e8dffa7501d01c2d18d02569
|
||||
F ext/fts5/test/fts5trigram.test 6c4e37864f3e7d90673db5563d9736d7e40080ab94d10ebdffa94c1b77941da0
|
||||
F ext/fts5/test/fts5trigram2.test 9fe4207f8a4241747aff1005258b564958588d21bfd240d6cd4c2e955d31c156
|
||||
F ext/fts5/test/fts5trigram2.test c91f0a94f7e1ff859682228646abeab4c0eba2effc46af2cbc8f0f48b05a0566
|
||||
F ext/fts5/test/fts5ubsan.test 783d5a8d13ebfa169e634940228db54540780e3ba7a87ad1e4510e61440bf64b
|
||||
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
|
||||
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
|
||||
@@ -248,7 +248,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
F ext/fts5/tool/mkfts5c.tcl 3eba8e9bee4221ed165f3304b51b2a74a705f4ec5df3d044573a2be539534af8
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
|
||||
F ext/icu/icu.c 5c858611fd11d65caf8a04acd836af9193880a724ba75cee63f9da75ce4a469d
|
||||
F ext/icu/icu.c 3add8197e0a86c1761771a39500ebae749438bcf1836160b407a56b4eaa8721c
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/intck/intck1.test f3a3cba14b6aeff145ffa5515546dd22f7510dad91512e519f43b92b56514012
|
||||
F ext/intck/intck2.test d2457c7e5e5b688046d15ebe08a1e1427cc5e7a6dc8d6af215f42e8bcaf67304
|
||||
@@ -258,7 +258,7 @@ F ext/intck/intckcorrupt.test f6c302792326fb3db9dcfc70b554c55369bc4b52882eaaf039
|
||||
F ext/intck/intckfault.test cff3f75dff74abb3edfcb13f6aa53f6436746ab64b09fe5e2028f051e985efab
|
||||
F ext/intck/sqlite3intck.c 0d10df36e2b7b438aa80ecd3f5e584d41b747586b038258fe6b407f66b81e7c5
|
||||
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
|
||||
F ext/intck/test_intck.c 34243458378a12d1356c79219a03f244800533b3ab65b4a02861f0403364df12
|
||||
F ext/intck/test_intck.c 6050ed1f3e11eb58c66ed20f75af43dec0e37c88c9089b98b8a0a26022735dc3
|
||||
F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
|
||||
F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
|
||||
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
|
||||
@@ -385,13 +385,13 @@ F ext/misc/carray.h 503209952ccf2431c7fd899ebb92bf46bf7635b38aace42ec8aa1b8d7b6e
|
||||
F ext/misc/cksumvfs.c 3a7931dd30667be6348af919f3f9e6188dfd7646b42af8e399a499b327f5bd63
|
||||
F ext/misc/closure.c 0e04f52d93e678dd6f950f195f365992edf3c380df246f3d80425cba4c13891e
|
||||
F ext/misc/completion.c ef78835483b43ac18c96be312b90b615d8368189909be03513ab7a9338131298
|
||||
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
|
||||
F ext/misc/compress.c 2c79a74330e0e0ba6cb3f7397f8ba5af12d46377ef5d3ee075e12dd8a6ed57f0
|
||||
F ext/misc/csv.c 575c2c05fba0a451586a4d42c2c81e711780c41e797126f198d8d9e0a308dcdb
|
||||
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
|
||||
F ext/misc/decimal.c 172cf81a8634e6a0f0bedaf71a8372fee63348cf5a3c4e1b78bb233c35889fdc
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
|
||||
F ext/misc/fileio.c d88e60f63557d76d4e38acffda5556b2ab42e98f5d830897f22aba65930d975c
|
||||
F ext/misc/fileio.c 916638042f318701460485032e33981056747d0f92e6757aa9499f2363ea7047
|
||||
F ext/misc/fossildelta.c 8c026e086e406e2b69947f1856fa3b848fff5379962276430d10085b8756b05a
|
||||
F ext/misc/fuzzer.c 8b28acf1a7e95d50e332bdd47e792ff27054ad99d3f9bc2e91273814d4b31a5a
|
||||
F ext/misc/ieee754.c 62a90978204d2c956d5036eb89e548e736ca5fac0e965912867ddd7bb833256d
|
||||
@@ -411,13 +411,14 @@ F ext/misc/regexp.c 4bdd0045912f81c84908bd535ec5ad3b1c8540b4287c70ab840709636240
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
|
||||
F ext/misc/series.c 384f93a8a09cf45e1aa6575660cb580ed61d372c590aad05cdcd4a84fbd8f6ab
|
||||
F ext/misc/series.c d96e5aac21658c6b5d54f918ac140460ec7197734c1a4fba806950831a7b1e7a
|
||||
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
|
||||
F ext/misc/shathree.c 543af7ce71d391cd3a9ab6924a6a1124efc63211fd0f2e240dc4b56077ba88ac
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c c0aa7b80d6df45f7da59d912b38752bcac1af53a5766966160e6c5cdd397dbea
|
||||
F ext/misc/sqlar.c 53e7d48f68d699a24f1a92e68e71eca8b3a9ff991fe9588c2a05bde103c6e7b7
|
||||
F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634
|
||||
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
|
||||
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
|
||||
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
|
||||
F ext/misc/totype.c 75ed9827d19cc3b434fc2aeb60725d4d46e1534373615612a4d1cfdcc3d60922
|
||||
F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
|
||||
@@ -429,7 +430,7 @@ F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808
|
||||
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
|
||||
F ext/misc/zipfile.c 64cb3d98b6316586e6056d182051aa9d28fdedfbf4b908e6b7a7d70209b1db11
|
||||
F ext/misc/zipfile.c 5a3bf1b9cccb8e0da2389fe9e39e9c7f2b1351474b7e5090635f817d495eee3f
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
|
||||
@@ -478,13 +479,15 @@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69
|
||||
F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8
|
||||
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
|
||||
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
|
||||
F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949
|
||||
F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
|
||||
F ext/recover/dbdata.c a22ecd689f00ff2ad33b5633c4ef84c8f088c65faeac18d4eb73c128395c7aec
|
||||
F ext/recover/recover1.test e16d78e94183562abff569967b18b7c77451d7044365516cd0fe14713a284851
|
||||
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
|
||||
F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
|
||||
F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
|
||||
F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
|
||||
F ext/recover/recovercorrupt2.test b9b974f006340a1300b5a7e687bd6097c5238498181c6f92d87406a77ece430b
|
||||
F ext/recover/recovercorrupt2.test 1418f1710debc24ff38276cedfcea234beb37a34205708e7e3e6d76cc4a979db
|
||||
F ext/recover/recovercorrupt3.test 2e7b9a1b528ca23ed382cec6f64e3fcbbd0f8e852add7562397fd8df83f335d5
|
||||
F ext/recover/recovercorrupt4.test cc4a56086c50fba6a5b20db122a3f220195b3d4f11a86e0858c7f5f5d8ba58d1
|
||||
F ext/recover/recoverfault.test 9d9f88eeb222615a25e7514f234c950d46bee20d24cd8db49d8fff8d650dcfe1
|
||||
F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539ccabf63623e7bb7e09
|
||||
F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
|
||||
@@ -492,7 +495,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b
|
||||
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
|
||||
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
|
||||
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
|
||||
F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc
|
||||
F ext/recover/sqlite3recover.c 65ef0f56301a16c0536c9839fb7e23540c9c4f75da0afe3b7b4d163c8f624404
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
@@ -566,6 +569,8 @@ F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8
|
||||
F ext/session/sessionalter.test 460bdac2832a550519f6bc32e5db2c0cee94f335870aaf25a3a403a81ab20e17
|
||||
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
|
||||
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
|
||||
F ext/session/sessionchange.test 77c4702050f24270b58070e2cf01c95c3d232a3ef164b70f31974b386ce69903
|
||||
F ext/session/sessionconflict.test 8b8cbd98548e2e636ddc17d0986276f60e833fb865617dd4f88ea5bbe3a16b96
|
||||
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
|
||||
F ext/session/sessionfault.test 573bf027fb870d57bd4e7cf50822a3e4b17b2b923407438747aaa918dec57a09
|
||||
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
|
||||
@@ -580,14 +585,14 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
|
||||
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
|
||||
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c 829d468f0f3d2710aace56b0116a7ca3f414683ce78e3125ae5e21547a895078
|
||||
F ext/session/sqlite3session.h 4cf19a51975746d7cff2fdd74db8b769c570958e1c3639ac150d824ac1553b3e
|
||||
F ext/session/test_session.c 7b94ad945cd4afe6c73ee935aeb3d44b4446186e1729362af616c7695a5283d9
|
||||
F ext/session/sqlite3session.c c7473aafbd88f796391a8c25aa90975a8f3729ab7f4f8cf74ab9d3b014e10abe
|
||||
F ext/session/sqlite3session.h 683ccbf16e2c2521661fc4c1cf918ce57002039efbcabcd8097fa4bca569104b
|
||||
F ext/session/test_session.c 8bcc857125372e640f75ab63b4188080f9bbab92b65f86dfd160721c574b2044
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
|
||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/GNUmakefile 4bb4cf70a8153dd5b5fee17d724075c54174da630b424bbcf48c744633396f62
|
||||
F ext/wasm/GNUmakefile 21f015f342e4ed9b7ff632c10750512259d26c836a34f4f535673fae9a7c9fcc
|
||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -605,18 +610,18 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
|
||||
F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
|
||||
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||
F ext/wasm/api/sqlite3-api-glue.js 2d35660c52dcb4bb16d00c56553d34e7caa6ad30083938b515e6f9aa0b312fbb
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 365b3ae01a461dc974796823652ef1ecb1a9fac5df295ee1a78002cc77afb0d8
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
|
||||
F ext/wasm/api/sqlite3-api-glue.js 114085f4dceb28e06d20d3fb597b2501a4aa69f4b6cd29234f7cc1cf81d5b92d
|
||||
F ext/wasm/api/sqlite3-api-oo1.js c373cc04625a96bd3f01ce8ebeac93a5d38dbda6215818c925570df5a945565e
|
||||
F ext/wasm/api/sqlite3-api-prologue.js b347a0c5350247f90174a0ad9b9e72a99a5f837f31f78f60fcdb829b2ca30b63
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 5cc22a3c0d52828cb32aad8691488719f47d27567e63e8bc8b832d74371c352d
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 196ad83d36ca794e564044788c9d21b964679d63cad865f604da37c4afc9a285
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 8433ee332d5f5e39fb19427fccb7bad7f44aa99b5504daad3343fc128c311e78
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js ea5a6ca69d5fdf5f00f7ac1826990ce183fb191f6a6fab4d215b81910614b064
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309
|
||||
F ext/wasm/api/sqlite3-wasm.c afba6827a49151b564af5cf588a6bbd0401b16ef5cbe3269c66f676fee9ca92c
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bd89edfe42a4d7122a6d6d405c5423cf00aabba1f76f6ea8e2dba9c628ddd91a
|
||||
F ext/wasm/api/sqlite3-wasm.c 9267174b9b0591b4f71193542ab57adf95bb9415f7d3453acf4a8ca8052f5e6c
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46f303ba8ddd1b2f0a391798837beddfa72e8c897038c8047eda49ce7d5ed46b
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
@@ -626,7 +631,7 @@ F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25
|
||||
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
|
||||
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
|
||||
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
|
||||
F ext/wasm/common/whwasmutil.js 4c64594eecc7af4ae64259e95a71ba2a7edf118881aaff0bba86d0c7164e78e4
|
||||
F ext/wasm/common/whwasmutil.js f7b3461028899b923fb554029a5c980396b02800b742aabb44346dd8704fd11b
|
||||
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
|
||||
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
|
||||
F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32e7be5bf
|
||||
@@ -636,7 +641,7 @@ F ext/wasm/demo-worker1-promiser.c-pp.html 635cf90685805e21772a5f7a35d1ace80f98a
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.js fcc628cb42fcfaf07d250477801de1e6deb1e319d003976612a0db8d76b9fccc
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
|
||||
F ext/wasm/dist.make f2ce42305268fe33d4b50f6e4bb3daf4a60302a90736eee382f1b8af9ff32ec1
|
||||
F ext/wasm/dist.make 653e212c1e84aa3be168d62a10616ccea45ee9585b0192745d2706707a5248ce
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make 3c2eace29255d6ddd219f5d8cc2728cb28b9fe717ea80b6062c2a6178947a16b
|
||||
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||
@@ -662,7 +667,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||
F ext/wasm/tester1.c-pp.js 18331ec28d7e63c8e262a9872a8da3964d37b7ac22eabe0016af93f3c6f74cc4
|
||||
F ext/wasm/tester1.c-pp.js 6d0a9aa44a97b4aadd582e0999ce45a2671b854a12ea3205d1c908da6bd4bdef
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
@@ -670,7 +675,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk e5da4b6c13f2b15bba7f1efb0a47089dfdde0973e85a024785485655d59fd758
|
||||
F main.mk 9541ffdce424ddddb463e2480c3f1cb4067bbd3a6d2c84b3f083cb128a2fa721
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -689,28 +694,28 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c 285b493d843e7ba8ef78b6ae7d31238e904901dbc0c484f7904de4cf18fd8802
|
||||
F src/btree.c 8b42fc7d9efdb2df05c30e8f91ff6cfbd979724ae24bf90269028468b7a13333
|
||||
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c 02f5b25ca854c83b5015cb02b8c9ab236c60b1795528675aee8a5070e58da52a
|
||||
F src/build.c 237ccc0290d131d646be722f418e92ee0a38043aee25e7dfdc75f8ce5b3abe4e
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
|
||||
F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
|
||||
F src/date.c 13dd752847afb32ed70510ad7345a5b9c841f51ad904dba5d010f1fa3a6a324e
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
||||
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
||||
F src/expr.c 36071487e377356f1dd62e1e35870ed36a7212cb34ab1578b75d4a27ecdbfcb8
|
||||
F src/expr.c af9c9242be0df17280faf36c9810339de9df3d7a64ac8d33a5190a1400086ee5
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
||||
F src/func.c 283d4f3b2751a1d9339fd93a8a013d1948fd5f4474a3cab0955eb4fafd445d0f
|
||||
F src/fkey.c 852f93c0ef995e0c2b8983059a2b97151c194cc8259e21f5bc2b7ac508348c2a
|
||||
F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f
|
||||
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
|
||||
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c bc4d172b52a6167cd28797397a464c2cca9607dc047dfa0b5cf61687962e6964
|
||||
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
|
||||
F src/insert.c 4bd7c7e54a1062dcd0214b7a6296f7194eb10fb14d3ddca1ed20b01c2a86a18c
|
||||
F src/json.c 5b6a1d6015997b9ee848a32948720bdb26a0ef2de5a2127ebf7355ce66dbdc0d
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 8a59d297ec77e6b78550433bfccb95a1b26f2fb69aaaf233206e21579a1cfcc1
|
||||
@@ -734,33 +739,33 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 6227cbc4ac93046f121436886cf3712da6f4e2082af6314f976eeae1d86b794a
|
||||
F src/os_unix.c 2ea8d3ed496b8d1f9332a9505653424e5464fd797ea9d91f8e2e62f9dd0298d0
|
||||
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
|
||||
F src/pager.c 9beb80f6e330dd63c5d8ba0f7a7f3a55fff22067a68d424949c389bfc6fa0c56
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/parse.y 5bcef16094213efcc365a9d4dc4e3131f09251dc8838dce4a9e5f9764bff5b82
|
||||
F src/parse.y 2bd540b3b1e79017eb41fca2396633a75e7dd430c05383c61fe52c6f4e97c6d8
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||
F src/pragma.c f8f1845b42df684e9d31c5a1628c989a34939686049d7878bc5394ac1ae9cac4
|
||||
F src/pragma.c 52bfbf6dfd668b69b5eb9bd1186e3a67367c8453807150d6e75239229924f684
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
|
||||
F src/printf.c 87b67bba3662a0523f39ae6b084a3907109702f717c654d6cecb838af5cd57f1
|
||||
F src/prepare.c d99931f45416652895e502328ca49fe782cfc4e1ebdcda13b3736d991ebf42ce
|
||||
F src/printf.c 8b250972305e14b365561be5117ed0fd364e4fd58968776df1ce64c6280b90f9
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 6310bdfed32184cd3a5d6ba203dfee1ea323051cb38a6c2e80a5b79c069f4e87
|
||||
F src/resolve.c 7e8d23ce7cdbfedf351a47e759f2722e8182ca10fd7580be43f4ce1f1a228145
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 51893b3e34d38ad8d46b5010a6e380ca878b578be5001a640daa907336187424
|
||||
F src/shell.c.in 0354ca51eee5fbf6af394a7ef9f5ef6823ef45b743db65431f6777e4d5be2199
|
||||
F src/sqlite.h.in 32389e0d584551b300d0157881336162c14315a424cbf385c0d65eb7c2e31f7b
|
||||
F src/select.c ea0b75fce45e1f2c22f50ed2b6e2ddd7f66640948d0fc79a397917b4236a74af
|
||||
F src/shell.c.in ad27d1d990e9e5fb7ae8fc38a717e91f55233714f59723e5618baf4a2a3d2b65
|
||||
F src/sqlite.h.in cbd3e4177791a61c056fd81e37a5b21bb6c8cb2ea8cac558c625974673f50acf
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 4ca38e206befb3738d8cca97b6c6ee56c10f1c5bdb379ac5442d0f1a71b9fefa
|
||||
F src/sqliteInt.h af50738edf6a6cf9aa974b98d75bd0cedce607948dd10885ac6ae6cf5abae23c
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
|
||||
F src/test1.c 310f43eb17a9252a7790726ca652e4ea3197da17c19eec93b8578863a49dc7b4
|
||||
F src/test1.c 6bd203421934f2af4d4a4b673f609879f1e0c35164f7e21d0d6cdc0da2eeee8f
|
||||
F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab
|
||||
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
|
||||
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
|
||||
@@ -771,7 +776,7 @@ F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
||||
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
|
||||
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
|
||||
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c 1ee3d64b49ca06a9cb8195fab04f1a0585cafc90d25a2a817caa14e7caab22e7
|
||||
F src/test_bestindex.c 1b5a1407b66c5caa67cfe1d93d96de5ec5d9d516bc69eb512482f85c037858c3
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 5fa77ee6064ba546e144c4fea870c5ede2c54314616f81485c6a9c4192100c75
|
||||
@@ -813,33 +818,33 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 3f703cacdab728d7741e5a6ac242006d74fe1c2754d4f03ed889d7253259bd68
|
||||
F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
|
||||
F src/trigger.c 0905b96b04bb6658509f711a8207287f1315cdbc3df1a1b13ba6483c8e341c81
|
||||
F src/treeview.c 4b0e9131c33a08905bb56a424cd07d6146497f3277301962b4d3d997c2fd7d5f
|
||||
F src/trigger.c 0858f75818ed1580332db274f1032bcc5effe567cb132df5c5be8b1d800ca97f
|
||||
F src/update.c 732404a04d1737ef14bb6ec6b84f74edf28b3c102a92ae46b4855438a710efe7
|
||||
F src/upsert.c 2e60567a0e9e8520c18671b30712a88dc73534474304af94f32bb5f3ef65ac65
|
||||
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
|
||||
F src/util.c 4d6d7ebfe6772a1b950c97bbb1d1a72ad4874617ec498ab8aa73b7f5a43e44bb
|
||||
F src/util.c 5d1a0134cf4240648d1c6bb5cc8efaca0ea2b5d5c840985aec7e947271f04375
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vdbe.c 651aa0f31027d5d0a133eb7b41d11c41dc3b88ecb760b770430da0e477ae3b6c
|
||||
F src/vdbe.c b05777c3ff2ed7b9dfc347e7cdee18e371aa6811cef1fe83454691b0dbe2cc9f
|
||||
F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
|
||||
F src/vdbeaux.c 6385727adf51a649e4993098870a62c3945fe21dbc0e0fd9013772aff930b8fb
|
||||
F src/vdbeaux.c 6e37cb918506c28fe7657454fcbc2e01e66bfba4164f306c2f075fd5c5fef609
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbemem.c 213bf303826c0ef702e3a2a69dab2309d84b8381b822c6787885859fd7cd4c4e
|
||||
F src/vdbemem.c 831a244831eaa45335f9ae276b50a7a82ee10d8c46c2c72492d4eb8c98d94d89
|
||||
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
|
||||
F src/vtab.c 4c475fb672a6fe57830561e614dbee21a9a24a6f616d1cfcbe85f356a09f14ad
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c 5fb499d20494b7eecaadb7584634af9afcb374cb0524912b475fcb1712458a1b
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||
F src/where.c 09253e913dc1a93aa6e0e1a5d25a392b8fa39096cc30d230dd302264b3be0661
|
||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||
F src/wherecode.c e033875570f5d65b99fdb5189e597d91c8bc34f4196089fd50e6086d174035e7
|
||||
F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435
|
||||
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
||||
F src/where.c 94c2ae6c3ef6173492c9b400635fca8f04316cf6bea8face1d425753aba31b85
|
||||
F src/whereInt.h 002adc3aa2cc10733b9b27958fdbe893987cd989fab25a9853941c1f9b9b0a65
|
||||
F src/wherecode.c c9cac0b0b8e809c5e7e79d7796918907fb685ad99be2aaa9737f9787aa47349c
|
||||
F src/whereexpr.c 7d0d34b42b9edfd8e8ca66beb3a6ef63fe211c001af54caf2ccbcd989b783290
|
||||
F src/window.c 1e40ffc509bae21e466f6106382d238e91eb73edd4ba10e66ca4fd7af2b96896
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
||||
@@ -866,7 +871,7 @@ F test/altermalloc2.test 17fb3724c4b004c469c27dc4ef181608aa644555fbd3f3236767584
|
||||
F test/altermalloc3.test 8040e486368403f2fdd6fc3998258b499bd4cc2f3ddbb5f8f874cd436f076e81
|
||||
F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba
|
||||
F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
|
||||
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
|
||||
F test/altertab2.test fff90e3f01e8eb0e09282f538b8ec7cfeb035dbedbe570fe1983440f4613ad0e
|
||||
F test/altertab3.test b331ae34e69594e19605e3297805202d6156fcc8f75379dfd972a2e51cae8721
|
||||
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
@@ -905,7 +910,7 @@ F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e188
|
||||
F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
|
||||
F test/autoindex1.test d34caffb0384003ee28eae87679214c029e9be4b332d9649a79e0b94ab70502c
|
||||
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test dcd6b2f8bed2be67b131e2e671f892e971d934e24fd00988952d0e0a67e24aa7
|
||||
F test/autoindex3.test ca502c8050166ac6107a7b4fe4e951f4d3270a23a958af02b14f1b962b83c4b6
|
||||
F test/autoindex4.test 3c2105e9172920e26f950ba3c5823e4972190e022c1e6f260ba476b0af24c593
|
||||
F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2fee19a3
|
||||
F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df
|
||||
@@ -931,10 +936,11 @@ F test/bestindex4.test 3039894f2dad50f3a68443dffad1b44c9b067ac03870102df1ce3d9a4
|
||||
F test/bestindex5.test a0c90b2dad7836e80a01379e200e5f8ec9476d49b349af02c0dbff2fb75dc98d
|
||||
F test/bestindex6.test 16942535b551273f3ad9df8d7cc4b7f22b1fcd8882714358859eb049a6f99dd4
|
||||
F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c414b71e
|
||||
F test/bestindex8.test 333ad8c6a554b885a49b68c019166eda92b05f493a92b36b0acdf7f766d04dad
|
||||
F test/bestindex8.test b63a4f171a2c83d481bb14c431a8b72e85d27b2ffdaa0435a95d58ca941678f9
|
||||
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
|
||||
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
|
||||
F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
|
||||
F test/bestindexC.test 2df6ada16d8f00d9bb6a9664d9c323560aeed0e0ebc7a32b99d85d70037fd250
|
||||
F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@@ -964,7 +970,7 @@ F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
|
||||
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
|
||||
F test/capi2.test 4ee545824adc3eb33bf57ef89f77440b28188ec3da72e5425ff0fcdba32e8d5a
|
||||
F test/capi3.test 3910a73c38ac76d69778dd9eb481ab7cd6ed59117fc047b4f6056a5c72529de1
|
||||
F test/capi3.test 4892b5e53d2a6941edc9d204a0ab174dd66e8689282d9a15e4384561c3965945
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a490f7
|
||||
F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde
|
||||
@@ -993,7 +999,7 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
|
||||
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
|
||||
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
|
||||
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
|
||||
F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
|
||||
F test/colname.test 387e880eeac0889900f7b3e9703c375515f5d323f71fd4f2bb5428a4ac8e2023
|
||||
F test/columncount.test 6fe99c2f35738b0129357a1cf3fa483f76140f4cd8a89014c88c33c876d2638f
|
||||
F test/conflict.test b705cddf025a675d3c13d62fa78ab1e2696fb8e07a3d7cccce1596ff8b301492
|
||||
F test/conflict2.test 5557909ce683b1073982f5d1b61dfb1d41e369533bfdaf003180c5bc87282dd1
|
||||
@@ -1019,7 +1025,7 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
|
||||
F test/corruptI.test 9d8cbf6214e492abe9e822e759b9751ae336cec0a6fe3ff3b37bfbd8ff9c22ca
|
||||
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
|
||||
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
|
||||
F test/corruptL.test 504d90502d9993440226edc355d2275524b89064ea3df5ee5c27f7028ec59d07
|
||||
F test/corruptL.test 652fc8ac0763a6fd3eb28b951d481924167b2d9936083bcc68253b2274a0c8fe
|
||||
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
|
||||
F test/corruptN.test 7c099d153a554001b4fb829c799b01f2ea6276cbc32479131e0db0da4efd9cc4
|
||||
F test/cost.test cc434a026b1e9d0d98137a147e24e5daf1b1ad09e9ff7da63b34c83ddd136d92
|
||||
@@ -1068,7 +1074,7 @@ F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad
|
||||
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 691c9e850b0d0b56b66e7e235453198cb4cf0760e324b7403d3c5abbeab0a014
|
||||
F test/distinct2.test bb71cc7b5e58e895787f9910a788c254f679928d324732d063fe9bc202ecbe71
|
||||
F test/distinct2.test 931a242fccaa05f17232e23acc9b2debe42901d90db723ddca038f7758951b5f
|
||||
F test/distinctagg.test 40d7169ae5846caaf62c6e307d2ca3c333daf9b6f7cde888956a339a97afe85f
|
||||
F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52
|
||||
F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075
|
||||
@@ -1111,6 +1117,7 @@ F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/expr.test 5c06696478212e5a04e04b043f993373f6f8e5ce5a80f5548a84703b123b6caa
|
||||
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
|
||||
F test/exprfault.test da33606d799718e2f8e34efd0e5858884a1ad87f608774c552a7f5517cc27181
|
||||
F test/exprfault2.test c49e84273898969af5dbc4fe6a3f4335f14639799f343590336c9ddf84425965
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/external_reader.test c7d34694f1b25c32d866f56ac80c1e29edddc42b4ef90cad589263ffac2cde0c
|
||||
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
@@ -1200,7 +1207,7 @@ F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
|
||||
F test/fts3snippet2.test e79afeb1f673713f96d7fc5655726081975399d11e659d15553207be43301dc4
|
||||
F test/fts3snippet2.test 03f6738ab3897bea2ba6be424a0613872e167acbf37a66200d655d737b470f65
|
||||
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
@@ -1231,7 +1238,7 @@ F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401b
|
||||
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test b56905748ce0567c01d60005f3e6ad1af19453d224ba4730ee687d048fd09ef9
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func2.test 69f6ae3751b4ec765bdc3b803c0a255aa0f693f28f44805bef03e6b4a3fd242f
|
||||
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
||||
F test/func4.test a3f9062487dbd826776f54f4e0e9517fe8c3cf689af92735308965774d51fac5
|
||||
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
||||
@@ -1274,8 +1281,9 @@ F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
|
||||
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
|
||||
F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a
|
||||
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
|
||||
F test/in7.test 742b18c284cd9a9cd1347d3a8affeee44b8de11e875e91a1d40498c18ba16441
|
||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
||||
F test/incrblob3.test 67621a04b3084113bf38ce03797d70eca012d9d8f948193b8f655df577b0da6f
|
||||
@@ -1298,7 +1306,7 @@ F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a91
|
||||
F test/index9.test 2ac891806a4136ef3e91280477e23114e67575207dc331e6797fa0ed9379f997
|
||||
F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4974
|
||||
F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
|
||||
F test/indexexpr1.test 833f511213a5e26549186813f0566bd72f978177a7e6e98a2d2dd695de3c670d
|
||||
F test/indexexpr1.test 24fa85a12da384dd1d56f7b24e593c51a8a54b4c5e2e8bbb9e5fdf1099427faf
|
||||
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
|
||||
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@@ -1351,7 +1359,7 @@ F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb9
|
||||
F test/json/json-speed-check.sh 912ee03e700a65c827ee0c7b4752c21ec5ef69cf7679d2f482ca817042bead52 x
|
||||
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
|
||||
F test/json101.test 30db5b055b103ccabc53a29cfe6cda3345d07e171aeb25403dafa04f19e98b19
|
||||
F test/json102.test 557a46e16df1aa9bdbc4076a71a45814ea0e7503d6621d87d42a8c04cbc2b0ef
|
||||
F test/json102.test 4b3a0f94535f033239b67c13dbee8b47d2b5ee467e0f2fdab5eadf370bbe5fd3
|
||||
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
|
||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||
F test/json105.test 043838b56e68f3252a0dcf5be1689016f6f3f05056f8dcfcdc9d074f4d932988
|
||||
@@ -1365,7 +1373,7 @@ F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
|
||||
F test/lemon-test01.y 70110eff607ab137ccc851edb2bc7e14a6d4f246b5d2d25f82a60b69d87a9ff2
|
||||
F test/like.test 242ee7f5d08a031144c0daf63bbd7e7710c847ccf387a83347e0b61b3aa69526
|
||||
F test/like2.test d3be15fefee3e02fc88942a9b98f26c5339bbdef7783c90023c092c4955fe3d3
|
||||
F test/like3.test a76e5938fadbe6d32807284c796bafd869974a961057bc5fc5a28e06de98745c
|
||||
@@ -1380,7 +1388,7 @@ F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
|
||||
F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37b8
|
||||
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
|
||||
F test/lock5.test 626571313daef2c949ce002f861042d63d81119fa62a9e999721c8bbd85e1ec9
|
||||
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
|
||||
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
|
||||
F test/lock_common.tcl 2f3f7f2e9637f93ccf609df48ef5b27a50278b6b1cd752b445d52262e5841413
|
||||
@@ -1440,7 +1448,7 @@ F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a
|
||||
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
|
||||
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
|
||||
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
|
||||
F test/mmapcorrupt.test 0d89724591f22a376019f3df60d075b838dd2ba6dae6effb0be465c49cf86d4a
|
||||
F test/mmapcorrupt.test 470fb44fe92e99c1d23701d156f8c17865f5b027063c9119dcfdb842791f4465
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
|
||||
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
|
||||
@@ -1498,10 +1506,10 @@ F test/pendingrace.test 6aa33756b950c4529f79c4f3817a9a1e4025bd0d9961571a05c0279b
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 8bb6d3992c1c31ff6d5553d1e0693d642f7e19015648c6ae7034cb497d26bbd4
|
||||
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
|
||||
F test/pragma4.test 22834a228e59b80f5c15b519b710474859d91535002670ddb7cd13ac44b54e9a
|
||||
F test/pragma4.test f93f317693e90ece4ed0f5505d9035cae03f9fc684b718278433f2e48703f693
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
@@ -1529,7 +1537,7 @@ F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed13
|
||||
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
|
||||
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test 3ead782eddf51f573cdd43bcbb10d1b485ac095a19a76d16c43fd159ea9b7466
|
||||
F test/returning1.test 212cd4111bb941a60abf608f20250db666c21eb1bc4d49217e96c87ff3ab9d1a
|
||||
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
|
||||
@@ -1605,12 +1613,12 @@ F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 17a5ca9c6f24f807b2f505b4b38fcbce143d96cd8664c06c34bbbe0672bf7c30
|
||||
F test/shell2.test 56da24128304c9ab67da2964cc80beff7b35761c446ec6e6e98bff2775b15026
|
||||
F test/shell3.test 5ad4b2813717956414f2c0c8a2027895cd98ccf7dd54dbacbde4d4f5591ce5a1
|
||||
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
|
||||
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
|
||||
F test/shell5.test 5b2ab1c0540217773f939927c24163a56257446da3f564d4724042620bfea762
|
||||
F test/shell5.test 6a49440bddc33a132f856fb189e71228f8132963655d12a2c8b8a161263b9632
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell7.test 753c6ece5361df50025a50cadf378ea36db9cc05fb23d7a96cff7fa130626ef9
|
||||
F test/shell8.test 9b71d56a6f6fc62edd9163534ac21eaa328ad95f1b9026e7bd08d5b4621eacf6
|
||||
F test/shell8.test aea51ecbcd4494c746b096aeff51d841d04d5f0dc4b62eb42427f16109b87acd
|
||||
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
|
||||
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
@@ -1653,15 +1661,17 @@ F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae
|
||||
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
|
||||
F test/sqllimits1.test dee96a51b83ef866d06ec3c687d4c951d97b02549facc5be88c9dfcb215b98bf
|
||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||
F test/starschema1.test a84205f97fe278a015ac39546c86b97228d22043af28f3a2ef809e8d5637ce1d
|
||||
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
|
||||
F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408
|
||||
F test/statfault.test 064f43379e4992b5221b7d9ac887c313b3191f85cce605d78e416fc4045da64e
|
||||
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
|
||||
F test/stmtrand.test 340e2ea4841c5cdc02d36e33739769c5d907ab529b12bb535407def0e413ca17
|
||||
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
|
||||
F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
|
||||
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
|
||||
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
|
||||
F test/subquery.test 312c5d26304b0e93a56ba2cb9d4480b8a1c8217e3b2b8f8be2bfb0b2458ac3a7
|
||||
F test/subquery.test 903abf41049f8404256f7be24b3151328304a5b25162e17ab0079460237382fc
|
||||
F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
|
||||
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
|
||||
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
|
||||
@@ -1677,7 +1687,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test 54f27eacd054aa528a8b6e3331192c484104f30aaee351ad035f2b39a00f87c4
|
||||
F test/tabfunc01.test f150d206294471d20f50029e6b46b76b87a7a010b16dc57eb44245c76dd02802
|
||||
F test/table.test 7862a00b58b5541511a26757ea9c5c7c3f8298766e98aa099deec703d9c0a8e0
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
@@ -1690,7 +1700,7 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf
|
||||
F test/testrunner.tcl b48a8fc17e3b200244f53d60348afa7fe9482400d164e95709890743af9536d0
|
||||
F test/testrunner.tcl 1386667c04207d0a540ce1a9bc5ee0b734f7a3ba856c14a03943fb4f32de55bb
|
||||
F test/testrunner_data.tcl 3d36660cfd55ea5e20e661e8f94c0520feebcb437848f9b98b33c483cc479c0c
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
@@ -1861,7 +1871,7 @@ F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f4
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/transitive1.test f8ee983600b33d167da1885657f064aec404e1c0d0bc8765fdf163f4c749237a
|
||||
F test/trigger1.test 02cc64dc98278816c1c1ed8e472e18db8edbad88f37018bf46223e9614831963
|
||||
F test/trigger1.test 2834f8830a1ae338d95c2e3ea0c2a7bc4cda126cdeb715004cf0fd071892e44f
|
||||
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
|
||||
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
|
||||
@@ -1906,7 +1916,7 @@ F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af623
|
||||
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
|
||||
F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807
|
||||
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
|
||||
F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb25d3
|
||||
F test/upsert1.test beba4316fbd4b7b9d76784313f6129a548cfe7abea04d46db33e2efce1ab0ac2
|
||||
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
|
||||
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
|
||||
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
|
||||
@@ -1916,7 +1926,7 @@ F test/uri.test c1abaaaa28e9422d61e5f3f9cbc8ef993ec49fe802f581520731708561d49384
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
|
||||
F test/vacuum-into.test 35dc6f79b563f91c61822f61797363e97fed1bf28f1f722688b98d43f1980d76
|
||||
F test/vacuum-into.test 77845cee98770c416dae9b0da6bb3229753861f2da65c11b4f9715d081712d8a
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
|
||||
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
|
||||
@@ -1924,11 +1934,11 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
|
||||
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
||||
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
|
||||
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
||||
F test/values.test 6c2426de40cd397a8ab68d375b6964ab3bce1244bbb69f5d1ed3ccd0e039c1f3
|
||||
F test/values.test 0eda08a6ce6545f1ab012dff4cc72a7dd0fee2510f42444136bb2b2b5ed84bc0
|
||||
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
|
||||
F test/view.test 3c23d7a068e9e4a0c4e6907498042772adea725f0630c3d9638ffd4e5a08b92b
|
||||
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
|
||||
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
|
||||
F test/vt02.c 5b44ac67b1a283fedecf2d6e2ceda61e7a157f01d44dcb4490dcb1e87d057060
|
||||
@@ -1951,7 +1961,7 @@ F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtabJ.test a6aef49d558af90fae10565b29501f82a95781cb4f797f2d13e2d19f9b6bc77b
|
||||
F test/vtabK.test 13293177528fada1235c0112db0d187d754af1355c5a39371abd365104e3afbf
|
||||
F test/vtabL.test 49ec7342e8bfcb0d6c3d2443c619f430c609c042d5d7e6ddf52def65d6d1812f
|
||||
F test/vtabL.test c7b7f537978005d063fa2f53a3cd5a46ecf651ecd19970cb9ed4203698398deb
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
@@ -2022,12 +2032,13 @@ F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb
|
||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||
F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
|
||||
F test/wherelimit2.test b9e4bfe7b4d7c2f85f99cf2bd2c51369378d04b1f3d1b60557423752003bfd90
|
||||
F test/wherelimit3.test 22d73e046870cf8bbe15573eda6b432b07ebe64a88711f9f849c6b3667c1fae6
|
||||
F test/widetab1.test c296a98e123762de79917350e45fa33fdf88577a2571eb3a64c8bf7e44ef74d1
|
||||
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
|
||||
F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
|
||||
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test 5e8abe56a7d667eeddbba6de180086dcf69ed528d046447a25464f945ece101f
|
||||
F test/window1.test 79dc3b9a2226f622d7e104a1fc750d1c4c3c08d6147b59085bdbe05352947ffa
|
||||
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
|
||||
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
|
||||
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
|
||||
@@ -2145,7 +2156,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
|
||||
F tool/sqldiff.c 985452ffc8554baee0f945d078859d393a22abc0bbf553a9f12acae1b6e1fdd0
|
||||
F tool/sqldiff.c 1e0a2c264c2ad5aca745d35deee3c7715cb00c703839cfb0b85be079db55194c
|
||||
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
@@ -2184,8 +2195,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 287ff24b26a512ff7648679767e68244f6eef95df6a49c46ed1f2594030ed523
|
||||
R f668a18b739f9caf1d0ed3baa3bf6c8f
|
||||
U drh
|
||||
Z 70cb6868aa0f914c12631462fc26d140
|
||||
P 1e6fa95b88cace9e6cac476863d57cfd8de483f83c922ff964b77cbaee6e9ae4
|
||||
R 3a4a85834551db124c9a29a9adb094ef
|
||||
U dan
|
||||
Z c34dc91d8750434d9c55abc5758418d0
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
67594481379824823105939fea2ce1fe280667f6db91735ac78b4b6164a78dab
|
||||
9d63033bf46ddf0f4d9d4ef06d56357fe6165f2370cd19cf81c2f7f61ce224fc
|
||||
+37
-18
@@ -5143,6 +5143,12 @@ static int accessPayload(
|
||||
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
|
||||
pCur->curFlags |= BTCF_ValidOvfl;
|
||||
}else{
|
||||
/* Sanity check the validity of the overflow page cache */
|
||||
assert( pCur->aOverflow[0]==nextPage
|
||||
|| pCur->aOverflow[0]==0
|
||||
|| CORRUPT_DB );
|
||||
assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
|
||||
|
||||
/* If the overflow page-list cache has been allocated and the
|
||||
** entry for the first required overflow page is valid, skip
|
||||
** directly to it.
|
||||
@@ -5624,6 +5630,23 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
|
||||
** this flags are true for a consistent database.
|
||||
**
|
||||
** This routine is is called from within assert() statements only.
|
||||
** It is an internal verification routine and does not appear in production
|
||||
** builds.
|
||||
*/
|
||||
static int cursorIsAtLastEntry(BtCursor *pCur){
|
||||
int ii;
|
||||
for(ii=0; ii<pCur->iPage; ii++){
|
||||
if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
|
||||
}
|
||||
return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move the cursor to the last entry in the table. Return SQLITE_OK
|
||||
** on success. Set *pRes to 0 if the cursor actually points to something
|
||||
** or set *pRes to 1 if the table is empty.
|
||||
@@ -5652,18 +5675,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
|
||||
/* If the cursor already points to the last entry, this is a no-op. */
|
||||
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* This block serves to assert() that the cursor really does point
|
||||
** to the last entry in the b-tree. */
|
||||
int ii;
|
||||
for(ii=0; ii<pCur->iPage; ii++){
|
||||
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
|
||||
}
|
||||
assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
|
||||
testcase( pCur->ix!=pCur->pPage->nCell-1 );
|
||||
/* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
|
||||
assert( pCur->pPage->leaf );
|
||||
#endif
|
||||
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -5716,6 +5728,7 @@ int sqlite3BtreeTableMoveto(
|
||||
}
|
||||
if( pCur->info.nKey<intKey ){
|
||||
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
|
||||
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -7554,7 +7567,8 @@ static int rebuildPage(
|
||||
if( j>(u32)usableSize ){ j = 0; }
|
||||
memcpy(&pTmp[j], &aData[j], usableSize - j);
|
||||
|
||||
for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i; k++){}
|
||||
assert( pCArray->ixNx[NB*2-1]>i );
|
||||
for(k=0; pCArray->ixNx[k]<=i; k++){}
|
||||
pSrcEnd = pCArray->apEnd[k];
|
||||
|
||||
pData = pEnd;
|
||||
@@ -7637,7 +7651,8 @@ static int pageInsertArray(
|
||||
u8 *pEnd; /* Maximum extent of cell data */
|
||||
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
|
||||
if( iEnd<=iFirst ) return 0;
|
||||
for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i ; k++){}
|
||||
assert( pCArray->ixNx[NB*2-1]>i );
|
||||
for(k=0; pCArray->ixNx[k]<=i ; k++){}
|
||||
pEnd = pCArray->apEnd[k];
|
||||
while( 1 /*Exit by break*/ ){
|
||||
int sz, rc;
|
||||
@@ -7922,6 +7937,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
|
||||
b.szCell = &szCell;
|
||||
b.apEnd[0] = pPage->aDataEnd;
|
||||
b.ixNx[0] = 2;
|
||||
b.ixNx[NB*2-1] = 0x7fffffff;
|
||||
rc = rebuildPage(&b, 0, 1, pNew);
|
||||
if( NEVER(rc) ){
|
||||
releasePage(pNew);
|
||||
@@ -8157,7 +8173,9 @@ static int balance_nonroot(
|
||||
CellArray b; /* Parsed information on cells being balanced */
|
||||
|
||||
memset(abDone, 0, sizeof(abDone));
|
||||
memset(&b, 0, sizeof(b));
|
||||
assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
|
||||
memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
|
||||
b.ixNx[NB*2-1] = 0x7fffffff;
|
||||
pBt = pParent->pBt;
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
|
||||
@@ -8748,7 +8766,8 @@ static int balance_nonroot(
|
||||
iOvflSpace += sz;
|
||||
assert( sz<=pBt->maxLocal+23 );
|
||||
assert( iOvflSpace <= (int)pBt->pageSize );
|
||||
for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
|
||||
assert( b.ixNx[NB*2-1]>j );
|
||||
for(k=0; b.ixNx[k]<=j; k++){}
|
||||
pSrcEnd = b.apEnd[k];
|
||||
if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
@@ -9521,7 +9540,7 @@ int sqlite3BtreeInsert(
|
||||
}else if( loc<0 && pPage->nCell>0 ){
|
||||
assert( pPage->leaf );
|
||||
idx = ++pCur->ix;
|
||||
pCur->curFlags &= ~BTCF_ValidNKey;
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
}else{
|
||||
assert( pPage->leaf );
|
||||
}
|
||||
@@ -9551,7 +9570,7 @@ int sqlite3BtreeInsert(
|
||||
*/
|
||||
if( pPage->nOverflow ){
|
||||
assert( rc==SQLITE_OK );
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey);
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
rc = balance(pCur);
|
||||
|
||||
/* Must make sure nOverflow is reset to zero even if the balance()
|
||||
|
||||
+4
-6
@@ -2927,9 +2927,6 @@ void sqlite3EndTable(
|
||||
sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
|
||||
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
|
||||
sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)",
|
||||
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
|
||||
}
|
||||
|
||||
/* Add the table to the in-memory representation of the database.
|
||||
@@ -3067,8 +3064,9 @@ create_view_fail:
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
/*
|
||||
** The Table structure pTable is really a VIEW. Fill in the names of
|
||||
** the columns of the view in the pTable structure. Return the number
|
||||
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
|
||||
** the columns of the view in the pTable structure. Return non-zero if
|
||||
** there are errors. If an error is seen an error message is left
|
||||
** in pParse->zErrMsg.
|
||||
*/
|
||||
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
Table *pSelTab; /* A fake table from which we get the result set */
|
||||
@@ -3191,7 +3189,7 @@ static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
sqlite3DeleteColumnNames(db, pTable);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIEW */
|
||||
return nErr;
|
||||
return nErr + pParse->nErr;
|
||||
}
|
||||
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
assert( pTable!=0 );
|
||||
|
||||
+2
-2
@@ -667,8 +667,8 @@ static const struct {
|
||||
/* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
|
||||
/* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
|
||||
/* 3 */ { 3, "day", 5373485.0, 86400.0 },
|
||||
/* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
|
||||
/* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
|
||||
/* 4 */ { 5, "month", 176546.0, 2592000.0 },
|
||||
/* 5 */ { 4, "year", 14713.0, 31536000.0 },
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+55
-21
@@ -1368,6 +1368,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
|
||||
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
assert( p!=0 );
|
||||
assert( db!=0 );
|
||||
exprDeleteRestart:
|
||||
assert( !ExprUseUValue(p) || p->u.iValue>=0 );
|
||||
assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
|
||||
assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
|
||||
@@ -1383,7 +1384,6 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
|
||||
/* The Expr.x union is never used at the same time as Expr.pRight */
|
||||
assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
|
||||
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
|
||||
if( p->pRight ){
|
||||
assert( !ExprHasProperty(p, EP_WinFunc) );
|
||||
sqlite3ExprDeleteNN(db, p->pRight);
|
||||
@@ -1398,6 +1398,19 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if( p->pLeft && p->op!=TK_SELECT_COLUMN ){
|
||||
Expr *pLeft = p->pLeft;
|
||||
if( !ExprHasProperty(p, EP_Static)
|
||||
&& !ExprHasProperty(pLeft, EP_Static)
|
||||
){
|
||||
/* Avoid unnecessary recursion on unary operators */
|
||||
sqlite3DbNNFreeNN(db, p);
|
||||
p = pLeft;
|
||||
goto exprDeleteRestart;
|
||||
}else{
|
||||
sqlite3ExprDeleteNN(db, pLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !ExprHasProperty(p, EP_Static) ){
|
||||
sqlite3DbNNFreeNN(db, p);
|
||||
@@ -1430,11 +1443,11 @@ void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
|
||||
**
|
||||
** The pExpr might be deleted immediately on an OOM error.
|
||||
**
|
||||
** The deferred delete is (currently) implemented by adding the
|
||||
** pExpr to the pParse->pConstExpr list with a register number of 0.
|
||||
** Return 0 if the delete was successfully deferred. Return non-zero
|
||||
** if the delete happened immediately because of an OOM.
|
||||
*/
|
||||
void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
|
||||
sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
|
||||
int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
|
||||
return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
|
||||
}
|
||||
|
||||
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
|
||||
@@ -2393,7 +2406,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction(
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Continue;
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
|
||||
@@ -2776,8 +2789,12 @@ int sqlite3ExprContainsSubquery(Expr *p){
|
||||
** to fit in a 32-bit integer, return 1 and put the value of the integer
|
||||
** in *pValue. If the expression is not an integer or if it is too big
|
||||
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
|
||||
**
|
||||
** If the pParse pointer is provided, then allow the expression p to be
|
||||
** a parameter (TK_VARIABLE) that is bound to an integer.
|
||||
** But if pParse is NULL, then p must be a pure integer literal.
|
||||
*/
|
||||
int sqlite3ExprIsInteger(const Expr *p, int *pValue){
|
||||
int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
|
||||
int rc = 0;
|
||||
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
|
||||
|
||||
@@ -2792,18 +2809,38 @@ int sqlite3ExprIsInteger(const Expr *p, int *pValue){
|
||||
}
|
||||
switch( p->op ){
|
||||
case TK_UPLUS: {
|
||||
rc = sqlite3ExprIsInteger(p->pLeft, pValue);
|
||||
rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
|
||||
break;
|
||||
}
|
||||
case TK_UMINUS: {
|
||||
int v = 0;
|
||||
if( sqlite3ExprIsInteger(p->pLeft, &v) ){
|
||||
if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
|
||||
assert( ((unsigned int)v)!=0x80000000 );
|
||||
*pValue = -v;
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_VARIABLE: {
|
||||
sqlite3_value *pVal;
|
||||
if( pParse==0 ) break;
|
||||
if( NEVER(pParse->pVdbe==0) ) break;
|
||||
if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
|
||||
sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
|
||||
pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
|
||||
SQLITE_AFF_BLOB);
|
||||
if( pVal ){
|
||||
if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
|
||||
sqlite3_int64 vv = sqlite3_value_int64(pVal);
|
||||
if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
|
||||
*pValue = (int)vv;
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
sqlite3ValueFree(pVal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return rc;
|
||||
@@ -4230,7 +4267,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
||||
** register iReg. The caller must ensure that iReg already contains
|
||||
** the correct value for the expression.
|
||||
*/
|
||||
static void exprToRegister(Expr *pExpr, int iReg){
|
||||
void sqlite3ExprToRegister(Expr *pExpr, int iReg){
|
||||
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
|
||||
if( NEVER(p==0) ) return;
|
||||
p->op2 = p->op;
|
||||
@@ -5239,7 +5276,7 @@ expr_code_doover:
|
||||
break;
|
||||
}
|
||||
testcase( pX->op==TK_COLUMN );
|
||||
exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
testcase( regFree1==0 );
|
||||
memset(&opCompare, 0, sizeof(opCompare));
|
||||
opCompare.op = TK_EQ;
|
||||
@@ -5293,15 +5330,14 @@ expr_code_doover:
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
if( pExpr->affExpr==OE_Ignore ){
|
||||
sqlite3VdbeAddOp4(
|
||||
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
sqlite3HaltConstraint(pParse,
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
sqlite3VdbeAddOp3(v, OP_Halt,
|
||||
pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
|
||||
pExpr->affExpr, pExpr->u.zToken, 0, 0);
|
||||
pExpr->affExpr, r1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -5590,7 +5626,7 @@ static void exprCodeBetween(
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = pDel;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
if( xJump ){
|
||||
xJump(pParse, &exprAnd, dest, jumpIfNull);
|
||||
}else{
|
||||
@@ -6668,9 +6704,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
|
||||
&& pAggInfo->aCol[iAgg].pCExpr==pExpr
|
||||
){
|
||||
pExpr = sqlite3ExprDup(db, pExpr, 0);
|
||||
if( pExpr ){
|
||||
if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
|
||||
pAggInfo->aCol[iAgg].pCExpr = pExpr;
|
||||
sqlite3ExprDeferredDelete(pParse, pExpr);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@@ -6679,9 +6714,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
|
||||
&& pAggInfo->aFunc[iAgg].pFExpr==pExpr
|
||||
){
|
||||
pExpr = sqlite3ExprDup(db, pExpr, 0);
|
||||
if( pExpr ){
|
||||
if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
|
||||
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
|
||||
sqlite3ExprDeferredDelete(pParse, pExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -1328,7 +1328,8 @@ static Trigger *fkActionTrigger(
|
||||
SrcList *pSrc;
|
||||
Expr *pRaise;
|
||||
|
||||
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
|
||||
pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
|
||||
pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
|
||||
if( pRaise ){
|
||||
pRaise->affExpr = OE_Abort;
|
||||
}
|
||||
|
||||
@@ -2206,6 +2206,8 @@ static void groupConcatValue(sqlite3_context *context){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
|
||||
sqlite3_result_text(context, "", 1, SQLITE_STATIC);
|
||||
}else{
|
||||
const char *zText = sqlite3_str_value(pAccum);
|
||||
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
|
||||
@@ -2545,6 +2547,7 @@ static void fpdecodeFunc(
|
||||
x = sqlite3_value_double(argv[0]);
|
||||
y = sqlite3_value_int(argv[1]);
|
||||
z = sqlite3_value_int(argv[2]);
|
||||
if( z<=0 ) z = 1;
|
||||
sqlite3FpDecode(&s, x, y, z);
|
||||
if( s.isSpecial==2 ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
|
||||
|
||||
+4
-1
@@ -3182,7 +3182,10 @@ static int xferOptimization(
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
|
||||
if( pDest->pCheck
|
||||
&& (db->mDbFlags & DBFLAG_Vacuum)==0
|
||||
&& sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
|
||||
){
|
||||
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
|
||||
}
|
||||
#endif
|
||||
|
||||
+7
-8
@@ -3795,13 +3795,6 @@ static void jsonArrayLengthFunc(
|
||||
jsonParseFree(p);
|
||||
}
|
||||
|
||||
/* True if the string is all digits */
|
||||
static int jsonAllDigits(const char *z, int n){
|
||||
int i;
|
||||
for(i=0; i<n && sqlite3Isdigit(z[i]); i++){}
|
||||
return i==n;
|
||||
}
|
||||
|
||||
/* True if the string is all alphanumerics and underscores */
|
||||
static int jsonAllAlphanum(const char *z, int n){
|
||||
int i;
|
||||
@@ -3864,10 +3857,16 @@ static void jsonExtractFunc(
|
||||
** NUMBER ==> $[NUMBER] // PG compatible
|
||||
** LABEL ==> $.LABEL // PG compatible
|
||||
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
|
||||
**
|
||||
** Updated 2024-05-27: If the NUMBER is negative, then PG counts from
|
||||
** the right of the array. Hence for negative NUMBER:
|
||||
**
|
||||
** NUMBER ==> $[#NUMBER] // PG compatible
|
||||
*/
|
||||
jsonStringInit(&jx, ctx);
|
||||
if( jsonAllDigits(zPath, nPath) ){
|
||||
if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
|
||||
jsonAppendRawNZ(&jx, "[", 1);
|
||||
if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1);
|
||||
jsonAppendRaw(&jx, zPath, nPath);
|
||||
jsonAppendRawNZ(&jx, "]", 2);
|
||||
}else if( jsonAllAlphanum(zPath, nPath) ){
|
||||
|
||||
+14
-18
@@ -2279,26 +2279,22 @@ static int nolockClose(sqlite3_file *id) {
|
||||
|
||||
/*
|
||||
** This routine checks if there is a RESERVED lock held on the specified
|
||||
** file by this or any other process. If such a lock is held, set *pResOut
|
||||
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
||||
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
||||
**
|
||||
** In dotfile locking, either a lock exists or it does not. So in this
|
||||
** variation of CheckReservedLock(), *pResOut is set to true if any lock
|
||||
** is held on the file and false if the file is unlocked.
|
||||
** file by this or any other process. If the caller holds a SHARED
|
||||
** or greater lock when it is called, then it is assumed that no other
|
||||
** client may hold RESERVED. Or, if the caller holds no lock, then it
|
||||
** is assumed another client holds RESERVED if the lock-file exists.
|
||||
*/
|
||||
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
int rc = SQLITE_OK;
|
||||
int reserved = 0;
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
|
||||
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
||||
|
||||
assert( pFile );
|
||||
reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
|
||||
OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
|
||||
*pResOut = reserved;
|
||||
return rc;
|
||||
if( pFile->eFileLock>=SHARED_LOCK ){
|
||||
*pResOut = 0;
|
||||
}else{
|
||||
*pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
|
||||
}
|
||||
OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3987,7 +3983,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
|
||||
|
||||
/* Forward declaration */
|
||||
static int unixGetTempname(int nBuf, char *zBuf);
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
|
||||
static int unixFcntlExternalReader(unixFile*, int*);
|
||||
#endif
|
||||
|
||||
@@ -4114,7 +4110,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
|
||||
|
||||
case SQLITE_FCNTL_EXTERNAL_READER: {
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
|
||||
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
|
||||
#else
|
||||
*(int*)pArg = 0;
|
||||
@@ -4287,7 +4283,7 @@ static int unixGetpagesize(void){
|
||||
|
||||
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
|
||||
|
||||
/*
|
||||
** Object used to represent an shared memory buffer.
|
||||
|
||||
+1
-1
@@ -7087,7 +7087,7 @@ sqlite3_file *sqlite3PagerFile(Pager *pPager){
|
||||
** This will be either the rollback journal or the WAL file.
|
||||
*/
|
||||
sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
|
||||
#if SQLITE_OMIT_WAL
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
return pPager->jfd;
|
||||
#else
|
||||
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
|
||||
|
||||
+18
-7
@@ -236,11 +236,13 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
|
||||
// improve performance and reduce the executable size. The goal here is
|
||||
// to get the "jump" operations in ISNULL through ESCAPE to have numeric
|
||||
// values that are early enough so that all jump operations are clustered
|
||||
// at the beginning.
|
||||
// at the beginning. Also, operators like NE and EQ need to be adjacent,
|
||||
// and all of the comparison operators need to be clustered together.
|
||||
// Various assert() statements throughout the code enforce these restrictions.
|
||||
//
|
||||
%token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST.
|
||||
%token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL.
|
||||
%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
|
||||
%token OR AND NOT IS ISNOT MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
|
||||
%token GT LE LT GE ESCAPE.
|
||||
|
||||
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
|
||||
@@ -1282,8 +1284,17 @@ expr(A) ::= NOT(B) expr(X).
|
||||
expr(A) ::= BITNOT(B) expr(X).
|
||||
{A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/}
|
||||
expr(A) ::= PLUS|MINUS(B) expr(X). [BITNOT] {
|
||||
A = sqlite3PExpr(pParse, @B==TK_PLUS ? TK_UPLUS : TK_UMINUS, X, 0);
|
||||
/*A-overwrites-B*/
|
||||
Expr *p = X;
|
||||
u8 op = @B + (TK_UPLUS-TK_PLUS);
|
||||
assert( TK_UPLUS>TK_PLUS );
|
||||
assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) );
|
||||
if( p && p->op==TK_UPLUS ){
|
||||
p->op = op;
|
||||
A = p;
|
||||
}else{
|
||||
A = sqlite3PExpr(pParse, op, p, 0);
|
||||
/*A-overwrites-B*/
|
||||
}
|
||||
}
|
||||
|
||||
expr(A) ::= expr(B) PTR(C) expr(D). {
|
||||
@@ -1649,8 +1660,8 @@ expr(A) ::= RAISE LP IGNORE RP. {
|
||||
A->affExpr = OE_Ignore;
|
||||
}
|
||||
}
|
||||
expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. {
|
||||
A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1);
|
||||
expr(A) ::= RAISE LP raisetype(T) COMMA expr(Z) RP. {
|
||||
A = sqlite3PExpr(pParse, TK_RAISE, Z, 0);
|
||||
if( A ) {
|
||||
A->affExpr = (char)T;
|
||||
}
|
||||
@@ -1929,8 +1940,8 @@ filter_clause(A) ::= FILTER LP WHERE expr(X) RP. { A = X; }
|
||||
TRUEFALSE /* True or false keyword */
|
||||
ISNOT /* Combination of IS and NOT */
|
||||
FUNCTION /* A function invocation */
|
||||
UMINUS /* Unary minus */
|
||||
UPLUS /* Unary plus */
|
||||
UMINUS /* Unary minus */
|
||||
TRUTH /* IS TRUE or IS FALSE or IS NOT TRUE or IS NOT FALSE */
|
||||
REGISTER /* Reference to a VDBE register */
|
||||
VECTOR /* Vector */
|
||||
|
||||
+2
-1
@@ -1703,7 +1703,7 @@ void sqlite3Pragma(
|
||||
/* Set the maximum error count */
|
||||
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
|
||||
if( zRight ){
|
||||
if( sqlite3GetInt32(zRight, &mxErr) ){
|
||||
if( sqlite3GetInt32(pValue->z, &mxErr) ){
|
||||
if( mxErr<=0 ){
|
||||
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
|
||||
}
|
||||
@@ -2911,6 +2911,7 @@ static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
|
||||
int i;
|
||||
sqlite3_finalize(pCsr->pPragma);
|
||||
pCsr->pPragma = 0;
|
||||
pCsr->iRowid = 0;
|
||||
for(i=0; i<ArraySize(pCsr->azArg); i++){
|
||||
sqlite3_free(pCsr->azArg[i]);
|
||||
pCsr->azArg[i] = 0;
|
||||
|
||||
+7
-1
@@ -633,7 +633,13 @@ void *sqlite3ParserAddCleanup(
|
||||
void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
|
||||
void *pPtr /* Pointer to object to be cleaned up */
|
||||
){
|
||||
ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
|
||||
ParseCleanup *pCleanup;
|
||||
if( sqlite3FaultSim(300) ){
|
||||
pCleanup = 0;
|
||||
sqlite3OomFault(pParse->db);
|
||||
}else{
|
||||
pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
|
||||
}
|
||||
if( pCleanup ){
|
||||
pCleanup->pNext = pParse->pCleanup;
|
||||
pParse->pCleanup = pCleanup;
|
||||
|
||||
+1
-1
@@ -857,7 +857,7 @@ void sqlite3_str_vappendf(
|
||||
sqlite3_str_appendall(pAccum, pItem->zAlias);
|
||||
}else{
|
||||
Select *pSel = pItem->pSelect;
|
||||
assert( pSel!=0 );
|
||||
assert( pSel!=0 ); /* Because of tag-20240424-1 */
|
||||
if( pSel->selFlags & SF_NestedFrom ){
|
||||
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
|
||||
}else if( pSel->selFlags & SF_MultiValue ){
|
||||
|
||||
+16
-12
@@ -228,7 +228,7 @@ static void extendFJMatch(
|
||||
static SQLITE_NOINLINE int isValidSchemaTableName(
|
||||
const char *zTab, /* Name as it appears in the SQL */
|
||||
Table *pTab, /* The schema table we are trying to match */
|
||||
Schema *pSchema /* non-NULL if a database qualifier is present */
|
||||
const char *zDb /* non-NULL if a database qualifier is present */
|
||||
){
|
||||
const char *zLegacy;
|
||||
assert( pTab!=0 );
|
||||
@@ -239,7 +239,7 @@ static SQLITE_NOINLINE int isValidSchemaTableName(
|
||||
if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
|
||||
return 1;
|
||||
}
|
||||
if( pSchema==0 ) return 0;
|
||||
if( zDb==0 ) return 0;
|
||||
if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
|
||||
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
|
||||
}else{
|
||||
@@ -422,7 +422,7 @@ static int lookupName(
|
||||
}
|
||||
}else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
|
||||
if( pTab->tnum!=1 ) continue;
|
||||
if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
|
||||
if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue;
|
||||
}
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
if( IN_RENAME_OBJECT && pItem->zAlias ){
|
||||
@@ -528,7 +528,8 @@ static int lookupName(
|
||||
if( pParse->bReturning ){
|
||||
if( (pNC->ncFlags & NC_UBaseReg)!=0
|
||||
&& ALWAYS(zTab==0
|
||||
|| sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
|
||||
|| sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0
|
||||
|| isValidSchemaTableName(zTab, pParse->pTriggerTab, 0))
|
||||
){
|
||||
pExpr->iTable = op!=TK_DELETE;
|
||||
pTab = pParse->pTriggerTab;
|
||||
@@ -827,8 +828,12 @@ static int lookupName(
|
||||
** If a generated column is referenced, set bits for every column
|
||||
** of the table.
|
||||
*/
|
||||
if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){
|
||||
pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
|
||||
if( pMatch ){
|
||||
if( pExpr->iColumn>=0 ){
|
||||
pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
|
||||
}else{
|
||||
pMatch->fg.rowidUsed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pExpr->op = eNewExprOp;
|
||||
@@ -1280,11 +1285,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){
|
||||
is_agg = 1;
|
||||
}
|
||||
#endif
|
||||
sqlite3WalkExprList(pWalker, pList);
|
||||
if( is_agg ){
|
||||
if( pExpr->pLeft ){
|
||||
@@ -1502,7 +1505,7 @@ static int resolveOrderByTermToExprList(
|
||||
int rc; /* Return code from subprocedures */
|
||||
u8 savedSuppErr; /* Saved value of db->suppressErr */
|
||||
|
||||
assert( sqlite3ExprIsInteger(pE, &i)==0 );
|
||||
assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
|
||||
pEList = pSelect->pEList;
|
||||
|
||||
/* Resolve all names in the ORDER BY term expression
|
||||
@@ -1601,7 +1604,7 @@ static int resolveCompoundOrderBy(
|
||||
if( pItem->fg.done ) continue;
|
||||
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
|
||||
if( NEVER(pE==0) ) continue;
|
||||
if( sqlite3ExprIsInteger(pE, &iCol) ){
|
||||
if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
|
||||
if( iCol<=0 || iCol>pEList->nExpr ){
|
||||
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
|
||||
return 1;
|
||||
@@ -1786,7 +1789,7 @@ static int resolveOrderGroupBy(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( sqlite3ExprIsInteger(pE2, &iCol) ){
|
||||
if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
|
||||
/* The ORDER BY term is an integer constant. Again, set the column
|
||||
** number so that sqlite3ResolveOrderGroupBy() will convert the
|
||||
** order-by term to a copy of the result-set expression */
|
||||
@@ -1889,6 +1892,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
if( pOuterNC ) pOuterNC->nNestedSelect++;
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
SrcItem *pItem = &p->pSrc->a[i];
|
||||
assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
|
||||
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
|
||||
int nRef = pOuterNC ? pOuterNC->nRef : 0;
|
||||
const char *zSavedContext = pParse->zAuthContext;
|
||||
|
||||
+33
-14
@@ -2324,8 +2324,7 @@ void sqlite3SubqueryColumnTypes(
|
||||
NameContext sNC;
|
||||
|
||||
assert( pSelect!=0 );
|
||||
testcase( (pSelect->selFlags & SF_Resolved)==0 );
|
||||
assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT );
|
||||
assert( (pSelect->selFlags & SF_Resolved)!=0 );
|
||||
assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
|
||||
assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
|
||||
if( db->mallocFailed || IN_RENAME_OBJECT ) return;
|
||||
@@ -2336,17 +2335,22 @@ void sqlite3SubqueryColumnTypes(
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
const char *zType;
|
||||
i64 n;
|
||||
int m = 0;
|
||||
Select *pS2 = pSelect;
|
||||
pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
|
||||
p = a[i].pExpr;
|
||||
/* pCol->szEst = ... // Column size est for SELECT tables never used */
|
||||
pCol->affinity = sqlite3ExprAffinity(p);
|
||||
while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){
|
||||
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
|
||||
pS2 = pS2->pNext;
|
||||
pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr);
|
||||
}
|
||||
if( pCol->affinity<=SQLITE_AFF_NONE ){
|
||||
pCol->affinity = aff;
|
||||
}
|
||||
if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
|
||||
int m = 0;
|
||||
Select *pS2;
|
||||
for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
|
||||
if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){
|
||||
for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){
|
||||
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
|
||||
}
|
||||
if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
|
||||
@@ -2376,12 +2380,12 @@ void sqlite3SubqueryColumnTypes(
|
||||
}
|
||||
}
|
||||
if( zType ){
|
||||
i64 m = sqlite3Strlen30(zType);
|
||||
const i64 k = sqlite3Strlen30(zType);
|
||||
n = sqlite3Strlen30(pCol->zCnName);
|
||||
pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
|
||||
pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2);
|
||||
pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
|
||||
if( pCol->zCnName ){
|
||||
memcpy(&pCol->zCnName[n+1], zType, m+1);
|
||||
memcpy(&pCol->zCnName[n+1], zType, k+1);
|
||||
pCol->colFlags |= COLFLAG_HASTYPE;
|
||||
}
|
||||
}
|
||||
@@ -2488,7 +2492,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
p->iLimit = iLimit = ++pParse->nMem;
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
assert( v!=0 );
|
||||
if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
|
||||
if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
if( n==0 ){
|
||||
@@ -2968,7 +2972,7 @@ static int multiSelect(
|
||||
p->pPrior = pPrior;
|
||||
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
||||
if( p->pLimit
|
||||
&& sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
|
||||
&& sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
|
||||
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
|
||||
){
|
||||
p->nSelectRow = sqlite3LogEst((u64)nLimit);
|
||||
@@ -6407,8 +6411,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
|
||||
if( p->selFlags & SF_HasTypeInfo ) return;
|
||||
p->selFlags |= SF_HasTypeInfo;
|
||||
pParse = pWalker->pParse;
|
||||
testcase( (p->selFlags & SF_Resolved)==0 );
|
||||
assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT );
|
||||
assert( (p->selFlags & SF_Resolved) );
|
||||
pTabList = p->pSrc;
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab = pFrom->pTab;
|
||||
@@ -7844,12 +7847,18 @@ int sqlite3Select(
|
||||
*/
|
||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||
&& OptimizationEnabled(db, SQLITE_GroupByOrder)
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
&& p->pWin==0
|
||||
#endif
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
if( pGroupBy ){
|
||||
for(i=0; i<pGroupBy->nExpr; i++){
|
||||
pGroupBy->a[i].u.x.iOrderByCol = i+1;
|
||||
}
|
||||
}
|
||||
p->selFlags |= SF_Aggregate;
|
||||
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
|
||||
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
||||
@@ -8312,12 +8321,22 @@ int sqlite3Select(
|
||||
sortOut, sortPTab);
|
||||
}
|
||||
for(j=0; j<pGroupBy->nExpr; j++){
|
||||
int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
|
||||
|
||||
if( groupBySort ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
|
||||
}else{
|
||||
pAggInfo->directMode = 1;
|
||||
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
|
||||
}
|
||||
|
||||
if( iOrderByCol ){
|
||||
Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
|
||||
Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
|
||||
if( ALWAYS(pBase!=0) && pBase->op!=TK_AGG_COLUMN ){
|
||||
sqlite3ExprToRegister(pX, iAMem+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
|
||||
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
|
||||
@@ -8333,9 +8352,9 @@ int sqlite3Select(
|
||||
** and resets the aggregate accumulator registers in preparation
|
||||
** for the next GROUP BY batch.
|
||||
*/
|
||||
sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
|
||||
VdbeComment((v, "output one row"));
|
||||
sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
|
||||
VdbeComment((v, "check abort flag"));
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||
|
||||
+53
-19
@@ -1221,9 +1221,9 @@ INCLUDE ../ext/misc/sqlar.c
|
||||
#endif
|
||||
INCLUDE ../ext/expert/sqlite3expert.h
|
||||
INCLUDE ../ext/expert/sqlite3expert.c
|
||||
|
||||
INCLUDE ../ext/intck/sqlite3intck.h
|
||||
INCLUDE ../ext/intck/sqlite3intck.c
|
||||
INCLUDE ../ext/misc/stmtrand.c
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
||||
#define SQLITE_SHELL_HAVE_RECOVER 1
|
||||
@@ -4253,6 +4253,7 @@ static int shell_exec(
|
||||
sqlite3_reset(pExplain);
|
||||
rc = sqlite3_stmt_explain(pExplain, 2);
|
||||
if( rc==SQLITE_OK ){
|
||||
bind_prepared_stmt(pArg, pExplain);
|
||||
while( sqlite3_step(pExplain)==SQLITE_ROW ){
|
||||
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
|
||||
int iEqpId = sqlite3_column_int(pExplain, 0);
|
||||
@@ -4270,6 +4271,7 @@ static int shell_exec(
|
||||
if( rc==SQLITE_OK ){
|
||||
pArg->cMode = MODE_Explain;
|
||||
assert( sqlite3_stmt_isexplain(pExplain)==1 );
|
||||
bind_prepared_stmt(pArg, pExplain);
|
||||
explain_data_prepare(pArg, pExplain);
|
||||
exec_prepared_stmt(pArg, pExplain);
|
||||
explain_data_delete(pArg);
|
||||
@@ -5364,6 +5366,7 @@ static void open_db(ShellState *p, int openFlags){
|
||||
#endif
|
||||
sqlite3_shathree_init(p->db, 0, 0);
|
||||
sqlite3_uint_init(p->db, 0, 0);
|
||||
sqlite3_stmtrand_init(p->db, 0, 0);
|
||||
sqlite3_decimal_init(p->db, 0, 0);
|
||||
sqlite3_base64_init(p->db, 0, 0);
|
||||
sqlite3_base85_init(p->db, 0, 0);
|
||||
@@ -5517,15 +5520,18 @@ static char **readline_completion(const char *zText, int iStart, int iEnd){
|
||||
|
||||
#elif HAVE_LINENOISE
|
||||
/*
|
||||
** Linenoise completion callback
|
||||
** Linenoise completion callback. Note that the 3rd argument is from
|
||||
** the "msteveb" version of linenoise, not the "antirez" version.
|
||||
*/
|
||||
static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
|
||||
static void linenoise_completion(const char *zLine, linenoiseCompletions *lc,
|
||||
void *pUserData){
|
||||
i64 nLine = strlen(zLine);
|
||||
i64 i, iStart;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char *zSql;
|
||||
char zBuf[1000];
|
||||
|
||||
UNUSED_PARAMETER(pUserData);
|
||||
if( nLine>(i64)sizeof(zBuf)-30 ) return;
|
||||
if( zLine[0]=='.' || zLine[0]=='#') return;
|
||||
for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
|
||||
@@ -7940,7 +7946,10 @@ static struct {
|
||||
int iCnt; /* Trigger the fault only if iCnt is already zero */
|
||||
int iInterval; /* Reset iCnt to this value after each fault */
|
||||
int eVerbose; /* When to print output */
|
||||
} faultsim_state = {-1, 0, 0, 0, 0};
|
||||
int nHit; /* Number of hits seen so far */
|
||||
int nRepeat; /* Turn off after this many hits. 0 for never */
|
||||
int nSkip; /* Skip this many before first fault */
|
||||
} faultsim_state = {-1, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
/*
|
||||
** This is the fault-sim callback
|
||||
@@ -7949,8 +7958,8 @@ static int faultsim_callback(int iArg){
|
||||
if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( faultsim_state.iCnt>0 ){
|
||||
faultsim_state.iCnt--;
|
||||
if( faultsim_state.iCnt ){
|
||||
if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--;
|
||||
if( faultsim_state.eVerbose>=2 ){
|
||||
oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
|
||||
}
|
||||
@@ -7960,6 +7969,10 @@ static int faultsim_callback(int iArg){
|
||||
oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
|
||||
}
|
||||
faultsim_state.iCnt = faultsim_state.iInterval;
|
||||
faultsim_state.nHit++;
|
||||
if( faultsim_state.nRepeat>0 && faultsim_state.nRepeat<=faultsim_state.nHit ){
|
||||
faultsim_state.iCnt = -1;
|
||||
}
|
||||
return faultsim_state.iErr;
|
||||
}
|
||||
|
||||
@@ -8944,6 +8957,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
eputf("%s: empty file\n", sCtx.zFile);
|
||||
import_cleanup(&sCtx);
|
||||
rc = 1;
|
||||
sqlite3_free(zCreate);
|
||||
goto meta_command_exit;
|
||||
}
|
||||
zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
|
||||
@@ -8970,7 +8984,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
nByte = strlen(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
zSql = 0;
|
||||
@@ -8989,16 +9002,21 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
if( nCol==0 ) return 0; /* no columns, no error */
|
||||
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
|
||||
|
||||
nByte = 64 /* space for "INSERT INTO", "VALUES(", ")\0" */
|
||||
+ (zSchema ? strlen(zSchema)*2 + 2: 0) /* Quoted schema name */
|
||||
+ strlen(zTable)*2 + 2 /* Quoted table name */
|
||||
+ nCol*2; /* Space for ",?" for each column */
|
||||
zSql = sqlite3_malloc64( nByte );
|
||||
if( zSql==0 ){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
if( zSchema ){
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
|
||||
sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
|
||||
zSchema, zTable);
|
||||
}else{
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
|
||||
sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
|
||||
}
|
||||
j = strlen30(zSql);
|
||||
for(i=1; i<nCol; i++){
|
||||
@@ -9007,6 +9025,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
zSql[j++] = ')';
|
||||
zSql[j] = 0;
|
||||
assert( j<nByte );
|
||||
if( eVerbose>=2 ){
|
||||
oputf("Insert using: %s\n", zSql);
|
||||
}
|
||||
@@ -10889,7 +10908,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
#ifdef YYCOVERAGE
|
||||
{"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
|
||||
#endif
|
||||
{"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
|
||||
{"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,1, "OFFSET " },
|
||||
{"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
|
||||
{"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
|
||||
{"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
|
||||
@@ -11121,17 +11140,23 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if( cli_strcmp(z,"off")==0 ){
|
||||
sqlite3_test_control(testctrl, 0);
|
||||
}else if( cli_strcmp(z,"on")==0 ){
|
||||
faultsim_state.iCnt = faultsim_state.iInterval;
|
||||
faultsim_state.iCnt = faultsim_state.nSkip;
|
||||
if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1;
|
||||
faultsim_state.nHit = 0;
|
||||
sqlite3_test_control(testctrl, faultsim_callback);
|
||||
}else if( cli_strcmp(z,"reset")==0 ){
|
||||
faultsim_state.iCnt = faultsim_state.iInterval;
|
||||
faultsim_state.iCnt = faultsim_state.nSkip;
|
||||
faultsim_state.nHit = 0;
|
||||
sqlite3_test_control(testctrl, faultsim_callback);
|
||||
}else if( cli_strcmp(z,"status")==0 ){
|
||||
oputf("faultsim.iId: %d\n", faultsim_state.iId);
|
||||
oputf("faultsim.iErr: %d\n", faultsim_state.iErr);
|
||||
oputf("faultsim.iCnt: %d\n", faultsim_state.iCnt);
|
||||
oputf("faultsim.nHit: %d\n", faultsim_state.nHit);
|
||||
oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
|
||||
oputf("faultsim.eVerbose: %d\n", faultsim_state.eVerbose);
|
||||
oputf("faultsim.nRepeat: %d\n", faultsim_state.nRepeat);
|
||||
oputf("faultsim.nSkip: %d\n", faultsim_state.nSkip);
|
||||
}else if( cli_strcmp(z,"-v")==0 ){
|
||||
if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
|
||||
}else if( cli_strcmp(z,"-q")==0 ){
|
||||
@@ -11142,6 +11167,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
faultsim_state.iErr = atoi(azArg[++kk]);
|
||||
}else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){
|
||||
faultsim_state.iInterval = atoi(azArg[++kk]);
|
||||
}else if( cli_strcmp(z,"-repeat")==0 && kk+1<nArg ){
|
||||
faultsim_state.nRepeat = atoi(azArg[++kk]);
|
||||
}else if( cli_strcmp(z,"-skip")==0 && kk+1<nArg ){
|
||||
faultsim_state.nSkip = atoi(azArg[++kk]);
|
||||
}else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
|
||||
bShowHelp = 1;
|
||||
}else{
|
||||
@@ -11165,6 +11194,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
" --errcode N When triggered, return N as error code\n"
|
||||
" --id ID Trigger only for the ID specified\n"
|
||||
" --interval N Trigger only after every N-th call\n"
|
||||
" --repeat N Turn off after N hits. 0 means never\n"
|
||||
" --skip N Skip the first N encounters\n"
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -12721,8 +12752,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
if( azCmd[i][0]=='.' ){
|
||||
rc = do_meta_command(azCmd[i], &data);
|
||||
if( rc ){
|
||||
free(azCmd);
|
||||
return rc==2 ? 0 : rc;
|
||||
if( rc==2 ) rc = 0;
|
||||
goto shell_main_exit;
|
||||
}
|
||||
}else{
|
||||
open_db(&data, 0);
|
||||
@@ -12735,8 +12766,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
eputf("Error: unable to process SQL: %s\n", azCmd[i]);
|
||||
}
|
||||
sqlite3_free(zErrMsg);
|
||||
free(azCmd);
|
||||
return rc!=0 ? rc : 1;
|
||||
if( rc==0 ) rc = 1;
|
||||
goto shell_main_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12774,7 +12805,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#if HAVE_READLINE || HAVE_EDITLINE
|
||||
rl_attempted_completion_function = readline_completion;
|
||||
#elif HAVE_LINENOISE
|
||||
linenoiseSetCompletionCallback(linenoise_completion);
|
||||
linenoiseSetCompletionCallback(linenoise_completion, NULL);
|
||||
#endif
|
||||
data.in = 0;
|
||||
rc = process_input(&data);
|
||||
@@ -12796,6 +12827,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
expertFinish(&data, 1, 0);
|
||||
}
|
||||
#endif
|
||||
shell_main_exit:
|
||||
free(azCmd);
|
||||
set_table_name(&data, 0);
|
||||
if( data.db ){
|
||||
@@ -12828,7 +12860,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
(unsigned int)(sqlite3_memory_used()-mem_main_enter));
|
||||
}
|
||||
#endif
|
||||
#endif /* !SQLITE_SHELL_FIDDLE */
|
||||
#else /* SQLITE_SHELL_FIDDLE... */
|
||||
shell_main_exit:
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+36
-17
@@ -3570,8 +3570,8 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
**
|
||||
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
|
||||
** <dd>The database connection comes up in "extended result code mode".
|
||||
** In other words, the database behaves has if
|
||||
** [sqlite3_extended_result_codes(db,1)] where called on the database
|
||||
** In other words, the database behaves as if
|
||||
** [sqlite3_extended_result_codes(db,1)] were called on the database
|
||||
** connection as soon as the connection is created. In addition to setting
|
||||
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
|
||||
** to return an extended result code.</dd>
|
||||
@@ -9942,24 +9942,45 @@ const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
** <li value="2"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
||||
** that the query planner does not need the rows returned in any particular
|
||||
** order, as long as rows with the same values in all "aOrderBy" columns
|
||||
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
||||
** combination of values in the columns identified by the "aOrderBy" field
|
||||
** needs to be returned.)^ ^It is always ok for two or more rows with the same
|
||||
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
||||
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
||||
** that have the same value for all columns identified by "aOrderBy".
|
||||
** ^However omitting the extra rows is optional.
|
||||
** order, as long as rows with the same values in all columns identified
|
||||
** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
|
||||
** contain the same values for all columns identified by "colUsed", all but
|
||||
** one such row may optionally be omitted from the result.)^
|
||||
** The virtual table is not required to omit rows that are duplicates
|
||||
** over the "colUsed" columns, but if the virtual table can do that without
|
||||
** too much extra effort, it could potentially help the query to run faster.
|
||||
** This mode is used for a DISTINCT query.
|
||||
** <li value="3"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
|
||||
** that the query planner needs only distinct rows but it does need the
|
||||
** rows to be sorted.)^ ^The virtual table implementation is free to omit
|
||||
** rows that are identical in all aOrderBy columns, if it wants to, but
|
||||
** it is not required to omit any rows. This mode is used for queries
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
|
||||
** virtual table must return rows in the order defined by "aOrderBy" as
|
||||
** if the sqlite3_vtab_distinct() interface had returned 0. However if
|
||||
** two or more rows in the result have the same values for all columns
|
||||
** identified by "colUsed", then all but one such row may optionally be
|
||||
** omitted.)^ Like when the return value is 2, the virtual table
|
||||
** is not required to omit rows that are duplicates over the "colUsed"
|
||||
** columns, but if the virtual table can do that without
|
||||
** too much extra effort, it could potentially help the query to run faster.
|
||||
** This mode is used for queries
|
||||
** that have both DISTINCT and ORDER BY clauses.
|
||||
** </ol>
|
||||
**
|
||||
** <p>The following table summarizes the conditions under which the
|
||||
** virtual table is allowed to set the "orderByConsumed" flag based on
|
||||
** the value returned by sqlite3_vtab_distinct(). This table is a
|
||||
** restatement of the previous four paragraphs:
|
||||
**
|
||||
** <table border=1 cellspacing=0 cellpadding=10 width="90%">
|
||||
** <tr>
|
||||
** <td valign="top">sqlite3_vtab_distinct() return value
|
||||
** <td valign="top">Rows are returned in aOrderBy order
|
||||
** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
|
||||
** <td valign="top">Duplicates over all colUsed columns may be omitted
|
||||
** <tr><td>0<td>yes<td>yes<td>no
|
||||
** <tr><td>1<td>no<td>yes<td>no
|
||||
** <tr><td>2<td>no<td>yes<td>yes
|
||||
** <tr><td>3<td>yes<td>yes<td>yes
|
||||
** </table>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
@@ -10811,8 +10832,6 @@ int sqlite3_deserialize(
|
||||
#if defined(__wasi__)
|
||||
# undef SQLITE_WASI
|
||||
# define SQLITE_WASI 1
|
||||
# undef SQLITE_OMIT_WAL
|
||||
# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
|
||||
# ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
# define SQLITE_OMIT_LOAD_EXTENSION
|
||||
# endif
|
||||
|
||||
+8
-4
@@ -3312,6 +3312,7 @@ struct SrcItem {
|
||||
unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
|
||||
unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
|
||||
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
|
||||
unsigned rowidUsed :1; /* The ROWID of this table is referenced */
|
||||
} fg;
|
||||
int iCursor; /* The VDBE cursor number used to access this table */
|
||||
union {
|
||||
@@ -3387,7 +3388,7 @@ struct SrcList {
|
||||
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
|
||||
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
|
||||
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
|
||||
/* 0x2000 not currently used */
|
||||
#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
|
||||
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
|
||||
/* 0x8000 not currently used */
|
||||
|
||||
@@ -3459,7 +3460,7 @@ struct NameContext {
|
||||
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
|
||||
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
|
||||
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
|
||||
#define NC_Complex 0x002000 /* True if a function or subquery seen */
|
||||
/* 0x002000 // available for reuse */
|
||||
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
|
||||
#define NC_HasWin 0x008000 /* One or more window functions seen */
|
||||
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
|
||||
@@ -4856,7 +4857,7 @@ void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
|
||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
|
||||
void sqlite3ExprDelete(sqlite3*, Expr*);
|
||||
void sqlite3ExprDeleteGeneric(sqlite3*,void*);
|
||||
void sqlite3ExprDeferredDelete(Parse*, Expr*);
|
||||
int sqlite3ExprDeferredDelete(Parse*, Expr*);
|
||||
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
|
||||
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
||||
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
||||
@@ -5024,6 +5025,7 @@ void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
||||
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
||||
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
||||
void sqlite3ExprToRegister(Expr *pExpr, int iReg);
|
||||
void sqlite3ExprCode(Parse*, Expr*, int);
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
|
||||
@@ -5086,7 +5088,7 @@ int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
int sqlite3ExprContainsSubquery(Expr*);
|
||||
#endif
|
||||
int sqlite3ExprIsInteger(const Expr*, int*);
|
||||
int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
int sqlite3IsRowid(const char*);
|
||||
@@ -5267,7 +5269,9 @@ void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
|
||||
void sqlite3Error(sqlite3*,int);
|
||||
void sqlite3ErrorClear(sqlite3*);
|
||||
void sqlite3SystemError(sqlite3*,int);
|
||||
#if !defined(SQLITE_OMIT_BLOB_LITERAL)
|
||||
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
||||
#endif
|
||||
u8 sqlite3HexToInt(int h);
|
||||
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
|
||||
|
||||
@@ -8174,6 +8174,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_stmtrand_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -8207,6 +8208,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
{ "remember", sqlite3_remember_init },
|
||||
{ "series", sqlite3_series_init },
|
||||
{ "spellfix", sqlite3_spellfix_init },
|
||||
{ "stmtrand", sqlite3_stmtrand_init },
|
||||
{ "totype", sqlite3_totype_init },
|
||||
{ "unionvtab", sqlite3_unionvtab_init },
|
||||
{ "wholenumber", sqlite3_wholenumber_init },
|
||||
|
||||
+22
-5
@@ -215,6 +215,9 @@ static int tclConnect(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp));
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("declare_vtab: %s", sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -302,11 +305,9 @@ static int tclFilter(
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xFilter", -1));
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(idxNum));
|
||||
if( idxStr ){
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(idxStr, -1));
|
||||
}else{
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("", -1));
|
||||
}
|
||||
Tcl_ListObjAppendElement(
|
||||
interp, pScript, Tcl_NewStringObj(idxStr ? idxStr : "", -1)
|
||||
);
|
||||
|
||||
pArg = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pArg);
|
||||
@@ -527,6 +528,7 @@ static int SQLITE_TCLAPI testBestIndexObj(
|
||||
"distinct", /* 3 */
|
||||
"in", /* 4 */
|
||||
"rhs_value", /* 5 */
|
||||
"collation", /* 6 */
|
||||
0
|
||||
};
|
||||
int ii;
|
||||
@@ -607,6 +609,17 @@ static int SQLITE_TCLAPI testBestIndexObj(
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zVal, -1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 6: assert( sqlite3_stricmp(azSub[ii], "collation")==0 ); {
|
||||
int iCons = 0;
|
||||
const char *zColl = "";
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &iCons) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zColl = sqlite3_vtab_collation(pIdxInfo, iCons);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zColl, -1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
@@ -697,6 +710,10 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
pIdxInfo->aConstraintUsage[iCons].omit = bOmit;
|
||||
}
|
||||
}
|
||||
}else
|
||||
if( sqlite3_stricmp("constraint", zCmd)==0 ){
|
||||
rc = SQLITE_CONSTRAINT;
|
||||
pTab->base.zErrMsg = sqlite3_mprintf("%s", Tcl_GetString(p));
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd);
|
||||
|
||||
+9
-4
@@ -194,8 +194,10 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
|
||||
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
|
||||
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
|
||||
if( pItem->pTab ){
|
||||
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
|
||||
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
|
||||
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
|
||||
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
|
||||
pItem->colUsed,
|
||||
pItem->fg.rowidUsed ? "+rowid" : "");
|
||||
}
|
||||
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
|
||||
sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
|
||||
@@ -235,12 +237,14 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
|
||||
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
|
||||
}
|
||||
if( pItem->pSelect ){
|
||||
sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
|
||||
if( pItem->pTab ){
|
||||
Table *pTab = pItem->pTab;
|
||||
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
|
||||
}
|
||||
assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
|
||||
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
|
||||
sqlite3TreeViewPop(&pView);
|
||||
}
|
||||
if( pItem->fg.isTabFunc ){
|
||||
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
|
||||
@@ -344,7 +348,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
|
||||
if( p->pLimit->pRight ){
|
||||
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
|
||||
sqlite3TreeViewItem(pView, "OFFSET", 0);
|
||||
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
|
||||
sqlite3TreeViewPop(&pView);
|
||||
}
|
||||
@@ -816,7 +820,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
case OE_Ignore: zType = "ignore"; break;
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView, "RAISE %s", zType);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -951,6 +951,72 @@ static ExprList *sqlite3ExpandReturning(
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/* If the Expr node is a subquery or an EXISTS operator or an IN operator that
|
||||
** uses a subquery, and if the subquery is SF_Correlated, then mark the
|
||||
** expression as EP_VarSelect.
|
||||
*/
|
||||
static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
if( ExprUseXSelect(pExpr)
|
||||
&& (pExpr->x.pSelect->selFlags & SF_Correlated)!=0
|
||||
){
|
||||
testcase( ExprHasProperty(pExpr, EP_VarSelect) );
|
||||
ExprSetProperty(pExpr, EP_VarSelect);
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If the SELECT references the table pWalker->u.pTab, then do two things:
|
||||
**
|
||||
** (1) Mark the SELECT as as SF_Correlated.
|
||||
** (2) Set pWalker->eCode to non-zero so that the caller will know
|
||||
** that (1) has happened.
|
||||
*/
|
||||
static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
|
||||
int i;
|
||||
SrcList *pSrc;
|
||||
assert( pSelect!=0 );
|
||||
pSrc = pSelect->pSrc;
|
||||
assert( pSrc!=0 );
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
if( pSrc->a[i].pTab==pWalker->u.pTab ){
|
||||
testcase( pSelect->selFlags & SF_Correlated );
|
||||
pSelect->selFlags |= SF_Correlated;
|
||||
pWalker->eCode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Scan the expression list that is the argument to RETURNING looking
|
||||
** for subqueries that depend on the table which is being modified in the
|
||||
** statement that is hosting the RETURNING clause (pTab). Mark all such
|
||||
** subqueries as SF_Correlated. If the subqueries are part of an
|
||||
** expression, mark the expression as EP_VarSelect.
|
||||
**
|
||||
** https://sqlite.org/forum/forumpost/2c83569ce8945d39
|
||||
*/
|
||||
static void sqlite3ProcessReturningSubqueries(
|
||||
ExprList *pEList,
|
||||
Table *pTab
|
||||
){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.xSelectCallback = sqlite3ReturningSubqueryCorrelated;
|
||||
w.u.pTab = pTab;
|
||||
sqlite3WalkExprList(&w, pEList);
|
||||
if( w.eCode ){
|
||||
w.xExprCallback = sqlite3ReturningSubqueryVarSelect;
|
||||
w.xSelectCallback = sqlite3SelectWalkNoop;
|
||||
sqlite3WalkExprList(&w, pEList);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the RETURNING trigger. Unlike other triggers
|
||||
** that invoke a subprogram in the bytecode, the code for RETURNING
|
||||
@@ -987,6 +1053,7 @@ static void codeReturningTrigger(
|
||||
sSelect.pSrc = &sFrom;
|
||||
sFrom.nSrc = 1;
|
||||
sFrom.a[0].pTab = pTab;
|
||||
sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
|
||||
sFrom.a[0].iCursor = -1;
|
||||
sqlite3SelectPrep(pParse, &sSelect, 0);
|
||||
if( pParse->nErr==0 ){
|
||||
@@ -1013,6 +1080,7 @@ static void codeReturningTrigger(
|
||||
int i;
|
||||
int nCol = pNew->nExpr;
|
||||
int reg = pParse->nMem+1;
|
||||
sqlite3ProcessReturningSubqueries(pNew, pTab);
|
||||
pParse->nMem += nCol+2;
|
||||
pReturning->iRetReg = reg;
|
||||
for(i=0; i<nCol; i++){
|
||||
|
||||
+9
-4
@@ -1015,10 +1015,13 @@ int sqlite3Atoi(const char *z){
|
||||
** Decode a floating-point value into an approximate decimal
|
||||
** representation.
|
||||
**
|
||||
** Round the decimal representation to n significant digits if
|
||||
** n is positive. Or round to -n signficant digits after the
|
||||
** decimal point if n is negative. No rounding is performed if
|
||||
** n is zero.
|
||||
** If iRound<=0 then round to -iRound significant digits to the
|
||||
** the left of the decimal point, or to a maximum of mxRound total
|
||||
** significant digits.
|
||||
**
|
||||
** If iRound>0 round to min(iRound,mxRound) significant digits total.
|
||||
**
|
||||
** mxRound must be positive.
|
||||
**
|
||||
** The significant digits of the decimal representation are
|
||||
** stored in p->z[] which is a often (but not always) a pointer
|
||||
@@ -1032,6 +1035,8 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
p->isSpecial = 0;
|
||||
p->z = p->zBuf;
|
||||
|
||||
assert( mxRound>0 );
|
||||
|
||||
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
|
||||
** NaN. */
|
||||
if( r<0.0 ){
|
||||
|
||||
+62
-32
@@ -1152,7 +1152,9 @@ jump_to_p2:
|
||||
**
|
||||
** The instruction at the address in register P1 is a Yield.
|
||||
** Jump to the P2 parameter of that Yield.
|
||||
** After the jump, register P1 becomes undefined.
|
||||
** After the jump, the value register P1 is left with a value
|
||||
** such that subsequent OP_Yields go back to the this same
|
||||
** OP_EndCoroutine instruction.
|
||||
**
|
||||
** See also: InitCoroutine
|
||||
*/
|
||||
@@ -1164,8 +1166,8 @@ case OP_EndCoroutine: { /* in1 */
|
||||
pCaller = &aOp[pIn1->u.i];
|
||||
assert( pCaller->opcode==OP_Yield );
|
||||
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
|
||||
pIn1->u.i = (int)(pOp - p->aOp) - 1;
|
||||
pOp = &aOp[pCaller->p2 - 1];
|
||||
pIn1->flags = MEM_Undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1212,7 +1214,7 @@ case OP_HaltIfNull: { /* in3 */
|
||||
/* no break */ deliberate_fall_through
|
||||
}
|
||||
|
||||
/* Opcode: Halt P1 P2 * P4 P5
|
||||
/* Opcode: Halt P1 P2 P3 P4 P5
|
||||
**
|
||||
** Exit immediately. All open cursors, etc are closed
|
||||
** automatically.
|
||||
@@ -1225,18 +1227,22 @@ case OP_HaltIfNull: { /* in3 */
|
||||
** then back out all changes that have occurred during this execution of the
|
||||
** VDBE, but do not rollback the transaction.
|
||||
**
|
||||
** If P4 is not null then it is an error message string.
|
||||
** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
|
||||
** text of an error message.
|
||||
**
|
||||
** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
|
||||
** If P3 is zero and P4 is not null then the error message string is held
|
||||
** in P4.
|
||||
**
|
||||
** P5 is a value between 1 and 4, inclusive, then the P4 error message
|
||||
** string is modified as follows:
|
||||
**
|
||||
** 0: (no change)
|
||||
** 1: NOT NULL constraint failed: P4
|
||||
** 2: UNIQUE constraint failed: P4
|
||||
** 3: CHECK constraint failed: P4
|
||||
** 4: FOREIGN KEY constraint failed: P4
|
||||
**
|
||||
** If P5 is not zero and P4 is NULL, then everything after the ":" is
|
||||
** omitted.
|
||||
** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
|
||||
** the ":" is omitted.
|
||||
**
|
||||
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
|
||||
** every program. So a jump past the last instruction of the program
|
||||
@@ -1249,6 +1255,9 @@ case OP_Halt: {
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
|
||||
#endif
|
||||
assert( pOp->p4type==P4_NOTUSED
|
||||
|| pOp->p4type==P4_STATIC
|
||||
|| pOp->p4type==P4_DYNAMIC );
|
||||
|
||||
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
|
||||
** something is wrong with the code generator. Raise an assertion in order
|
||||
@@ -1279,7 +1288,12 @@ case OP_Halt: {
|
||||
p->errorAction = (u8)pOp->p2;
|
||||
assert( pOp->p5<=4 );
|
||||
if( p->rc ){
|
||||
if( pOp->p5 ){
|
||||
if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
|
||||
const char *zErr;
|
||||
assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
|
||||
zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
|
||||
sqlite3VdbeError(p, "%s", zErr);
|
||||
}else if( pOp->p5 ){
|
||||
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
|
||||
"FOREIGN KEY" };
|
||||
testcase( pOp->p5==1 );
|
||||
@@ -4322,23 +4336,23 @@ case OP_OpenWrite:
|
||||
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
|
||||
p->minWriteFileFormat = pDb->pSchema->file_format;
|
||||
}
|
||||
if( pOp->p5 & OPFLAG_P2ISREG ){
|
||||
assert( p2>0 );
|
||||
assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
|
||||
pIn2 = &aMem[p2];
|
||||
assert( memIsValid(pIn2) );
|
||||
assert( (pIn2->flags & MEM_Int)!=0 );
|
||||
sqlite3VdbeMemIntegerify(pIn2);
|
||||
p2 = (int)pIn2->u.i;
|
||||
/* The p2 value always comes from a prior OP_CreateBtree opcode and
|
||||
** that opcode will always set the p2 value to 2 or more or else fail.
|
||||
** If there were a failure, the prepared statement would have halted
|
||||
** before reaching this instruction. */
|
||||
assert( p2>=2 );
|
||||
}
|
||||
}else{
|
||||
wrFlag = 0;
|
||||
}
|
||||
if( pOp->p5 & OPFLAG_P2ISREG ){
|
||||
assert( p2>0 );
|
||||
assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
|
||||
assert( pOp->opcode==OP_OpenWrite );
|
||||
pIn2 = &aMem[p2];
|
||||
assert( memIsValid(pIn2) );
|
||||
assert( (pIn2->flags & MEM_Int)!=0 );
|
||||
sqlite3VdbeMemIntegerify(pIn2);
|
||||
p2 = (int)pIn2->u.i;
|
||||
/* The p2 value always comes from a prior OP_CreateBtree opcode and
|
||||
** that opcode will always set the p2 value to 2 or more or else fail.
|
||||
** If there were a failure, the prepared statement would have halted
|
||||
** before reaching this instruction. */
|
||||
assert( p2>=2 );
|
||||
assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
|
||||
}
|
||||
if( pOp->p4type==P4_KEYINFO ){
|
||||
pKeyInfo = pOp->p4.pKeyInfo;
|
||||
@@ -4582,7 +4596,8 @@ case OP_SequenceTest: {
|
||||
** is the only cursor opcode that works with a pseudo-table.
|
||||
**
|
||||
** P3 is the number of fields in the records that will be stored by
|
||||
** the pseudo-table.
|
||||
** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
|
||||
** will return NULL for every column.
|
||||
*/
|
||||
case OP_OpenPseudo: {
|
||||
VdbeCursor *pCx;
|
||||
@@ -9000,14 +9015,29 @@ case OP_ReleaseReg: {
|
||||
|
||||
/* Opcode: Noop * * * * *
|
||||
**
|
||||
** Do nothing. This instruction is often useful as a jump
|
||||
** destination.
|
||||
** Do nothing. Continue downward to the next opcode.
|
||||
*/
|
||||
/*
|
||||
** The magic Explain opcode are only inserted when explain==2 (which
|
||||
** is to say when the EXPLAIN QUERY PLAN syntax is used.)
|
||||
** This opcode records information from the optimizer. It is the
|
||||
** the same as a no-op. This opcodesnever appears in a real VM program.
|
||||
/* Opcode: Explain P1 P2 P3 P4 *
|
||||
**
|
||||
** This is the same as OP_Noop during normal query execution. The
|
||||
** purpose of this opcode is to hold information about the query
|
||||
** plan for the purpose of EXPLAIN QUERY PLAN output.
|
||||
**
|
||||
** The P4 value is human-readable text that describes the query plan
|
||||
** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1".
|
||||
**
|
||||
** The P1 value is the ID of the current element and P2 is the parent
|
||||
** element for the case of nested query plan elements. If P2 is zero
|
||||
** then this element is a top-level element.
|
||||
**
|
||||
** For loop elements, P3 is the estimated code of each invocation of this
|
||||
** element.
|
||||
**
|
||||
** As with all opcodes, the meanings of the parameters for OP_Explain
|
||||
** are subject to change from one release to the next. Applications
|
||||
** should not attempt to interpret or use any of the information
|
||||
** contined in the OP_Explain opcode. The information provided by this
|
||||
** opcode is intended for testing and debugging use only.
|
||||
*/
|
||||
default: { /* This is really OP_Noop, OP_Explain */
|
||||
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
|
||||
|
||||
+6
-4
@@ -3355,9 +3355,9 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
|
||||
/* Check for immediate foreign key violations. */
|
||||
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
|
||||
sqlite3VdbeCheckFk(p, 0);
|
||||
(void)sqlite3VdbeCheckFk(p, 0);
|
||||
}
|
||||
|
||||
|
||||
/* If the auto-commit flag is set and this is the only active writer
|
||||
** VM, then we do either a commit or rollback of the current transaction.
|
||||
**
|
||||
@@ -5336,7 +5336,8 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
|
||||
assert( iVar>0 );
|
||||
if( v ){
|
||||
Mem *pMem = &v->aVar[iVar-1];
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0
|
||||
|| (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
|
||||
if( 0==(pMem->flags & MEM_Null) ){
|
||||
sqlite3_value *pRet = sqlite3ValueNew(v->db);
|
||||
if( pRet ){
|
||||
@@ -5356,7 +5357,8 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
|
||||
*/
|
||||
void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
|
||||
assert( iVar>0 );
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0
|
||||
|| (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
|
||||
if( iVar>=32 ){
|
||||
v->expmask |= 0x80000000;
|
||||
}else{
|
||||
|
||||
+5
-5
@@ -1949,17 +1949,17 @@ int sqlite3Stat4Column(
|
||||
sqlite3_value **ppVal /* OUT: Extracted value */
|
||||
){
|
||||
u32 t = 0; /* a column type code */
|
||||
int nHdr; /* Size of the header in the record */
|
||||
int iHdr; /* Next unread header byte */
|
||||
int iField; /* Next unread data byte */
|
||||
int szField = 0; /* Size of the current data field */
|
||||
u32 nHdr; /* Size of the header in the record */
|
||||
u32 iHdr; /* Next unread header byte */
|
||||
i64 iField; /* Next unread data byte */
|
||||
u32 szField = 0; /* Size of the current data field */
|
||||
int i; /* Column index */
|
||||
u8 *a = (u8*)pRec; /* Typecast byte array */
|
||||
Mem *pMem = *ppVal; /* Write result into this Mem object */
|
||||
|
||||
assert( iCol>0 );
|
||||
iHdr = getVarint32(a, nHdr);
|
||||
if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
|
||||
if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
|
||||
iField = nHdr;
|
||||
for(i=0; i<=iCol; i++){
|
||||
iHdr += getVarint32(&a[iHdr], t);
|
||||
|
||||
+2
-2
@@ -286,10 +286,10 @@ static int bytecodevtabColumn(
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
case 9: /* nexec */
|
||||
sqlite3_result_int(ctx, pOp->nExec);
|
||||
sqlite3_result_int64(ctx, pOp->nExec);
|
||||
break;
|
||||
case 10: /* ncycle */
|
||||
sqlite3_result_int(ctx, pOp->nCycle);
|
||||
sqlite3_result_int64(ctx, pOp->nCycle);
|
||||
break;
|
||||
#else
|
||||
case 9: /* nexec */
|
||||
|
||||
+4
-1
@@ -831,7 +831,10 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
for(i=0; aKeyword[i]; i++){
|
||||
int tokenType = 0;
|
||||
do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
|
||||
if( tokenType!=aKeyword[i] ) return SQLITE_MISUSE_BKPT;
|
||||
if( tokenType!=aKeyword[i] ){
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
+416
-122
@@ -302,6 +302,42 @@ static Expr *whereRightSubexprIsColumn(Expr *p){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
|
||||
** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
|
||||
** This function checks to see if the term is compatible with an index
|
||||
** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
|
||||
** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
|
||||
** or "NOCASE") used by the comparison in pTerm. If it is not compatible
|
||||
** with affinity idxaff, NULL is returned.
|
||||
*/
|
||||
static SQLITE_NOINLINE const char *indexInAffinityOk(
|
||||
Parse *pParse,
|
||||
WhereTerm *pTerm,
|
||||
u8 idxaff
|
||||
){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
Expr inexpr;
|
||||
|
||||
assert( pTerm->eOperator & WO_IN );
|
||||
|
||||
if( sqlite3ExprIsVector(pX->pLeft) ){
|
||||
int iField = pTerm->u.x.iField - 1;
|
||||
inexpr.flags = 0;
|
||||
inexpr.op = TK_EQ;
|
||||
inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
|
||||
assert( ExprUseXSelect(pX) );
|
||||
inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
|
||||
pX = &inexpr;
|
||||
}
|
||||
|
||||
if( sqlite3IndexAffinityOk(pX, idxaff) ){
|
||||
CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
|
||||
return pRet ? pRet->zName : sqlite3StrBINARY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance to the next WhereTerm that matches according to the criteria
|
||||
** established when the pScan object was initialized by whereScanInit().
|
||||
@@ -352,16 +388,24 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
if( (pTerm->eOperator & pScan->opMask)!=0 ){
|
||||
/* Verify the affinity and collating sequence match */
|
||||
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
|
||||
CollSeq *pColl;
|
||||
const char *zCollName;
|
||||
Parse *pParse = pWC->pWInfo->pParse;
|
||||
pX = pTerm->pExpr;
|
||||
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
|
||||
continue;
|
||||
|
||||
if( (pTerm->eOperator & WO_IN) ){
|
||||
zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
|
||||
if( !zCollName ) continue;
|
||||
}else{
|
||||
CollSeq *pColl;
|
||||
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
|
||||
continue;
|
||||
}
|
||||
assert(pX->pLeft);
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
||||
zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
|
||||
}
|
||||
assert(pX->pLeft);
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
||||
if( pColl==0 ) pColl = pParse->db->pDfltColl;
|
||||
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
|
||||
|
||||
if( sqlite3StrICmp(zCollName, pScan->zCollName) ){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -796,6 +840,40 @@ static int constraintCompatibleWithOuterJoin(
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
/*
|
||||
** Return true if column iCol of table pTab seem like it might be a
|
||||
** good column to use as part of a query-time index.
|
||||
**
|
||||
** Current algorithm (subject to improvement!):
|
||||
**
|
||||
** 1. If iCol is already the left-most column of some other index,
|
||||
** then return false.
|
||||
**
|
||||
** 2. If iCol is part of an existing index that has an aiRowLogEst of
|
||||
** more than 20, then return false.
|
||||
**
|
||||
** 3. If no disqualifying conditions above are found, return true.
|
||||
*/
|
||||
static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
|
||||
const Table *pTab,
|
||||
int iCol
|
||||
){
|
||||
const Index *pIdx;
|
||||
for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
|
||||
int j;
|
||||
for(j=0; j<pIdx->nKeyCol; j++){
|
||||
if( pIdx->aiColumn[j]==iCol ){
|
||||
if( j==0 ) return 0;
|
||||
if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
|
||||
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
@@ -810,6 +888,8 @@ static int termCanDriveIndex(
|
||||
const Bitmask notReady /* Tables in outer loops of the join */
|
||||
){
|
||||
char aff;
|
||||
int leftCol;
|
||||
|
||||
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
|
||||
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
|
||||
assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
|
||||
@@ -820,11 +900,12 @@ static int termCanDriveIndex(
|
||||
}
|
||||
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
|
||||
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
|
||||
if( pTerm->u.x.leftColumn<0 ) return 0;
|
||||
aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
|
||||
leftCol = pTerm->u.x.leftColumn;
|
||||
if( leftCol<0 ) return 0;
|
||||
aff = pSrc->pTab->aCol[leftCol].affinity;
|
||||
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
|
||||
testcase( pTerm->pExpr->op==TK_IS );
|
||||
return 1;
|
||||
return columnIsGoodIndexCandidate(pSrc->pTab, leftCol);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1265,6 +1346,20 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Return term iTerm of the WhereClause passed as the first argument. Terms
|
||||
** are numbered from 0 upwards, starting with the terms in pWC->a[], then
|
||||
** those in pWC->pOuter->a[] (if any), and so on.
|
||||
*/
|
||||
static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){
|
||||
WhereClause *p;
|
||||
for(p=pWC; p; p=p->pOuter){
|
||||
if( iTerm<p->nTerm ) return &p->a[iTerm];
|
||||
iTerm -= p->nTerm;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and populate an sqlite3_index_info structure. It is the
|
||||
** responsibility of the caller to eventually release the structure
|
||||
@@ -1291,6 +1386,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
const Table *pTab;
|
||||
int eDistinct = 0;
|
||||
ExprList *pOrderBy = pWInfo->pOrderBy;
|
||||
WhereClause *p;
|
||||
|
||||
assert( pSrc!=0 );
|
||||
pTab = pSrc->pTab;
|
||||
@@ -1301,28 +1397,30 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
** Mark each term with the TERM_OK flag. Set nTerm to the number of
|
||||
** terms found.
|
||||
*/
|
||||
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
pTerm->wtFlags &= ~TERM_OK;
|
||||
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
||||
if( pTerm->prereqRight & mUnusable ) continue;
|
||||
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
testcase( pTerm->eOperator & WO_IS );
|
||||
testcase( pTerm->eOperator & WO_ALL );
|
||||
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
|
||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||
for(p=pWC, nTerm=0; p; p=p->pOuter){
|
||||
for(i=0, pTerm=p->a; i<p->nTerm; i++, pTerm++){
|
||||
pTerm->wtFlags &= ~TERM_OK;
|
||||
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
||||
if( pTerm->prereqRight & mUnusable ) continue;
|
||||
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
testcase( pTerm->eOperator & WO_IS );
|
||||
testcase( pTerm->eOperator & WO_ALL );
|
||||
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
|
||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||
|
||||
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
|
||||
assert( pTerm->u.x.leftColumn>=XN_ROWID );
|
||||
assert( pTerm->u.x.leftColumn<pTab->nCol );
|
||||
if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
|
||||
&& !constraintCompatibleWithOuterJoin(pTerm,pSrc)
|
||||
){
|
||||
continue;
|
||||
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
|
||||
assert( pTerm->u.x.leftColumn>=XN_ROWID );
|
||||
assert( pTerm->u.x.leftColumn<pTab->nCol );
|
||||
if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
|
||||
&& !constraintCompatibleWithOuterJoin(pTerm,pSrc)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
nTerm++;
|
||||
pTerm->wtFlags |= TERM_OK;
|
||||
}
|
||||
nTerm++;
|
||||
pTerm->wtFlags |= TERM_OK;
|
||||
}
|
||||
|
||||
/* If the ORDER BY clause contains only columns in the current
|
||||
@@ -1372,7 +1470,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
}
|
||||
if( i==n ){
|
||||
nOrderBy = n;
|
||||
if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){
|
||||
if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
|
||||
eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
|
||||
}else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
|
||||
eDistinct = 1;
|
||||
@@ -1401,49 +1499,52 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
pHidden->pParse = pParse;
|
||||
pHidden->eDistinct = eDistinct;
|
||||
pHidden->mIn = 0;
|
||||
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
u16 op;
|
||||
if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
|
||||
pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
op = pTerm->eOperator & WO_ALL;
|
||||
if( op==WO_IN ){
|
||||
if( (pTerm->wtFlags & TERM_SLICE)==0 ){
|
||||
pHidden->mIn |= SMASKBIT32(j);
|
||||
for(p=pWC, i=j=0; p; p=p->pOuter){
|
||||
int nLast = i+p->nTerm;;
|
||||
for(pTerm=p->a; i<nLast; i++, pTerm++){
|
||||
u16 op;
|
||||
if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
|
||||
pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
op = pTerm->eOperator & WO_ALL;
|
||||
if( op==WO_IN ){
|
||||
if( (pTerm->wtFlags & TERM_SLICE)==0 ){
|
||||
pHidden->mIn |= SMASKBIT32(j);
|
||||
}
|
||||
op = WO_EQ;
|
||||
}
|
||||
op = WO_EQ;
|
||||
}
|
||||
if( op==WO_AUX ){
|
||||
pIdxCons[j].op = pTerm->eMatchOp;
|
||||
}else if( op & (WO_ISNULL|WO_IS) ){
|
||||
if( op==WO_ISNULL ){
|
||||
pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
|
||||
if( op==WO_AUX ){
|
||||
pIdxCons[j].op = pTerm->eMatchOp;
|
||||
}else if( op & (WO_ISNULL|WO_IS) ){
|
||||
if( op==WO_ISNULL ){
|
||||
pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
|
||||
}else{
|
||||
pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
|
||||
}
|
||||
}else{
|
||||
pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
|
||||
}
|
||||
}else{
|
||||
pIdxCons[j].op = (u8)op;
|
||||
/* The direct assignment in the previous line is possible only because
|
||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||
** following asserts verify this fact. */
|
||||
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
|
||||
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
|
||||
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
|
||||
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
|
||||
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
|
||||
assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
|
||||
pIdxCons[j].op = (u8)op;
|
||||
/* The direct assignment in the previous line is possible only because
|
||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||
** following asserts verify this fact. */
|
||||
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
|
||||
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
|
||||
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
|
||||
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
|
||||
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
|
||||
assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
|
||||
|
||||
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
|
||||
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
|
||||
){
|
||||
testcase( j!=i );
|
||||
if( j<16 ) mNoOmit |= (1 << j);
|
||||
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
|
||||
if( op==WO_GT ) pIdxCons[j].op = WO_GE;
|
||||
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
|
||||
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
|
||||
){
|
||||
testcase( j!=i );
|
||||
if( j<16 ) mNoOmit |= (1 << j);
|
||||
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
|
||||
if( op==WO_GT ) pIdxCons[j].op = WO_GE;
|
||||
}
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
assert( j==nTerm );
|
||||
pIdxInfo->nConstraint = j;
|
||||
@@ -1463,6 +1564,17 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
return pIdxInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free and zero the sqlite3_index_info.idxStr value if needed.
|
||||
*/
|
||||
static void freeIdxStr(sqlite3_index_info *pIdxInfo){
|
||||
if( pIdxInfo->needToFreeIdxStr ){
|
||||
sqlite3_free(pIdxInfo->idxStr);
|
||||
pIdxInfo->idxStr = 0;
|
||||
pIdxInfo->needToFreeIdxStr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
|
||||
** and possibly modified by xBestIndex methods.
|
||||
@@ -1478,6 +1590,7 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
|
||||
sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
|
||||
pHidden->aRhs[i] = 0;
|
||||
}
|
||||
freeIdxStr(pIdxInfo);
|
||||
sqlite3DbFree(db, pIdxInfo);
|
||||
}
|
||||
|
||||
@@ -2829,7 +2942,7 @@ static void whereLoopOutputAdjust(
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
int k = 0;
|
||||
testcase( pTerm->pExpr->op==TK_IS );
|
||||
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
|
||||
if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
|
||||
k = 10;
|
||||
}else{
|
||||
k = 20;
|
||||
@@ -3126,7 +3239,7 @@ static int whereLoopAddBtreeIndex(
|
||||
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
|
||||
){
|
||||
if( iCol==XN_ROWID || pProbe->uniqNotNull
|
||||
|| (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
|
||||
|| (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ))
|
||||
){
|
||||
pNew->wsFlags |= WHERE_ONEROW;
|
||||
}else{
|
||||
@@ -4013,6 +4126,21 @@ static int isLimitTerm(WhereTerm *pTerm){
|
||||
&& pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the first nCons constraints in the pUsage array are
|
||||
** marked as in-use (have argvIndex>0). False otherwise.
|
||||
*/
|
||||
static int allConstraintsUsed(
|
||||
struct sqlite3_index_constraint_usage *aUsage,
|
||||
int nCons
|
||||
){
|
||||
int ii;
|
||||
for(ii=0; ii<nCons; ii++){
|
||||
if( aUsage[ii].argvIndex<=0 ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument pIdxInfo is already populated with all constraints that may
|
||||
** be used by the virtual table identified by pBuilder->pNew->iTab. This
|
||||
@@ -4063,7 +4191,7 @@ static int whereLoopAddVirtualOne(
|
||||
** arguments mUsable and mExclude. */
|
||||
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
|
||||
for(i=0; i<nConstraint; i++, pIdxCons++){
|
||||
WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
|
||||
WhereTerm *pTerm = termFromWhereClause(pWC, pIdxCons->iTermOffset);
|
||||
pIdxCons->usable = 0;
|
||||
if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
|
||||
&& (pTerm->eOperator & mExclude)==0
|
||||
@@ -4094,6 +4222,7 @@ static int whereLoopAddVirtualOne(
|
||||
** Make no entries in the loop table.
|
||||
*/
|
||||
WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n"));
|
||||
freeIdxStr(pIdxInfo);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
@@ -4111,18 +4240,17 @@ static int whereLoopAddVirtualOne(
|
||||
int j = pIdxCons->iTermOffset;
|
||||
if( iTerm>=nConstraint
|
||||
|| j<0
|
||||
|| j>=pWC->nTerm
|
||||
|| (pTerm = termFromWhereClause(pWC, j))==0
|
||||
|| pNew->aLTerm[iTerm]!=0
|
||||
|| pIdxCons->usable==0
|
||||
){
|
||||
sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
|
||||
testcase( pIdxInfo->needToFreeIdxStr );
|
||||
freeIdxStr(pIdxInfo);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
testcase( iTerm==nConstraint-1 );
|
||||
testcase( j==0 );
|
||||
testcase( j==pWC->nTerm-1 );
|
||||
pTerm = &pWC->a[j];
|
||||
pNew->prereq |= pTerm->prereqRight;
|
||||
assert( iTerm<pNew->nLSlot );
|
||||
pNew->aLTerm[iTerm] = pTerm;
|
||||
@@ -4153,18 +4281,21 @@ static int whereLoopAddVirtualOne(
|
||||
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
|
||||
}
|
||||
|
||||
/* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET
|
||||
** terms. And if there are any, they should follow all other terms. */
|
||||
assert( pbRetryLimit || !isLimitTerm(pTerm) );
|
||||
if( isLimitTerm(pTerm) && *pbIn ){
|
||||
assert( !isLimitTerm(pTerm) || i>=nConstraint-2 );
|
||||
assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) );
|
||||
|
||||
if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){
|
||||
/* If there is an IN(...) term handled as an == (separate call to
|
||||
** xFilter for each value on the RHS of the IN) and a LIMIT or
|
||||
** OFFSET term handled as well, the plan is unusable. Set output
|
||||
** variable *pbRetryLimit to true to tell the caller to retry with
|
||||
** LIMIT and OFFSET disabled. */
|
||||
if( pIdxInfo->needToFreeIdxStr ){
|
||||
sqlite3_free(pIdxInfo->idxStr);
|
||||
pIdxInfo->idxStr = 0;
|
||||
pIdxInfo->needToFreeIdxStr = 0;
|
||||
}
|
||||
** OFFSET term handled as well, the plan is unusable. Similarly,
|
||||
** if there is a LIMIT/OFFSET and there are other unused terms,
|
||||
** the plan cannot be used. In these cases set variable *pbRetryLimit
|
||||
** to true to tell the caller to retry with LIMIT and OFFSET
|
||||
** disabled. */
|
||||
freeIdxStr(pIdxInfo);
|
||||
*pbRetryLimit = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -4177,7 +4308,7 @@ static int whereLoopAddVirtualOne(
|
||||
/* The non-zero argvIdx values must be contiguous. Raise an
|
||||
** error if they are not */
|
||||
sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
|
||||
testcase( pIdxInfo->needToFreeIdxStr );
|
||||
freeIdxStr(pIdxInfo);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -4232,7 +4363,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
|
||||
if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
|
||||
CollSeq *pC = 0;
|
||||
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
|
||||
Expr *pX = pHidden->pWC->a[iTerm].pExpr;
|
||||
Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr;
|
||||
if( pX->pLeft ){
|
||||
pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
|
||||
}
|
||||
@@ -4278,7 +4409,9 @@ int sqlite3_vtab_rhs_value(
|
||||
rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
|
||||
}else{
|
||||
if( pH->aRhs[iCons]==0 ){
|
||||
WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
|
||||
WhereTerm *pTerm = termFromWhereClause(
|
||||
pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset
|
||||
);
|
||||
rc = sqlite3ValueFromExpr(
|
||||
pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
|
||||
SQLITE_AFF_BLOB, &pH->aRhs[iCons]
|
||||
@@ -4434,9 +4567,8 @@ static int whereLoopAddVirtual(
|
||||
Bitmask mNext = ALLBITS;
|
||||
assert( mNext>0 );
|
||||
for(i=0; i<nConstraint; i++){
|
||||
Bitmask mThis = (
|
||||
pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
|
||||
);
|
||||
int iTerm = p->aConstraint[i].iTermOffset;
|
||||
Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq;
|
||||
if( mThis>mPrev && mThis<mNext ) mNext = mThis;
|
||||
}
|
||||
mPrev = mNext;
|
||||
@@ -4472,7 +4604,6 @@ static int whereLoopAddVirtual(
|
||||
}
|
||||
}
|
||||
|
||||
if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
|
||||
freeIndexInfo(pParse->db, p);
|
||||
WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
|
||||
return rc;
|
||||
@@ -5141,6 +5272,83 @@ static LogEst whereSortingCost(
|
||||
return rSortCost;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the maximum number of paths in the solver algorithm, for
|
||||
** queries that have three or more terms in the FROM clause. Queries with
|
||||
** two or fewer FROM clause terms are handled by the caller.
|
||||
**
|
||||
** Query planning is NP-hard. We must limit the number of paths at
|
||||
** each step of the solver search algorithm to avoid exponential behavior.
|
||||
**
|
||||
** The value returned is a tuning parameter. Currently the value is:
|
||||
**
|
||||
** 18 for star queries
|
||||
** 12 otherwise
|
||||
**
|
||||
** For the purposes of SQLite, a star-query is defined as a query
|
||||
** with a large central table that is joined against four or more
|
||||
** smaller tables. The central table is called the "fact" table.
|
||||
** The smaller tables that get joined are "dimension tables".
|
||||
**
|
||||
** SIDE EFFECT: (and really the whole point of this subroutine)
|
||||
**
|
||||
** If pWInfo describes a star-query, then the cost on WhereLoops for the
|
||||
** fact table is reduced. This heuristic helps keep fact tables in
|
||||
** outer loops. Without this heuristic, paths with fact tables in outer
|
||||
** loops tend to get pruned by the mxChoice limit on the number of paths,
|
||||
** resulting in poor query plans. The total amount of heuristic cost
|
||||
** adjustment is stored in pWInfo->nOutStarDelta and the cost adjustment
|
||||
** for each WhereLoop is stored in its rStarDelta field.
|
||||
*/
|
||||
static int computeMxChoice(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
int nLoop = pWInfo->nLevel; /* Number of terms in the join */
|
||||
if( nRowEst==0 && nLoop>=5 ){
|
||||
/* Check to see if we are dealing with a star schema and if so, reduce
|
||||
** the cost of fact tables relative to dimension tables, as a heuristic
|
||||
** to help keep the fact tables in outer loops.
|
||||
*/
|
||||
int iLoop; /* Counter over join terms */
|
||||
Bitmask m; /* Bitmask for current loop */
|
||||
assert( pWInfo->nOutStarDelta==0 );
|
||||
for(iLoop=0, m=1; iLoop<nLoop; iLoop++, m<<=1){
|
||||
WhereLoop *pWLoop; /* For looping over WhereLoops */
|
||||
int nDep = 0; /* Number of dimension tables */
|
||||
LogEst rDelta; /* Heuristic cost adjustment */
|
||||
Bitmask mSeen = 0; /* Mask of dimension tables */
|
||||
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
|
||||
if( (pWLoop->prereq & m)!=0 && (pWLoop->maskSelf & mSeen)==0 ){
|
||||
nDep++;
|
||||
mSeen |= pWLoop->maskSelf;
|
||||
}
|
||||
}
|
||||
if( nDep<=3 ) continue;
|
||||
rDelta = 15*(nDep-3);
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
SrcItem *pItem = pWInfo->pTabList->a + iLoop;
|
||||
sqlite3DebugPrintf("Fact-table %s: %d dimensions, cost reduced %d\n",
|
||||
pItem->zAlias ? pItem->zAlias : pItem->pTab->zName,
|
||||
nDep, rDelta);
|
||||
}
|
||||
#endif
|
||||
if( pWInfo->nOutStarDelta==0 ){
|
||||
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
|
||||
pWLoop->rStarDelta = 0;
|
||||
}
|
||||
}
|
||||
pWInfo->nOutStarDelta += rDelta;
|
||||
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
|
||||
if( pWLoop->maskSelf==m ){
|
||||
pWLoop->rRun -= rDelta;
|
||||
pWLoop->nOut -= rDelta;
|
||||
pWLoop->rStarDelta = rDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pWInfo->nOutStarDelta>0 ? 18 : 12;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
|
||||
** attempts to find the lowest cost path that visits each WhereLoop
|
||||
@@ -5176,13 +5384,25 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
|
||||
pParse = pWInfo->pParse;
|
||||
nLoop = pWInfo->nLevel;
|
||||
/* TUNING: For simple queries, only the best path is tracked.
|
||||
** For 2-way joins, the 5 best paths are followed.
|
||||
** For joins of 3 or more tables, track the 10 best paths */
|
||||
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
|
||||
assert( nLoop<=pWInfo->pTabList->nSrc );
|
||||
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n",
|
||||
nRowEst, pParse->nQueryLoop));
|
||||
/* TUNING: mxChoice is the maximum number of possible paths to preserve
|
||||
** at each step. Based on the number of loops in the FROM clause:
|
||||
**
|
||||
** nLoop mxChoice
|
||||
** ----- --------
|
||||
** 1 1 // the most common case
|
||||
** 2 5
|
||||
** 3+ 12 or 18 // see computeMxChoice()
|
||||
*/
|
||||
if( nLoop<=1 ){
|
||||
mxChoice = 1;
|
||||
}else if( nLoop==2 ){
|
||||
mxChoice = 5;
|
||||
}else{
|
||||
mxChoice = computeMxChoice(pWInfo, nRowEst);
|
||||
}
|
||||
assert( nLoop<=pWInfo->pTabList->nSrc );
|
||||
|
||||
/* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
|
||||
** case the purpose of this call is to estimate the number of rows returned
|
||||
@@ -5265,7 +5485,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rUnsorted = pWLoop->rRun + pFrom->nRow;
|
||||
if( pWLoop->rSetup ){
|
||||
rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup, rUnsorted);
|
||||
}
|
||||
rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
|
||||
nOut = pFrom->nRow + pWLoop->nOut;
|
||||
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
|
||||
@@ -5310,6 +5533,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
|
||||
** of legal values for isOrdered, -1..64.
|
||||
*/
|
||||
testcase( nTo==0 );
|
||||
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
|
||||
if( pTo->maskLoop==maskNew
|
||||
&& ((pTo->isOrdered^isOrdered)&0x80)==0
|
||||
@@ -5426,16 +5650,28 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
|
||||
#ifdef WHERETRACE_ENABLED /* >=2 */
|
||||
if( sqlite3WhereTrace & 0x02 ){
|
||||
LogEst rMin, rFloor = 0;
|
||||
int nDone = 0;
|
||||
sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
|
||||
for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
|
||||
sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
|
||||
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
|
||||
pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
|
||||
if( pTo->isOrdered>0 ){
|
||||
sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
|
||||
}else{
|
||||
sqlite3DebugPrintf("\n");
|
||||
while( nDone<nTo ){
|
||||
rMin = 0x7fff;
|
||||
for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
|
||||
if( pTo->rCost>rFloor && pTo->rCost<rMin ) rMin = pTo->rCost;
|
||||
}
|
||||
for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
|
||||
if( pTo->rCost==rMin ){
|
||||
sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
|
||||
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
|
||||
pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
|
||||
if( pTo->isOrdered>0 ){
|
||||
sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
|
||||
}else{
|
||||
sqlite3DebugPrintf("\n");
|
||||
}
|
||||
nDone++;
|
||||
}
|
||||
}
|
||||
rFloor = rMin;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -5530,7 +5766,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
}
|
||||
}
|
||||
|
||||
pWInfo->nRowOut = pFrom->nRow;
|
||||
pWInfo->nRowOut = pFrom->nRow + pWInfo->nOutStarDelta;
|
||||
|
||||
/* Free temporary memory and return success */
|
||||
sqlite3StackFreeNN(pParse->db, pSpace);
|
||||
@@ -5782,6 +6018,10 @@ static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){
|
||||
** the right-most table of a subquery that was flattened into the
|
||||
** main query and that subquery was the right-hand operand of an
|
||||
** inner join that held an ON or USING clause.
|
||||
** 6) The ORDER BY clause has 63 or fewer terms
|
||||
** 7) The omit-noop-join optimization is enabled.
|
||||
**
|
||||
** Items (1), (6), and (7) are checked by the caller.
|
||||
**
|
||||
** For example, given:
|
||||
**
|
||||
@@ -5920,9 +6160,62 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
|
||||
}
|
||||
}
|
||||
nSearch += pLoop->nOut;
|
||||
if( pWInfo->nOutStarDelta ) nSearch += pLoop->rStarDelta;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Expression Node callback for sqlite3ExprCanReturnSubtype().
|
||||
**
|
||||
** Only a function call is able to return a subtype. So if the node
|
||||
** is not a function call, return WRC_Prune immediately.
|
||||
**
|
||||
** A function call is able to return a subtype if it has the
|
||||
** SQLITE_RESULT_SUBTYPE property.
|
||||
**
|
||||
** Assume that every function is able to pass-through a subtype from
|
||||
** one of its argument (using sqlite3_result_value()). Most functions
|
||||
** are not this way, but we don't have a mechanism to distinguish those
|
||||
** that are from those that are not, so assume they all work this way.
|
||||
** That means that if one of its arguments is another function and that
|
||||
** other function is able to return a subtype, then this function is
|
||||
** able to return a subtype.
|
||||
*/
|
||||
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
||||
int n;
|
||||
FuncDef *pDef;
|
||||
sqlite3 *db;
|
||||
if( pExpr->op!=TK_FUNCTION ){
|
||||
return WRC_Prune;
|
||||
}
|
||||
assert( ExprUseXList(pExpr) );
|
||||
db = pWalker->pParse->db;
|
||||
n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||
if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
|
||||
pWalker->eCode = 1;
|
||||
return WRC_Prune;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if expression pExpr is able to return a subtype.
|
||||
**
|
||||
** A TRUE return does not guarantee that a subtype will be returned.
|
||||
** It only indicates that a subtype return is possible. False positives
|
||||
** are acceptable as they only disable an optimization. False negatives,
|
||||
** on the other hand, can lead to incorrect answers.
|
||||
*/
|
||||
static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.pParse = pParse;
|
||||
w.xExprCallback = exprNodeCanReturnSubtype;
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
return w.eCode;
|
||||
}
|
||||
|
||||
/*
|
||||
** The index pIdx is used by a query and contains one or more expressions.
|
||||
** In other words pIdx is an index on an expression. iIdxCur is the cursor
|
||||
@@ -5956,19 +6249,11 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
||||
continue;
|
||||
}
|
||||
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
|
||||
if( pExpr->op==TK_FUNCTION ){
|
||||
if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
|
||||
/* Functions that might set a subtype should not be replaced by the
|
||||
** value taken from an expression index since the index omits the
|
||||
** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
|
||||
int n;
|
||||
FuncDef *pDef;
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( ExprUseXList(pExpr) );
|
||||
n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||
if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
|
||||
if( p==0 ) break;
|
||||
@@ -6151,6 +6436,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( pOrderBy && pOrderBy->nExpr>=BMS ){
|
||||
pOrderBy = 0;
|
||||
wctrlFlags &= ~WHERE_WANT_DISTINCT;
|
||||
wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */
|
||||
}
|
||||
|
||||
/* The number of tables in the FROM clause is limited by the number of
|
||||
@@ -6391,7 +6677,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
if( pWInfo->pOrderBy ){
|
||||
whereInterstageHeuristic(pWInfo);
|
||||
wherePathSolver(pWInfo, pWInfo->nRowOut+1);
|
||||
wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}
|
||||
|
||||
@@ -6451,10 +6737,10 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0 /* these two combine to guarantee */
|
||||
&& 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
if( pWInfo->nLevel>=2 /* Must be a join, or this opt8n is pointless */
|
||||
&& pResultSet!=0 /* Condition (1) */
|
||||
&& 0==(wctrlFlags & (WHERE_AGG_DISTINCT|WHERE_KEEP_ALL_JOINS)) /* (1),(6) */
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin) /* (7) */
|
||||
){
|
||||
notReady = whereOmitNoopJoin(pWInfo, notReady);
|
||||
nTabList = pWInfo->nLevel;
|
||||
@@ -6940,7 +7226,15 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
|
||||
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
|
||||
if( (ws & WHERE_IDX_ONLY)==0 ){
|
||||
assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
|
||||
SrcItem *pSrc = &pTabList->a[pLevel->iFrom];
|
||||
assert( pLevel->iTabCur==pSrc->iCursor );
|
||||
if( pSrc->fg.viaCoroutine ){
|
||||
int m, n;
|
||||
n = pSrc->regResult;
|
||||
assert( pSrc->pTab!=0 );
|
||||
m = pSrc->pTab->nCol;
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
|
||||
}
|
||||
if( (ws & WHERE_INDEXED)
|
||||
|
||||
@@ -160,6 +160,8 @@ struct WhereLoop {
|
||||
/**** whereLoopXfer() copies fields above ***********************/
|
||||
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
|
||||
u16 nLSlot; /* Number of slots allocated for aLTerm[] */
|
||||
LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not
|
||||
** initialized unless pWInfo->nOutStarDelta>0 */
|
||||
WhereTerm **aLTerm; /* WhereTerms used */
|
||||
WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
|
||||
WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
|
||||
@@ -482,6 +484,7 @@ struct WhereInfo {
|
||||
unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
|
||||
unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
|
||||
unsigned sorted :1; /* True if really sorted (not just grouped) */
|
||||
LogEst nOutStarDelta; /* Artifical nOut reduction for star-query */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iEndWhere; /* End of the WHERE clause itself */
|
||||
|
||||
+224
-132
@@ -218,7 +218,8 @@ int sqlite3WhereExplainOneScan(
|
||||
zMsg = sqlite3StrAccumFinish(&str);
|
||||
sqlite3ExplainBreakpoint("",zMsg);
|
||||
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
|
||||
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
|
||||
pParse->addrExplain, pLoop->rRun,
|
||||
zMsg, P4_DYNAMIC);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -460,6 +461,39 @@ static void updateRangeAffinityStr(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because
|
||||
** columns might have been rearranged in the result set. This routine
|
||||
** fixes them up.
|
||||
**
|
||||
** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values
|
||||
** contain the *old* locations of each expression. This is a temporary
|
||||
** use of u.x.iOrderByCol, not its intended use. The caller must reset
|
||||
** u.x.iOrderByCol back to zero for all entries in pEList before the
|
||||
** caller returns.
|
||||
**
|
||||
** This routine changes pOrderBy->a[].u.x.iOrderByCol values from
|
||||
** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based
|
||||
** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero.
|
||||
*/
|
||||
static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){
|
||||
int i, j;
|
||||
if( pOrderBy==0 ) return;
|
||||
for(i=0; i<pOrderBy->nExpr; i++){
|
||||
int t = pOrderBy->a[i].u.x.iOrderByCol;
|
||||
if( t==0 ) continue;
|
||||
for(j=0; j<pEList->nExpr; j++){
|
||||
if( pEList->a[j].u.x.iOrderByCol==t ){
|
||||
pOrderBy->a[i].u.x.iOrderByCol = j+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( j>=pEList->nExpr ){
|
||||
pOrderBy->a[i].u.x.iOrderByCol = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** pX is an expression of the form: (vector) IN (SELECT ...)
|
||||
@@ -522,7 +556,8 @@ static Expr *removeUnindexableInClauseTerms(
|
||||
iField = pLoop->aLTerm[i]->u.x.iField - 1;
|
||||
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
|
||||
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
|
||||
pOrigRhs->a[iField].pExpr = 0;
|
||||
pOrigRhs->a[iField].pExpr = 0;
|
||||
if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
|
||||
if( pOrigLhs ){
|
||||
assert( pOrigLhs->a[iField].pExpr!=0 );
|
||||
pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
|
||||
@@ -545,18 +580,16 @@ static Expr *removeUnindexableInClauseTerms(
|
||||
sqlite3ExprDelete(db, pNew->pLeft);
|
||||
pNew->pLeft = p;
|
||||
}
|
||||
if( pSelect->pOrderBy ){
|
||||
/* If the SELECT statement has an ORDER BY clause, zero the
|
||||
** iOrderByCol variables. These are set to non-zero when an
|
||||
** ORDER BY term exactly matches one of the terms of the
|
||||
** result-set. Since the result-set of the SELECT statement may
|
||||
** have been modified or reordered, these variables are no longer
|
||||
** set correctly. Since setting them is just an optimization,
|
||||
** it's easiest just to zero them here. */
|
||||
ExprList *pOrderBy = pSelect->pOrderBy;
|
||||
for(i=0; i<pOrderBy->nExpr; i++){
|
||||
pOrderBy->a[i].u.x.iOrderByCol = 0;
|
||||
}
|
||||
|
||||
/* If either the ORDER BY clause or the GROUP BY clause contains
|
||||
** references to result-set columns, those references might now be
|
||||
** obsolete. So fix them up.
|
||||
*/
|
||||
assert( pRhs!=0 || db->mallocFailed );
|
||||
if( pRhs ){
|
||||
adjustOrderByCol(pSelect->pOrderBy, pRhs);
|
||||
adjustOrderByCol(pSelect->pGroupBy, pRhs);
|
||||
for(i=0; i<pRhs->nExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -571,6 +604,147 @@ static Expr *removeUnindexableInClauseTerms(
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
/*
|
||||
** Generate code for a single X IN (....) term of the WHERE clause.
|
||||
**
|
||||
** This is a special-case of codeEqualityTerm() that works for IN operators
|
||||
** only. It is broken out into a subroutine because this case is
|
||||
** uncommon and by splitting it off into a subroutine, the common case
|
||||
** runs faster.
|
||||
**
|
||||
** The current value for the constraint is left in register iTarget.
|
||||
** This routine sets up a loop that will iterate over all values of X.
|
||||
*/
|
||||
static SQLITE_NOINLINE void codeINTerm(
|
||||
Parse *pParse, /* The parsing context */
|
||||
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
|
||||
WhereLevel *pLevel, /* The level of the FROM clause we are working on */
|
||||
int iEq, /* Index of the equality term within this level */
|
||||
int bRev, /* True for reverse-order IN operations */
|
||||
int iTarget /* Attempt to leave results in this register */
|
||||
){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
int eType = IN_INDEX_NOOP;
|
||||
int iTab;
|
||||
struct InLoop *pIn;
|
||||
WhereLoop *pLoop = pLevel->pWLoop;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
int nEq = 0;
|
||||
int *aiMap = 0;
|
||||
|
||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
|
||||
&& pLoop->u.btree.pIndex!=0
|
||||
&& pLoop->u.btree.pIndex->aSortOrder[iEq]
|
||||
){
|
||||
testcase( iEq==0 );
|
||||
testcase( bRev );
|
||||
bRev = !bRev;
|
||||
}
|
||||
assert( pX->op==TK_IN );
|
||||
|
||||
for(i=0; i<iEq; i++){
|
||||
if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
|
||||
disableTerm(pLevel, pTerm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||
assert( pLoop->aLTerm[i]!=0 );
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
|
||||
}
|
||||
|
||||
iTab = 0;
|
||||
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
|
||||
}else{
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
|
||||
sqlite3 *db = pParse->db;
|
||||
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
|
||||
if( !db->mallocFailed ){
|
||||
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
|
||||
pExpr->iTable = iTab;
|
||||
}
|
||||
sqlite3ExprDelete(db, pX);
|
||||
}else{
|
||||
int n = sqlite3ExprVectorSize(pX->pLeft);
|
||||
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
|
||||
}
|
||||
pX = pExpr;
|
||||
}
|
||||
|
||||
if( eType==IN_INDEX_INDEX_DESC ){
|
||||
testcase( bRev );
|
||||
bRev = !bRev;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
||||
VdbeCoverageIf(v, bRev);
|
||||
VdbeCoverageIf(v, !bRev);
|
||||
|
||||
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
||||
pLoop->wsFlags |= WHERE_IN_ABLE;
|
||||
if( pLevel->u.in.nIn==0 ){
|
||||
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
|
||||
}
|
||||
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
|
||||
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
|
||||
}
|
||||
|
||||
i = pLevel->u.in.nIn;
|
||||
pLevel->u.in.nIn += nEq;
|
||||
pLevel->u.in.aInLoop =
|
||||
sqlite3WhereRealloc(pTerm->pWC->pWInfo,
|
||||
pLevel->u.in.aInLoop,
|
||||
sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
|
||||
pIn = pLevel->u.in.aInLoop;
|
||||
if( pIn ){
|
||||
int iMap = 0; /* Index in aiMap[] */
|
||||
pIn += i;
|
||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ){
|
||||
int iOut = iTarget + i - iEq;
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
|
||||
}else{
|
||||
int iCol = aiMap ? aiMap[iMap++] : 0;
|
||||
pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
|
||||
if( i==iEq ){
|
||||
pIn->iCur = iTab;
|
||||
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
|
||||
if( iEq>0 ){
|
||||
pIn->iBase = iTarget - i;
|
||||
pIn->nPrefix = i;
|
||||
}else{
|
||||
pIn->nPrefix = 0;
|
||||
}
|
||||
}else{
|
||||
pIn->eEndLoopOp = OP_Noop;
|
||||
}
|
||||
pIn++;
|
||||
}
|
||||
}
|
||||
testcase( iEq>0
|
||||
&& (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
|
||||
&& (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
|
||||
if( iEq>0
|
||||
&& (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
|
||||
){
|
||||
sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
|
||||
}
|
||||
}else{
|
||||
pLevel->u.in.nIn = 0;
|
||||
}
|
||||
sqlite3DbFree(pParse->db, aiMap);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Generate code for a single equality term of the WHERE clause. An equality
|
||||
** term can be either X=expr or X IN (...). pTerm is the term to be
|
||||
@@ -595,7 +769,6 @@ static int codeEqualityTerm(
|
||||
int iTarget /* Attempt to leave results in this register */
|
||||
){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int iReg; /* Register holding results */
|
||||
|
||||
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
|
||||
@@ -604,125 +777,12 @@ static int codeEqualityTerm(
|
||||
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
|
||||
}else if( pX->op==TK_ISNULL ){
|
||||
iReg = iTarget;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
|
||||
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
}else{
|
||||
int eType = IN_INDEX_NOOP;
|
||||
int iTab;
|
||||
struct InLoop *pIn;
|
||||
WhereLoop *pLoop = pLevel->pWLoop;
|
||||
int i;
|
||||
int nEq = 0;
|
||||
int *aiMap = 0;
|
||||
|
||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
|
||||
&& pLoop->u.btree.pIndex!=0
|
||||
&& pLoop->u.btree.pIndex->aSortOrder[iEq]
|
||||
){
|
||||
testcase( iEq==0 );
|
||||
testcase( bRev );
|
||||
bRev = !bRev;
|
||||
}
|
||||
assert( pX->op==TK_IN );
|
||||
iReg = iTarget;
|
||||
|
||||
for(i=0; i<iEq; i++){
|
||||
if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
|
||||
disableTerm(pLevel, pTerm);
|
||||
return iTarget;
|
||||
}
|
||||
}
|
||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||
assert( pLoop->aLTerm[i]!=0 );
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
|
||||
}
|
||||
|
||||
iTab = 0;
|
||||
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
|
||||
}else{
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
|
||||
sqlite3 *db = pParse->db;
|
||||
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
|
||||
if( !db->mallocFailed ){
|
||||
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
|
||||
pExpr->iTable = iTab;
|
||||
}
|
||||
sqlite3ExprDelete(db, pX);
|
||||
}else{
|
||||
int n = sqlite3ExprVectorSize(pX->pLeft);
|
||||
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
|
||||
}
|
||||
pX = pExpr;
|
||||
}
|
||||
|
||||
if( eType==IN_INDEX_INDEX_DESC ){
|
||||
testcase( bRev );
|
||||
bRev = !bRev;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
||||
VdbeCoverageIf(v, bRev);
|
||||
VdbeCoverageIf(v, !bRev);
|
||||
|
||||
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
||||
pLoop->wsFlags |= WHERE_IN_ABLE;
|
||||
if( pLevel->u.in.nIn==0 ){
|
||||
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
|
||||
}
|
||||
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
|
||||
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
|
||||
}
|
||||
|
||||
i = pLevel->u.in.nIn;
|
||||
pLevel->u.in.nIn += nEq;
|
||||
pLevel->u.in.aInLoop =
|
||||
sqlite3WhereRealloc(pTerm->pWC->pWInfo,
|
||||
pLevel->u.in.aInLoop,
|
||||
sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
|
||||
pIn = pLevel->u.in.aInLoop;
|
||||
if( pIn ){
|
||||
int iMap = 0; /* Index in aiMap[] */
|
||||
pIn += i;
|
||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ){
|
||||
int iOut = iReg + i - iEq;
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
|
||||
}else{
|
||||
int iCol = aiMap ? aiMap[iMap++] : 0;
|
||||
pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
|
||||
if( i==iEq ){
|
||||
pIn->iCur = iTab;
|
||||
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
|
||||
if( iEq>0 ){
|
||||
pIn->iBase = iReg - i;
|
||||
pIn->nPrefix = i;
|
||||
}else{
|
||||
pIn->nPrefix = 0;
|
||||
}
|
||||
}else{
|
||||
pIn->eEndLoopOp = OP_Noop;
|
||||
}
|
||||
pIn++;
|
||||
}
|
||||
}
|
||||
testcase( iEq>0
|
||||
&& (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
|
||||
&& (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
|
||||
if( iEq>0
|
||||
&& (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
|
||||
){
|
||||
sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
|
||||
}
|
||||
}else{
|
||||
pLevel->u.in.nIn = 0;
|
||||
}
|
||||
sqlite3DbFree(pParse->db, aiMap);
|
||||
codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1337,6 +1397,27 @@ static SQLITE_NOINLINE void filterPullDown(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
|
||||
** operator. Return true if level pLoop is guaranteed to visit only one
|
||||
** row for each key generated for the index.
|
||||
*/
|
||||
static int whereLoopIsOneRow(WhereLoop *pLoop){
|
||||
if( pLoop->u.btree.pIndex->onError
|
||||
&& pLoop->nSkip==0
|
||||
&& pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
|
||||
){
|
||||
int ii;
|
||||
for(ii=0; ii<pLoop->u.btree.nEq; ii++){
|
||||
if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||
** implementation described by pWInfo.
|
||||
@@ -1415,7 +1496,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
|
||||
pLevel->iLeftJoin = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
|
||||
VdbeComment((v, "init LEFT JOIN no-match flag"));
|
||||
VdbeComment((v, "init LEFT JOIN match flag"));
|
||||
}
|
||||
|
||||
/* Compute a safe address to jump to if we discover that the table for
|
||||
@@ -2084,7 +2165,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
|
||||
/* Record the instruction used to terminate the loop. */
|
||||
if( pLoop->wsFlags & WHERE_ONEROW ){
|
||||
if( (pLoop->wsFlags & WHERE_ONEROW)
|
||||
|| (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop))
|
||||
){
|
||||
pLevel->op = OP_Noop;
|
||||
}else if( bRev ){
|
||||
pLevel->op = OP_Prev;
|
||||
@@ -2730,7 +2813,16 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
|
||||
pRJ->regReturn);
|
||||
for(k=0; k<iLevel; k++){
|
||||
int iIdxCur;
|
||||
SrcItem *pRight;
|
||||
assert( pWInfo->a[k].pWLoop->iTab == pWInfo->a[k].iFrom );
|
||||
pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
|
||||
mAll |= pWInfo->a[k].pWLoop->maskSelf;
|
||||
if( pRight->fg.viaCoroutine ){
|
||||
sqlite3VdbeAddOp3(
|
||||
v, OP_Null, 0, pRight->regResult,
|
||||
pRight->regResult + pRight->pSelect->pEList->nExpr-1
|
||||
);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
|
||||
iIdxCur = pWInfo->a[k].iIdxCur;
|
||||
if( iIdxCur ){
|
||||
|
||||
+26
-10
@@ -101,7 +101,12 @@ static int allowedOp(int op){
|
||||
assert( TK_LT>TK_EQ && TK_LT<TK_GE );
|
||||
assert( TK_LE>TK_EQ && TK_LE<TK_GE );
|
||||
assert( TK_GE==TK_EQ+4 );
|
||||
return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
|
||||
assert( TK_IN<TK_EQ );
|
||||
assert( TK_IS<TK_EQ );
|
||||
assert( TK_ISNULL<TK_EQ );
|
||||
if( op>TK_GE ) return 0;
|
||||
if( op>=TK_EQ ) return 1;
|
||||
return op==TK_IN || op==TK_ISNULL || op==TK_IS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -134,15 +139,16 @@ static u16 exprCommute(Parse *pParse, Expr *pExpr){
|
||||
static u16 operatorMask(int op){
|
||||
u16 c;
|
||||
assert( allowedOp(op) );
|
||||
if( op==TK_IN ){
|
||||
if( op>=TK_EQ ){
|
||||
assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
|
||||
c = (u16)(WO_EQ<<(op-TK_EQ));
|
||||
}else if( op==TK_IN ){
|
||||
c = WO_IN;
|
||||
}else if( op==TK_ISNULL ){
|
||||
c = WO_ISNULL;
|
||||
}else if( op==TK_IS ){
|
||||
c = WO_IS;
|
||||
}else{
|
||||
assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
|
||||
c = (u16)(WO_EQ<<(op-TK_EQ));
|
||||
assert( op==TK_IS );
|
||||
c = WO_IS;
|
||||
}
|
||||
assert( op!=TK_ISNULL || c==WO_ISNULL );
|
||||
assert( op!=TK_IN || c==WO_IN );
|
||||
@@ -429,6 +435,13 @@ static int isAuxiliaryVtabOperator(
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if( pExpr->op>=TK_EQ ){
|
||||
/* Comparison operators are a common case. Save a few comparisons for
|
||||
** that common case by terminating early. */
|
||||
assert( TK_NE < TK_EQ );
|
||||
assert( TK_ISNOT < TK_EQ );
|
||||
assert( TK_NOTNULL < TK_EQ );
|
||||
return 0;
|
||||
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
|
||||
int res = 0;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
@@ -1570,7 +1583,7 @@ static void whereAddLimitExpr(
|
||||
Expr *pNew;
|
||||
int iVal = 0;
|
||||
|
||||
if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
|
||||
if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
|
||||
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
|
||||
if( pVal==0 ) return;
|
||||
ExprSetProperty(pVal, EP_IntValue);
|
||||
@@ -1638,6 +1651,7 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
|
||||
continue;
|
||||
}
|
||||
if( pWC->a[ii].leftCursor!=iCsr ) return;
|
||||
if( pWC->a[ii].prereqRight!=0 ) return;
|
||||
}
|
||||
|
||||
/* Check condition (5). Return early if it is not met. */
|
||||
@@ -1652,12 +1666,14 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
|
||||
|
||||
/* All conditions are met. Add the terms to the where-clause object. */
|
||||
assert( p->pLimit->op==TK_LIMIT );
|
||||
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
|
||||
if( p->iOffset>0 ){
|
||||
if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){
|
||||
whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
|
||||
}
|
||||
if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){
|
||||
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -909,7 +909,7 @@ static ExprList *exprListAppendList(
|
||||
int iDummy;
|
||||
Expr *pSub;
|
||||
pSub = sqlite3ExprSkipCollateAndLikely(pDup);
|
||||
if( sqlite3ExprIsInteger(pSub, &iDummy) ){
|
||||
if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
|
||||
pSub->op = TK_NULL;
|
||||
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
|
||||
pSub->u.zToken = 0;
|
||||
|
||||
@@ -360,4 +360,26 @@ do_catchsql_test 8.6 {
|
||||
SELECT sql FROM sqlite_master WHERE name='i0';
|
||||
} {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}}
|
||||
|
||||
|
||||
reset_db
|
||||
|
||||
do_execsql_test 9.0 {
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
CREATE TABLE t2(a,b,c,d,x);
|
||||
|
||||
CREATE TRIGGER AFTER INSERT ON t2 BEGIN
|
||||
|
||||
SELECT group_conct(
|
||||
123 ORDER BY (
|
||||
SELECT 1 FROM ( VALUES(a, 'b'), ('c') )
|
||||
))
|
||||
FROM t1;
|
||||
|
||||
END;
|
||||
}
|
||||
|
||||
do_catchsql_test 9.1 {
|
||||
ALTER TABLE t2 RENAME TO newname;
|
||||
} {1 {error in trigger AFTER: all VALUES must have the same number of terms}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -90,5 +90,40 @@ do_eqp_test 220 {
|
||||
`--SEARCH u USING AUTOMATIC COVERING INDEX (b=?)
|
||||
}
|
||||
|
||||
# 2024-05-27
|
||||
# ticket https://sqlite.org/src/tktview/8ff324e120
|
||||
# forum post https://sqlite.org/forum/forumpost/b21c2101a559be0a
|
||||
#
|
||||
# If an index with STAT1 data indicates that a column is not very
|
||||
# selective, then do not attempt to create an automatic index on
|
||||
# that column.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 300 {
|
||||
CREATE TABLE t1(id INTEGER PRIMARY KEY);
|
||||
CREATE TABLE t2(cid INT, pid INT, rx INT, PRIMARY KEY(cid, pid, rx));
|
||||
CREATE INDEX x1 ON t2(pid, rx);
|
||||
ANALYZE sqlite_schema;
|
||||
REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
|
||||
('t2', 'x1', '500000 250 250'),
|
||||
('t2','sqlite_autoindex_t2_1','500000 1 1 1');
|
||||
ANALYZE sqlite_schema;
|
||||
}
|
||||
do_eqp_test 310 {
|
||||
WITH RECURSIVE children(id) AS (
|
||||
SELECT cid FROM t2 WHERE pid = ?1 AND rx = ?2
|
||||
UNION
|
||||
SELECT cid FROM t2 JOIN children ON t2.pid = children.id AND rx = ?2
|
||||
) SELECT count(id) FROM children;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--CO-ROUTINE children
|
||||
| |--SETUP
|
||||
| | `--SEARCH t2 USING INDEX x1 (pid=? AND rx=?)
|
||||
| `--RECURSIVE STEP
|
||||
| |--SCAN children
|
||||
| `--SEARCH t2 USING INDEX x1 (pid=? AND rx=?)
|
||||
`--SCAN children
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -158,7 +158,7 @@ do_test 2.2 {
|
||||
set ::lFilterArgs [list]
|
||||
execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 }
|
||||
set ::lFilterArgs
|
||||
} {{5 50}}
|
||||
} {{50 5}}
|
||||
|
||||
do_test 2.3 {
|
||||
set ::lFilterArgs [list]
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
# 2024-04-26
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindexC
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {lVal method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t1(a)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
set idxstr [list]
|
||||
set res [list]
|
||||
|
||||
set idx 0
|
||||
foreach c $clist {
|
||||
array set a $c
|
||||
if {$a(usable)==0} continue
|
||||
if {$a(op)=="limit" && ![info exists ::do_not_use_limit]} {
|
||||
lappend idxstr limit
|
||||
lappend res omit $idx
|
||||
}
|
||||
if {$a(op)=="offset" && ![info exists ::do_not_use_offset]} {
|
||||
lappend idxstr offset
|
||||
lappend res omit $idx
|
||||
}
|
||||
incr idx
|
||||
}
|
||||
|
||||
return "cost 1000000 rows 1000000 idxnum 0 idxstr {$idxstr} $res"
|
||||
}
|
||||
|
||||
xFilter {
|
||||
set idxstr [lindex $args 1]
|
||||
set LIMIT ""
|
||||
foreach a $idxstr b [lindex $args 2] {
|
||||
set x($a) $b
|
||||
}
|
||||
|
||||
if {![info exists x(limit)]} { set x(limit) -1 }
|
||||
if {![info exists x(offset)]} { set x(offset) -1 }
|
||||
set LIMIT " LIMIT $x(limit) OFFSET $x(offset)"
|
||||
|
||||
set idx 1
|
||||
foreach v $lVal {
|
||||
lappend lRow "($idx, '$v')"
|
||||
incr idx
|
||||
}
|
||||
|
||||
return [list sql "
|
||||
SELECT * FROM ( VALUES [join $lRow ,]) $LIMIT
|
||||
"]
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f");
|
||||
CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "A B C D E F a b");
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TEMP TABLE t_unionall AS
|
||||
SELECT * FROM x1 UNION ALL SELECT * FROM x2;
|
||||
|
||||
CREATE TEMP TABLE t_intersect AS
|
||||
SELECT * FROM x1 INTERSECT SELECT * FROM x2;
|
||||
|
||||
CREATE TEMP TABLE t_union AS
|
||||
SELECT * FROM x1 UNION SELECT * FROM x2;
|
||||
|
||||
CREATE TEMP TABLE t_except AS
|
||||
SELECT * FROM x1 EXCEPT SELECT * FROM x2;
|
||||
}
|
||||
|
||||
foreach {tn limit} {
|
||||
1 "LIMIT 8"
|
||||
2 "LIMIT 4"
|
||||
3 "LIMIT 4 OFFSET 2"
|
||||
4 "LIMIT 8 OFFSET 4"
|
||||
} {
|
||||
|
||||
foreach {op tbl} {
|
||||
"UNION ALL" t_unionall
|
||||
"UNION" t_union
|
||||
"INTERSECT" t_intersect
|
||||
"EXCEPT" t_except
|
||||
} {
|
||||
|
||||
set expect [execsql "SELECT * FROM $tbl $limit"]
|
||||
do_execsql_test 1.2.$tbl.$tn "SELECT * FROM (
|
||||
SELECT * FROM x1 $op SELECT * FROM x2
|
||||
) $limit" $expect
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f");
|
||||
CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "a b e f");
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM x1
|
||||
EXCEPT
|
||||
SELECT * FROM x2
|
||||
LIMIT 3
|
||||
} {c d}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "1 2 3 4 5 6 7 8 9 10");
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM y1 WHERE a = COALESCE('8', a) LIMIT 3
|
||||
} {8}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM y1 WHERE a = '2' LIMIT 3
|
||||
} {2}
|
||||
|
||||
load_static_extension db series
|
||||
do_execsql_test 3.3 {
|
||||
SELECT * FROM generate_series(1, 5) WHERE value = (value & 14) LIMIT 3
|
||||
} {2 4}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
SELECT value FROM generate_series(1,10) WHERE value>2 LIMIT 4 OFFSET 1;
|
||||
} {4 5 6 7}
|
||||
|
||||
set ::do_not_use_limit 1
|
||||
do_execsql_test 3.5 {
|
||||
SELECT * FROM y1 LIMIT 5 OFFSET 3
|
||||
} {4 5 6 7 8}
|
||||
unset ::do_not_use_limit
|
||||
set ::do_not_use_offset 1
|
||||
do_execsql_test 3.6 {
|
||||
SELECT * FROM y1 LIMIT 5 OFFSET 3
|
||||
} {4 5 6 7 8}
|
||||
unset ::do_not_use_offset
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
proc vtab_command {lVal method args} {
|
||||
switch -- $method {
|
||||
xConnect { error "not happy!" }
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
do_catchsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command 1);
|
||||
} {1 {not happy!}}
|
||||
do_test 4.1 {
|
||||
sqlite3_errcode db
|
||||
} SQLITE_ERROR
|
||||
|
||||
proc vtab_command {lVal method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return $lVal
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "PRAGMA page_size=1024");
|
||||
} {1 {declare_vtab: syntax error}}
|
||||
do_catchsql_test 4.3 {
|
||||
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "CREATE TABLE x1(");
|
||||
} {1 {declare_vtab: incomplete input}}
|
||||
do_catchsql_test 4.4 {
|
||||
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "CREATE TABLE x1(insert)");
|
||||
} {1 {declare_vtab: near "insert": syntax error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
|
||||
proc quote {str} {
|
||||
return "'[string map {' ''} $str]'"
|
||||
}
|
||||
|
||||
proc vtab_command {lVal method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t1(a, b, c, d)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
|
||||
set res [list]
|
||||
set idx 0
|
||||
set idxnum 0
|
||||
|
||||
set cols(0) a
|
||||
set cols(1) b
|
||||
set cols(2) c
|
||||
|
||||
set lCons [list]
|
||||
|
||||
foreach c $clist {
|
||||
array set a $c
|
||||
if {$a(usable)==0} continue
|
||||
|
||||
if {($a(op)=="eq" || $a(op)=="is") && [info exists cols($a(column))]} {
|
||||
lappend res omit $idx
|
||||
set coll [$hdl collation $idx]
|
||||
lappend lCons "$cols($a(column)) = %[llength $lCons]% COLLATE $coll"
|
||||
|
||||
set idxnum [expr {$idx + (1 << $a(column))}]
|
||||
catch { unset cols($a(column)) }
|
||||
}
|
||||
|
||||
incr idx
|
||||
}
|
||||
|
||||
if {[llength [array names cols]]>0} {
|
||||
set missing [list]
|
||||
for {set i 0} {$i < 3} {incr i} {
|
||||
catch { lappend missing $cols($i) }
|
||||
}
|
||||
set msg "missing required constraints: [join $missing ,]"
|
||||
return [list constraint $msg]
|
||||
}
|
||||
|
||||
set idxstr [join $lCons " AND "]
|
||||
return "cost 1000 rows 1000 idxnum $idxnum $res idxstr {$idxstr}"
|
||||
}
|
||||
|
||||
xFilter {
|
||||
foreach {idxnum idxstr lArg} $args {}
|
||||
set i 0
|
||||
set where $idxstr
|
||||
foreach a $lArg {
|
||||
set where [string map [list %$i% [quote $a]] $where]
|
||||
incr i
|
||||
}
|
||||
# puts $where
|
||||
return [list sql "SELECT rowid, * FROM $lVal WHERE $where"]
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command t1);
|
||||
CREATE TABLE t1(a, b, c, d);
|
||||
}
|
||||
|
||||
foreach {tn where ok} {
|
||||
0 "WHERE a=? AND b=? AND c=? AND c=?" 1
|
||||
1 "WHERE a=? AND b=? AND c=?" 1
|
||||
2 "WHERE a=? AND b=? AND (c=? OR c=?)" 1
|
||||
3 "WHERE a=? AND b=? AND (c=? OR c=? OR c=?)" 1
|
||||
4 "WHERE a=? AND b=? AND (c IS ? OR c IS ?)" 1
|
||||
5 "WHERE a=? AND ((b=? AND c=?) OR (c=? AND b=?))" 1
|
||||
6 "WHERE a=? AND ((b=? AND c=?) OR (c=?))" 0
|
||||
} {
|
||||
do_test 5.2.$tn {
|
||||
catch { execsql "SELECT * FROM x1 $::where" } msg
|
||||
# if {$tn==0 || $tn==2 || $tn==3} { puts "MSG: $msg" }
|
||||
} [expr !$ok]
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
SELECT * FROM x1 WHERE (a, b, c) = (?, ?, ?);
|
||||
}
|
||||
|
||||
do_execsql_test 5.4 {
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(1, 'x', 'y', 'z', 'one');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(2, 'X', 'Y', 'Z', 'two');
|
||||
SELECT * FROM x1 WHERE (a, b, c) = ('X', 'Y', 'Z');
|
||||
} {X Y Z two}
|
||||
do_execsql_test 5.5 {
|
||||
SELECT * FROM x1 WHERE a='x' AND b='y' AND c='z';
|
||||
} {x y z one}
|
||||
do_execsql_test 5.6 {
|
||||
SELECT * FROM x1
|
||||
WHERE a='x' COLLATE nocase AND b='y' COLLATE nocase AND c='z'COLLATE nocase;
|
||||
} {x y z one X Y Z two}
|
||||
|
||||
do_execsql_test 5.7 {
|
||||
DELETE FROM t1;
|
||||
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(0, 'x', 'y', 'z', 'zero');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(1, 'x', 'y', 'Z', 'one');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(2, 'x', 'Y', 'z', 'two');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(3, 'x', 'Y', 'Z', 'three');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(4, 'X', 'y', 'z', 'four');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(5, 'X', 'y', 'Z', 'five');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(6, 'X', 'Y', 'z', 'six');
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(7, 'X', 'Y', 'z', 'seven');
|
||||
}
|
||||
|
||||
do_execsql_test 5.8 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {
|
||||
zero two three
|
||||
}
|
||||
|
||||
do_execsql_test 5.9 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' COLLATE nocase
|
||||
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {
|
||||
zero four two
|
||||
three six seven
|
||||
}
|
||||
|
||||
finish_test
|
||||
+1
-1
@@ -181,7 +181,7 @@ do_test capi3-3.4 {
|
||||
do_test capi3-3.5 {
|
||||
list [sqlite3_system_errno $db2] [sqlite3_close $db2]
|
||||
} [list $::capi3_errno SQLITE_OK]
|
||||
if {[clang_sanitize_address]==0} {
|
||||
if {[clang_sanitize_address]==0 && 0} {
|
||||
do_test capi3-3.6.1-misuse {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_MISUSE}
|
||||
|
||||
+1
-1
@@ -424,7 +424,7 @@ do_catchsql_test colname-9.400 {
|
||||
#
|
||||
do_catchsql_test colname-9.410 {
|
||||
CREATE TABLE t5 AS SELECT RAISE(abort,a);
|
||||
} {1 {RAISE() may only be used within a trigger-program}}
|
||||
} {1 {no such column: a}}
|
||||
|
||||
# Make sure the quotation marks get removed from the column names
|
||||
# when constructing a new table from an aggregate SELECT.
|
||||
|
||||
@@ -1505,4 +1505,89 @@ do_catchsql_test 19.4 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 18.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 20480 pagesize 4096 filename crash-a4150b729051e4.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 64: 00 00 00 00 00 00 00 00 00 00 ff f0 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 04 0e e5 00 0f c2 0f 75 ...............u
|
||||
| 112: 0f 19 0e e5 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 3808: 00 00 00 00 00 32 04 06 17 17 11 01 4b 69 6e 64 .....2......Kind
|
||||
| 3824: 65 78 74 31 61 62 63 74 31 05 43 52 45 41 54 45 ext1abct1.CREATE
|
||||
| 3840: 20 49 4e 44 45 58 20 74 31 61 62 63 20 4f 4e 20 INDEX t1abc ON
|
||||
| 3856: 74 31 28 61 2c 62 2c 63 29 5a 03 06 17 25 25 01 t1(a,b,c)Z...%%.
|
||||
| 3872: 79 74 61 62 6c 65 73 71 6c 69 74 65 5f 73 74 61 ytablesqlite_sta
|
||||
| 3888: 74 34 73 71 6c 69 74 65 5f 73 74 61 74 34 04 43 t4sqlite_stat4.C
|
||||
| 3904: 52 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c 69 REATE TABLE sqli
|
||||
| 3920: 74 65 5f 73 74 61 74 34 28 74 62 6c 2c 69 64 78 te_stat4(tbl,idx
|
||||
| 3936: 2c 6e 65 71 2c 6e 6c 74 2c 6e 64 6c 74 2c 73 61 ,neq,nlt,ndlt,sa
|
||||
| 3952: 6d 70 6c 65 29 4b 02 06 17 25 25 01 5b 74 61 62 mple)K...%%.[tab
|
||||
| 3968: 6c 65 73 71 6c 69 74 65 5f 73 74 61 74 31 73 71 lesqlite_stat1sq
|
||||
| 3984: 6c 69 74 65 5f 73 74 61 74 31 03 43 52 45 41 54 lite_stat1.CREAT
|
||||
| 4000: 45 20 54 41 42 4c 45 20 73 71 6c 69 74 65 5f 73 E TABLE sqlite_s
|
||||
| 4016: 74 61 74 31 28 74 62 6c 2c 69 64 78 2c 73 74 61 tat1(tbl,idx,sta
|
||||
| 4032: 74 29 3c 01 06 17 11 11 01 65 74 61 62 6c 65 74 t)<......etablet
|
||||
| 4048: 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 1t1.CREATE TABLE
|
||||
| 4064: 20 74 31 28 61 20 54 45 58 54 2c 20 62 20 49 4e t1(a TEXT, b IN
|
||||
| 4080: 54 2c 20 63 20 49 4e 54 2c 20 64 20 49 4e 54 29 T, c INT, d INT)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4000: 0b 07 05 13 01 01 01 62 63 64 64 06 0b 0c 06 05 .......bcdd.....
|
||||
| 4016: 13 02 01 01 64 65 66 01 59 09 0a 0c 05 05 13 03 ....def.Y.......
|
||||
| 4032: 01 01 64 65 66 02 6f 08 09 0c 04 05 13 02 01 01 ..def.o.........
|
||||
| 4048: 61 62 63 01 59 07 08 0c 03 05 13 02 01 01 87 62 abc.Y..........b
|
||||
| 4064: 63 00 ea 06 07 0c 02 05 13 02 01 01 61 62 63 00 c...........abc.
|
||||
| 4080: ea 06 06 0b 01 05 13 01 01 01 61 62 63 7b 04 04 ..........abc...
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 01 0f e0 00 0f e1 00 00 00 00 00 00 ................
|
||||
| 4064: 00 1d 01 04 11 17 31 74 31 74 31 61 62 63 31 30 ......1t1t1abc10
|
||||
| 4080: 30 30 30 20 35 30 30 30 20 32 30 30 30 20 31 30 000 5000 2000 10
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 07 0e ac 00 0f d1 0f a0 0f 6f 0f 3e .............o.>
|
||||
| 16: 0f 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3744: 00 00 00 00 00 00 00 00 00 00 00 00 2f 07 07 11 ............/...
|
||||
| 3760: 17 1b 1b 1b 24 74 31 74 31 61 62 63 32 20 31 20 ....$t1t1abc2 1
|
||||
| 3776: 31 20 31 35 20 36 20 36 20 36 32 20 35 20 36 20 1 15 6 6 62 5 6
|
||||
| 3792: 36 05 13 02 01 01 64 65 66 02 37 08 05 2f 06 07 6.....def.7../..
|
||||
| 3808: 11 17 1b 1b 1b 24 74 41 74 31 61 62 63 32 20 31 .....$tAt1abc2 1
|
||||
| 3824: 20 31 20 31 35 20 35 20 55 20 35 32 20 34 20 35 1 15 5 U 52 4 5
|
||||
| 3840: 20 35 05 13 02 01 01 64 65 66 01 59 09 06 2e 05 5.....def.Y....
|
||||
| 3856: 07 11 17 1b 1b 1b 22 74 31 74 31 61 62 63 31 20 .......t1t1abc1
|
||||
| 3872: 31 20 31 20 31 34 20 34 20 34 20 34 31 20 33 20 1 1 14 4 4 41 3
|
||||
| 3888: 34 20 34 08 b3 cd f0 f1 62 63 64 64 06 07 2f 05 4 4.....bcdd../.
|
||||
| 3904: 07 11 17 1b 1b 1b 24 74 37 74 31 61 62 63 34 20 ......$t7t1abc4
|
||||
| 3920: 31 20 31 20 31 30 20 33 20 33 20 33 30 20 32 20 1 1 10 3 3 30 2
|
||||
| 3936: 33 20 33 05 13 02 01 01 61 62 63 01 59 07 04 2f 3 3.....abc.Y../
|
||||
| 3952: 03 07 11 17 1b 1b 1b 24 74 31 74 31 61 62 63 34 .......$t1t1abc4
|
||||
| 3968: 20 32 20 31 20 31 30 20 31 20 32 20 32 30 20 31 2 1 10 1 2 20 1
|
||||
| 3984: 20 32 20 32 05 13 02 01 01 61 62 63 00 ea 06 03 2 2.....abc....
|
||||
| 4000: 2f 02 07 11 17 1b 1b 1b 24 74 31 74 31 61 62 63 /.......$t1t1abc
|
||||
| 4016: 34 20 32 20 31 20 31 30 20 31 20 31 20 31 30 20 4 2 1 10 1 1 10
|
||||
| 4032: 31 20 31 20 31 05 13 02 01 01 61 62 63 00 ea 05 1 1 1.....abc...
|
||||
| 4048: 02 2d 01 07 11 17 1b 1b 1b 20 74 31 74 31 61 62 .-....... t1t1ab
|
||||
| 4064: 63 34 20 31 20 31 20 31 30 20 30 20 30 1f 30 30 c4 1 1 10 0 0.00
|
||||
| 4080: 20 30 20 30 20 30 05 13 01 01 09 61 62 63 7b 04 0 0 0.....abc..
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 07 0f a8 00 0f f5 00 00 00 00 00 00 ................
|
||||
| 4000: 00 00 00 00 00 00 00 00 0c 05 13 02 01 01 64 65 ..............de
|
||||
| 4016: 66 02 37 08 05 0c 05 13 02 01 01 64 65 66 01 59 f.7........def.Y
|
||||
| 4032: 09 06 0b 05 12 01 01 01 62 63 64 64 06 07 0c 05 ........bcdd....
|
||||
| 4048: 13 02 01 01 61 62 63 01 59 07 01 2c 05 13 02 01 ....abc.Y..,....
|
||||
| 4064: 01 61 62 63 00 ea 06 03 0c 05 13 02 01 01 61 62 .abc..........ab
|
||||
| 4080: 63 00 ea 05 00 00 00 00 00 00 00 00 00 00 00 00 c...............
|
||||
| end crash-a4150b729051e4.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 18.1 {
|
||||
SELECT a FROM t1 WHERE b GLOB b AND b GLOB '0^x]␅6␚xz]';
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -313,4 +313,53 @@ do_execsql_test 4020 {
|
||||
SELECT b FROM t1 UNION SELECT 1;
|
||||
} {1 { }}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5010 {
|
||||
CREATE TABLE cnt(a);
|
||||
WITH RECURSIVE cnt2(x) AS (
|
||||
VALUES(1) UNION ALL SELECT x+1 FROM cnt2 WHERE x<50
|
||||
)
|
||||
INSERT INTO cnt SELECT x FROM cnt2;
|
||||
}
|
||||
|
||||
do_execsql_test 5020 {
|
||||
SELECT DISTINCT abs(random())%5 AS r FROM cnt ORDER BY r;
|
||||
} {0 1 2 3 4}
|
||||
|
||||
do_execsql_test 5030 {
|
||||
SELECT abs(random())%5 AS r FROM cnt GROUP BY 1 ORDER BY 1;
|
||||
} {0 1 2 3 4}
|
||||
|
||||
do_execsql_test 5040 {
|
||||
SELECT a FROM cnt WHERE a>45 GROUP BY 1;
|
||||
} {46 47 48 49 50}
|
||||
|
||||
|
||||
# 2024-06-03 dbsqlfuzz 8a44f675401a8b1f68a43bf813c4f4f72ad8f0ea
|
||||
# Use of uninitialized bytecode register due to the call-function-once
|
||||
# optimization at check-in 663f5dd32d9db832
|
||||
#
|
||||
db null NULL
|
||||
do_execsql_test 5050 {
|
||||
CREATE TABLE t0(a TEXT); INSERT INTO t0 VALUES('abcd');
|
||||
CREATE TABLE t1(b TEXT);
|
||||
CREATE TABLE t2(c TEXT);
|
||||
CREATE TABLE t3(d TEXT); INSERT INTO t3 VALUES('wxyz');
|
||||
CREATE VIEW v4(e) AS SELECT (SELECT t2.c FROM t0, t1 GROUP BY 1) FROM t2;
|
||||
SELECT v4.e FROM t3 LEFT JOIN v4 ON true GROUP BY 1;
|
||||
} NULL
|
||||
do_execsql_test 5060 {
|
||||
DROP VIEW v4;
|
||||
CREATE VIEW v4(e) AS SELECT (SELECT t2.c COLLATE nocase FROM t0, t1 GROUP BY 1) FROM t2;
|
||||
SELECT v4.e FROM t3 LEFT JOIN v4 ON true GROUP BY 1;
|
||||
} NULL
|
||||
|
||||
do_execsql_test 5070 {
|
||||
DROP VIEW v4;
|
||||
CREATE VIEW v4(e) AS SELECT (SELECT unlikely(t2.c COLLATE nocase) FROM t0, t1 GROUP BY 1) FROM t2;
|
||||
SELECT v4.e FROM t3 LEFT JOIN v4 ON true GROUP BY 1;
|
||||
} NULL
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# 2024-05-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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix exprfault2
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a,b,c,d,f,PRIMARY KEY(b,b));
|
||||
CREATE TABLE t2(x INT PRIMARY KEY, y, z);
|
||||
CREATE TABLE t3(a,b,c,d,e,PRIMARY KEY(a,b))WITHOUT ROWID;
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
|
||||
do_faultsim_test 1 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
UPDATE t3 SET (d,d,d,d, a )=(SELECT EXISTS(SELECT 1 NOT IN(SELECT EXISTS(SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t2 UNION SELECT (SELECT max( 1 IN(SELECT x NOT IN(SELECT 1 NOT IN(SELECT EXISTS(SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t2 UNION SELECT (SELECT max( (SELECT x NOT IN(SELECT 1 NOT IN(SELECT EXISTS(SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t2 UNION SELECT (SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT (SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) ORDERa)| (SELECT 1 x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) a)| (SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(ORDER BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT x ORDER BY 1) ORDER BY 1) z)|9 AS blob) IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))EXCEPT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) z) ORDER BY 1) IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT (SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) ORDERa)| (SELECT 1 x ORDER BY 1)))EXCEPT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) a)| (SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT x ORDER BY 1) ORDER BY 1) z)|9 AS blob) IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))EXCEPT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) z) ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) ORDERa)| (SELECT 1 x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 5 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) ORDERa)| (SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(ORDER BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT x ORDER BY 1) ORDER BY 1) z)| 1 AS blob) IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT DISTINCT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 UNION SELECT d ORDER BY 1) ORDER BY 1) z)| (SELECT 1 IN(SELECT max( 1 IN(SELECT c ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t2 UNION SELECT x ORDER BY 1)))INTERSECT SELECT (SELECT 1 FROM t2 UNION SELECT x ORDER BY 1) ORDER BY 1) e)|9 AS blob) FROM t2 WHERE a<x), e= BY 1) FROM t2 UNION SELECT 1 ORDER BY 1) ORDER BY 1)) a) FILTER (GROUP BY 1 HAVING b<= OVER(ORDER BY (SELECT max(x INPARTITION BY sum((SELECT y FROM t2 UNION SELECT x IN(SELECT 1 ORDER BY 1) ORDER 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t2 WHERE xBY 1) ORDER BY 1)) FROM77;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {1 {near ")": syntax error}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -55,5 +55,16 @@ do_execsql_test 2.2 {
|
||||
'(def AND (one NEAR abc)) OR one'
|
||||
} {<b>one</b>}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE f USING fts3(a,b);
|
||||
INSERT INTO f VALUES (101,x'056522650565056505650d051e056505650565286505650565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056f05650565056505650565056505650565050565056505640565056505650565056505651e05650565056505650565056505650505656565056505650565056505651e0565056505650565056505650565052265056505650569056505650565056505650565056505650565056505650500406505650565056505650565056505000101e5c501014b010101c501c5c501010101f5010201010101014101017373737373737373737373737373737373737373737373737373737330737373737373737373737373737365056505650d051e05650565056528056505650d05650505656505650565650565056505650565056505e505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565286505c705650565050565059494949494949494949494949494949494949494949494949494949494949494949494650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650505650565056505650565056505650565056500000000000000000000000000000000000000000000000000000000000000000565056505656505650565056505650d056500000000000000000000000000000000000000000000000000000000000000000100000000000000ed0000000000ffffffffffffffffffffff0007ffffff0001c5c50001c5c50001c5c50001c5c50001c5c50001c5c50001e5c50001c5c50001c5c50001c5c50001c5c50001c5c5000100000014720000000000000016dac5c50001c5c50001c5c50001c5c50001c5c50001c5c50d0505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800465056505650565056505651e650565056505650565056505650d05650505656505650565050565650584058005650565056505650565056505650565056522650565056505650d051e056505650561286505c70565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650565226505737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373733a73737373737373737373737373737373737373737373737373737373737373737373737373737373737c7373737365056505650d051e05650565056528650565056505650505650565056505650565056505650565056505e505650565056505656505650565056505650d05650505656505650565ef65056505');
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT length(snippet(f)) FROM f WHERE b MATCH x'0565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650565056505650565050565056505640565056505650565056505651e05650565056522650565056505650d051e056505650565286505650565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056f05650565056505650565056505650565050565056505640565056505650565056505651e05650565056505650565056505650505656565056505650565056505651e0565056505650565056505650565052265056505650569056505650565056505650565056505650565056505650500406505650565056505650565056505000101e5c501014b010101c501c5c501010101f50102010101010141010141010001017bf15905000000000017';
|
||||
} {192}
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
finish_test
|
||||
|
||||
@@ -508,4 +508,27 @@ do_test func2-3.9.2 {
|
||||
bin_to_hex [lindex $blob 0]
|
||||
} "12"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# At one point this was extremely slow to compile.
|
||||
#
|
||||
do_test func2-3.10 {
|
||||
set tm [time {
|
||||
execsql {
|
||||
SELECT '' IN (zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
|
||||
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(1)
|
||||
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
||||
}
|
||||
}]
|
||||
|
||||
set tm [lindex $tm 0]
|
||||
expr $tm<2000000
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -266,4 +266,26 @@ do_execsql_test 9.2 {
|
||||
SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500');
|
||||
} {1e500}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 10.0 {
|
||||
CREATE TABLE t1(a, b TEXT COLLATE NOCASE);
|
||||
INSERT INTO t1 VALUES('abc', 'def');
|
||||
INSERT INTO t1 VALUES('ghi', 'jkl');
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT rowid FROM t1 WHERE (a, b) IN ( VALUES('abc', 'def'), ('ghi', 'JKL') );
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
CREATE INDEX i1 ON t1(a, b COLLATE BINARY);
|
||||
}
|
||||
|
||||
do_execsql_test 10.3 {
|
||||
SELECT rowid FROM t1 WHERE (a, b) IN ( VALUES('abc', 'def'), ('ghi', 'JKL') );
|
||||
} {1 2}
|
||||
|
||||
finish_test
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
# 2024-05-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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix in7
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c PRIMARY KEY);
|
||||
CREATE TABLE t2(x, y, z);
|
||||
}
|
||||
|
||||
foreach {tn nNext idx sql} {
|
||||
1 1 {
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE (a, b) IN (SELECT x, y FROM t2)
|
||||
}
|
||||
|
||||
2 0 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE (a, b) IN (SELECT x, y FROM t2)
|
||||
}
|
||||
|
||||
3 0 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a = ? AND b = ?
|
||||
}
|
||||
|
||||
3 1 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a = ? AND b IS ?
|
||||
}
|
||||
|
||||
4 0 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a = ? AND b IN (?, ?, ?);
|
||||
}
|
||||
|
||||
5 1 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b, c);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a = ? AND b = ?
|
||||
}
|
||||
|
||||
6 0 {
|
||||
} {
|
||||
SELECT * FROM t1 WHERE c IN (SELECT z FROM t2)
|
||||
}
|
||||
|
||||
7 0 {
|
||||
} {
|
||||
SELECT * FROM t1 WHERE (a, c) IN (SELECT z, x FROM t2)
|
||||
}
|
||||
|
||||
8 1 {
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a IN (SELECT z FROM t2)
|
||||
}
|
||||
|
||||
9 1 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a IN (SELECT z FROM t2) AND b IS ?
|
||||
}
|
||||
10 0 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a IN (SELECT z FROM t2) AND b = ?
|
||||
}
|
||||
11 1 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a IS NULL AND b IN (SELECT z FROM t2)
|
||||
}
|
||||
12 0 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||
} {
|
||||
SELECT * FROM t1 WHERE a = ? AND b IN (SELECT z FROM t2)
|
||||
}
|
||||
} {
|
||||
do_test 1.1.$tn {
|
||||
execsql BEGIN
|
||||
execsql $idx
|
||||
|
||||
catch { array unset root_to_tbl }
|
||||
catch { array unset csr_to_root }
|
||||
|
||||
db eval {SELECT rootpage, tbl_name FROM sqlite_schema} {
|
||||
set root_to_tbl($rootpage) $tbl_name
|
||||
}
|
||||
|
||||
set nSeen 0
|
||||
db eval "explain $sql" {
|
||||
if {$opcode=="OpenRead"} {
|
||||
set csr_to_root($p1) $p2
|
||||
}
|
||||
if {$opcode=="Next"} {
|
||||
catch {
|
||||
set root $csr_to_root($p1)
|
||||
set tbl $root_to_tbl($root)
|
||||
if {$tbl=="t1"} {incr nSeen}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
execsql ROLLBACK
|
||||
|
||||
set nSeen
|
||||
} $nNext
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a TEXT PRIMARY KEY, b TEXT) WITHOUT ROWID;
|
||||
INSERT INTO t1 VALUES('1', 'one');
|
||||
INSERT INTO t1 VALUES('2', NULL);
|
||||
INSERT INTO t1 VALUES('3', 'three');
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT b FROM t1 WHERE a IN (1,2,3) ORDER BY b ASC NULLS LAST;
|
||||
} {one three {}}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -615,6 +615,58 @@ do_execsql_test indexexpr1-2200 {
|
||||
GROUP BY t2.type, t1.tag
|
||||
) v ON v.type = 0 AND v.tag = u.tag;
|
||||
} {7 100 8 101}
|
||||
do_execsql_test indexexpr1-2210 {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(x INT, y TEXT);
|
||||
INSERT INTO t1(x,y) VALUES(1,'{b:5}');
|
||||
SELECT json_insert('{}', '$.a', coalesce(null,json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
db null NULL
|
||||
do_execsql_test indexexpr1-2211 {
|
||||
CREATE INDEX t1j ON t1(coalesce(null,json(y)));
|
||||
SELECT json_insert('{}', '$.a', coalesce(null,json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2220 {
|
||||
DROP INDEX t1j;
|
||||
SELECT json_insert('{}', '$.a', iif(1,json(y),123))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2221 {
|
||||
CREATE INDEX t1j ON t1(iif(1,json(y),123));
|
||||
SELECT json_insert('{}', '$.a', iif(1,json(y),123))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2230 {
|
||||
DROP INDEX t1j;
|
||||
SELECT json_insert('{}', '$.a', ifnull(NULL,json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2231 {
|
||||
CREATE INDEX t1j ON t1(ifnull(NULL,json(y)));
|
||||
SELECT json_insert('{}', '$.a', ifnull(NULL,json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2240 {
|
||||
DROP INDEX t1j;
|
||||
SELECT json_insert('{}', '$.a', nullif(json(y),8))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2241 {
|
||||
CREATE INDEX t1j ON t1(nullif(json(y),8));
|
||||
SELECT json_insert('{}', '$.a', nullif(json(y),8))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2250 {
|
||||
DROP INDEX t1j;
|
||||
SELECT json_insert('{}', '$.a', min('~',json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2251 {
|
||||
CREATE INDEX t1j ON t1(min('~',json(y)));
|
||||
SELECT json_insert('{}', '$.a', min('~',json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2260 {
|
||||
DROP INDEX t1j;
|
||||
SELECT json_insert('{}', '$.a', max('...',json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
do_execsql_test indexexpr1-2261 {
|
||||
CREATE INDEX t1j ON t1(max('...',json(y)));
|
||||
SELECT json_insert('{}', '$.a', max('...',json(y)))->>'$.a.b' FROM t1;
|
||||
} {5}
|
||||
|
||||
|
||||
# 2023-11-08 Forum post https://sqlite.org/forum/forumpost/68d284c86b082c3e
|
||||
#
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user