Compare commits
182 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3d536d378 | |||
| a751fddd01 | |||
| 8cec7ac644 | |||
| 016214ddf7 | |||
| 3b171836ec | |||
| 21219fe313 | |||
| 4c6a1298f8 | |||
| b11e7e6aa7 | |||
| 3c44d50e47 | |||
| 9dc32eaa33 | |||
| 3903ad4497 | |||
| 655219897a | |||
| a4ccda2979 | |||
| 17b83d28b8 | |||
| 94dbae0c8d | |||
| 2fdb32316d | |||
| ec79dfaf7e | |||
| 2eec675e6e | |||
| ee8e00f53f | |||
| 0ed22ad847 | |||
| 936c8e42e1 | |||
| bebe2d8be8 | |||
| 3731703dbb | |||
| 2526668556 | |||
| 33087dbf30 | |||
| b8337932b3 | |||
| 00208479fd | |||
| f765aec406 | |||
| e212493358 | |||
| df903fe056 | |||
| 0462499051 | |||
| 79dac84b31 | |||
| b834f629cc | |||
| fa0763eb34 | |||
| c72953a4bc | |||
| c4439fb134 | |||
| 61f2ee6ab8 | |||
| 1550771a6a | |||
| 9a1a4822e8 | |||
| f722d91fa8 | |||
| 5d783d5c84 | |||
| e09e451a48 | |||
| 325420616f | |||
| 0e4afddadf | |||
| 7e60106d15 | |||
| 8292aa7a18 | |||
| a8c43830f2 | |||
| 0e93237b17 | |||
| f0c9bc596e | |||
| 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 | |||
| ac94cf3ece | |||
| 5b613ed41b | |||
| fa4c4247a5 | |||
| 1152def76e | |||
| 660322f96f | |||
| 05c6d13027 | |||
| 6951c49779 | |||
| ed27183d83 | |||
| 8181cc6c10 | |||
| de6a4be9b5 | |||
| 743ae4c68b | |||
| b411c4d69e | |||
| 65a1d7a284 | |||
| 7fd9b53308 | |||
| f895173c5f | |||
| 634f434686 | |||
| efe9500af7 | |||
| 13f5910889 | |||
| 307f290b32 | |||
| 8ce73ce15b | |||
| 7f7d0b19f8 | |||
| 9352cfa30b | |||
| 69dbd7a4e7 | |||
| cfd4507c83 | |||
| 6921a2d205 | |||
| ed517a7082 | |||
| dcc121999c | |||
| a509a90958 | |||
| ca3b9096c4 | |||
| 1872f8d844 | |||
| eb5bd4db91 | |||
| 791b6f36cc | |||
| f7aab656ff | |||
| ed6c9aa6ab | |||
| bcf97e70f5 | |||
| 99b4e6e254 | |||
| 41c9945c74 | |||
| 4397d28378 | |||
| 55051d661c | |||
| d2b3b72a2b | |||
| cf84ae0189 | |||
| 4a402b80c5 | |||
| a631eb378d | |||
| d9eee787bd | |||
| 378bf82e2b | |||
| 2faaf3830e | |||
| 006a9b51aa | |||
| 529ed1a3a3 | |||
| af64a22762 | |||
| 296ae1e467 | |||
| 219b4f2061 |
@@ -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.46.1])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 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.46.1.
|
||||
#
|
||||
#
|
||||
# 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.46.1'
|
||||
PACKAGE_STRING='sqlite 3.46.1'
|
||||
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.46.1 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.46.1:";;
|
||||
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.46.1
|
||||
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.46.1, 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.46.1, 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.46.1
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -53,11 +53,6 @@
|
||||
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
/* Character used to represent a known-incomplete UTF-8 char group (�) */
|
||||
static WCHAR cBadGroup = 0xfffd;
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
static HANDLE handleOfFile(FILE *pf){
|
||||
int fileDesc = _fileno(pf);
|
||||
|
||||
@@ -465,6 +465,13 @@ do_execsql_test 5.3 {
|
||||
t2 t2_idx_0001295b {100 20 5}
|
||||
}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
SELECT sqlite_expert_rem(123, 123);
|
||||
} {1 {no such function: sqlite_expert_rem}}
|
||||
do_catchsql_test 5.5 {
|
||||
SELECT sqlite_expert_sample();
|
||||
} {1 {no such function: sqlite_expert_sample}}
|
||||
|
||||
if 0 {
|
||||
do_test expert1-6.0 {
|
||||
catchcmd :memory: {
|
||||
|
||||
@@ -626,7 +626,7 @@ static int expertFilter(
|
||||
pCsr->pData = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
|
||||
"SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
|
||||
"SELECT * FROM main.%Q WHERE sqlite_expert_sample()", pVtab->pTab->zName
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1500,7 +1500,7 @@ struct IdxRemCtx {
|
||||
};
|
||||
|
||||
/*
|
||||
** Implementation of scalar function rem().
|
||||
** Implementation of scalar function sqlite_expert_rem().
|
||||
*/
|
||||
static void idxRemFunc(
|
||||
sqlite3_context *pCtx,
|
||||
@@ -1513,7 +1513,7 @@ static void idxRemFunc(
|
||||
assert( argc==2 );
|
||||
|
||||
iSlot = sqlite3_value_int(argv[0]);
|
||||
assert( iSlot<=p->nSlot );
|
||||
assert( iSlot<p->nSlot );
|
||||
pSlot = &p->aSlot[iSlot];
|
||||
|
||||
switch( pSlot->eType ){
|
||||
@@ -1624,7 +1624,8 @@ static int idxPopulateOneStat1(
|
||||
const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
|
||||
const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
|
||||
zCols = idxAppendText(&rc, zCols,
|
||||
"%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
|
||||
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
|
||||
zComma, zName, nCol, zName, zColl
|
||||
);
|
||||
zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
|
||||
}
|
||||
@@ -1757,13 +1758,13 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
|
||||
rc = sqlite3_create_function(
|
||||
dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
|
||||
rc = sqlite3_create_function(dbrem, "sqlite_expert_rem",
|
||||
2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
|
||||
rc = sqlite3_create_function(p->db, "sqlite_expert_sample",
|
||||
0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1815,6 +1816,9 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
|
||||
}
|
||||
|
||||
sqlite3_create_function(p->db, "sqlite_expert_rem", 2, SQLITE_UTF8, 0,0,0,0);
|
||||
sqlite3_create_function(p->db, "sqlite_expert_sample", 0,SQLITE_UTF8,0,0,0,0);
|
||||
|
||||
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -55,8 +55,8 @@ struct Fts5PhraseIter {
|
||||
** EXTENSION API FUNCTIONS
|
||||
**
|
||||
** xUserData(pFts):
|
||||
** Return a copy of the context pointer the extension function was
|
||||
** registered with.
|
||||
** Return a copy of the pUserData pointer passed to the xCreateFunction()
|
||||
** API when the extension function was registered.
|
||||
**
|
||||
** xColumnTotalSize(pFts, iCol, pnToken):
|
||||
** If parameter iCol is less than zero, set output variable *pnToken
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -2452,6 +2456,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
assert( pRight->eType==FTS5_STRING
|
||||
|| pRight->eType==FTS5_TERM
|
||||
|| pRight->eType==FTS5_EOF
|
||||
|| (pRight->eType==FTS5_AND && pParse->bPhraseToAnd)
|
||||
);
|
||||
|
||||
if( pLeft->eType==FTS5_AND ){
|
||||
|
||||
+19
-10
@@ -1700,6 +1700,7 @@ static int fts5UpdateMethod(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = fts5SpecialDelete(pTab, apVal);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
@@ -2874,14 +2875,16 @@ 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
|
||||
);
|
||||
pConfig->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
|
||||
@@ -2975,17 +2978,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;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ static int fts5AsciiCreate(
|
||||
int i;
|
||||
memset(p, 0, sizeof(AsciiTokenizer));
|
||||
memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
|
||||
fts5AsciiAddExceptions(p, zArg, 1);
|
||||
@@ -90,6 +90,7 @@ static int fts5AsciiCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && i<nArg ) rc = SQLITE_ERROR;
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5AsciiDelete((Fts5Tokenizer*)p);
|
||||
p = 0;
|
||||
@@ -381,17 +382,16 @@ static int fts5UnicodeCreate(
|
||||
}
|
||||
|
||||
/* Search for a "categories" argument */
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
if( 0==sqlite3_stricmp(azArg[i], "categories") ){
|
||||
zCat = azArg[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unicodeSetCategories(p, zCat);
|
||||
}
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
@@ -416,6 +416,7 @@ static int fts5UnicodeCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
|
||||
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -1298,7 +1299,7 @@ static int fts5TriCreate(
|
||||
int i;
|
||||
pNew->bFold = 1;
|
||||
pNew->iFoldParam = 0;
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
|
||||
@@ -1316,6 +1317,7 @@ static int fts5TriCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
|
||||
|
||||
if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
|
||||
@@ -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 {no such tokenizer: blah}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -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 {no such tokenizer: blah}}
|
||||
|
||||
|
||||
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}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -85,5 +85,25 @@ do_execsql_test 1.7 {
|
||||
SELECT highlight(t1, 0, '>', '<') FROM t1('BB mess');
|
||||
} {AAdont>BBmess<}
|
||||
|
||||
# 2024-08-06 https://sqlite.org/forum/forumpost/171bcc2bcd
|
||||
# Error handling of tokenize= arguments.
|
||||
#
|
||||
foreach {n tkz} {
|
||||
1 {ascii none}
|
||||
2 {unicode61 none}
|
||||
3 {porter none}
|
||||
4 {trigram none}
|
||||
5 {ascii none 0}
|
||||
6 {unicode61 none 0}
|
||||
7 {porter none 0}
|
||||
8 {trigram none 0}
|
||||
} {
|
||||
db eval {DROP TABLE IF EXISTS t2;}
|
||||
do_catchsql_test 2.$n "
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(a,b,c,tokenize='$tkz');
|
||||
" {1 {error in tokenizer constructor}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -69,6 +69,9 @@ do_execsql_test 2.0 {
|
||||
INSERT INTO t1 VALUES('abcdefghijklm');
|
||||
INSERT INTO t1 VALUES('กรุงเทพมหานคร');
|
||||
}
|
||||
do_catchsql_test 2.0.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(z, tokenize='trigram case_sensitive');
|
||||
} {1 {error in tokenizer constructor}}
|
||||
|
||||
foreach {tn s res} {
|
||||
1 abc "(abc)defghijklm"
|
||||
@@ -206,7 +209,7 @@ do_execsql_test 7.0 {
|
||||
(20, "жираф.png"),
|
||||
(30, "cat.png"),
|
||||
(40, "кот.png"),
|
||||
(50, "misic-🎵-.mp3");
|
||||
(50, "misic-ðµ-.mp3");
|
||||
}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT rowid FROM f WHERE +filename GLOB '*ир*';
|
||||
|
||||
@@ -21,6 +21,9 @@ do_execsql_test 1.0 "
|
||||
INSERT INTO t1 VALUES('abc\u0303defghijklm');
|
||||
INSERT INTO t1 VALUES('a\u0303b\u0303c\u0303defghijklm');
|
||||
"
|
||||
do_catchsql_test 1.0.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(z, tokenize='trigram remove_diacritics');
|
||||
} {1 {error in tokenizer constructor}}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT highlight(t1, 0, '(', ')') FROM t1('abc');
|
||||
|
||||
+35
-2
@@ -471,7 +471,7 @@ static void icuLoadCollation(
|
||||
UCollator *pUCollator; /* ICU library collation object */
|
||||
int rc; /* Return code from sqlite3_create_collation_x() */
|
||||
|
||||
assert(nArg==2);
|
||||
assert(nArg==2 || nArg==3);
|
||||
(void)nArg; /* Unused parameter */
|
||||
zLocale = (const char *)sqlite3_value_text(apArg[0]);
|
||||
zName = (const char *)sqlite3_value_text(apArg[1]);
|
||||
@@ -486,7 +486,39 @@ static void icuLoadCollation(
|
||||
return;
|
||||
}
|
||||
assert(p);
|
||||
|
||||
if(nArg==3){
|
||||
const char *zOption = (const char*)sqlite3_value_text(apArg[2]);
|
||||
static const struct {
|
||||
const char *zName;
|
||||
UColAttributeValue val;
|
||||
} aStrength[] = {
|
||||
{ "PRIMARY", UCOL_PRIMARY },
|
||||
{ "SECONDARY", UCOL_SECONDARY },
|
||||
{ "TERTIARY", UCOL_TERTIARY },
|
||||
{ "DEFAULT", UCOL_DEFAULT_STRENGTH },
|
||||
{ "QUARTERNARY", UCOL_QUATERNARY },
|
||||
{ "IDENTICAL", UCOL_IDENTICAL },
|
||||
};
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i>=sizeof(aStrength)/sizeof(aStrength[0]) ){
|
||||
sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p));
|
||||
sqlite3_str_appendf(pStr,
|
||||
"unknown collation strength \"%s\" - should be one of:",
|
||||
zOption);
|
||||
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
|
||||
sqlite3_str_appendf(pStr, " %s", aStrength[i].zName);
|
||||
}
|
||||
sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
|
||||
sqlite3_free(sqlite3_str_finish(pStr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
|
||||
icuCollationColl, icuCollationDel
|
||||
);
|
||||
@@ -509,6 +541,7 @@ int sqlite3IcuInit(sqlite3 *db){
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
} scalars[] = {
|
||||
{"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
|
||||
{"icu_load_collation",3,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
|
||||
{"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
|
||||
{"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
+154
-40
@@ -38,8 +38,9 @@ SQLITE_EXTENSION_INIT1
|
||||
typedef struct vtablog_vtab vtablog_vtab;
|
||||
struct vtablog_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
char *zDb; /* Schema name. argv[1] of xConnect/xCreate */
|
||||
char *zName; /* Table name. argv[2] of xConnect/xCreate */
|
||||
int nRow; /* Number of rows in the table */
|
||||
int iInst; /* Instance number for this vtablog table */
|
||||
int nCursor; /* Number of cursors created */
|
||||
};
|
||||
|
||||
@@ -167,15 +168,14 @@ static int vtablogConnectCreate(
|
||||
char **pzErr,
|
||||
int isCreate
|
||||
){
|
||||
static int nInst = 0;
|
||||
vtablog_vtab *pNew;
|
||||
int i;
|
||||
int rc;
|
||||
int iInst = ++nInst;
|
||||
char *zSchema = 0;
|
||||
char *zNRow = 0;
|
||||
|
||||
printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst);
|
||||
printf("%s.%s.%s():\n", argv[1], argv[2],
|
||||
isCreate ? "xCreate" : "xConnect");
|
||||
printf(" argc=%d\n", argc);
|
||||
for(i=0; i<argc; i++){
|
||||
printf(" argv[%d] = ", i);
|
||||
@@ -189,17 +189,18 @@ static int vtablogConnectCreate(
|
||||
for(i=3; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){
|
||||
return SQLITE_ERROR;
|
||||
rc = SQLITE_ERROR;
|
||||
goto vtablog_end_connect;
|
||||
}
|
||||
if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){
|
||||
return SQLITE_ERROR;
|
||||
rc = SQLITE_ERROR;
|
||||
goto vtablog_end_connect;
|
||||
}
|
||||
}
|
||||
|
||||
if( zSchema==0 ){
|
||||
*pzErr = sqlite3_mprintf("no schema defined");
|
||||
return SQLITE_ERROR;
|
||||
zSchema = sqlite3_mprintf("%s","CREATE TABLE x(a,b);");
|
||||
}
|
||||
printf(" schema = '%s'\n", zSchema);
|
||||
rc = sqlite3_declare_vtab(db, zSchema);
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
@@ -208,8 +209,14 @@ static int vtablogConnectCreate(
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->nRow = 10;
|
||||
if( zNRow ) pNew->nRow = atoi(zNRow);
|
||||
pNew->iInst = iInst;
|
||||
printf(" nrow = %d\n", pNew->nRow);
|
||||
pNew->zDb = sqlite3_mprintf("%s", argv[1]);
|
||||
pNew->zName = sqlite3_mprintf("%s", argv[2]);
|
||||
}
|
||||
|
||||
vtablog_end_connect:
|
||||
sqlite3_free(zSchema);
|
||||
sqlite3_free(zNRow);
|
||||
return rc;
|
||||
}
|
||||
static int vtablogCreate(
|
||||
@@ -237,7 +244,9 @@ static int vtablogConnect(
|
||||
*/
|
||||
static int vtablogDisconnect(sqlite3_vtab *pVtab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
|
||||
printf("vtablogDisconnect(%d)\n", pTab->iInst);
|
||||
printf("%s.%s.xDisconnect()\n", pTab->zDb, pTab->zName);
|
||||
sqlite3_free(pTab->zDb);
|
||||
sqlite3_free(pTab->zName);
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -247,7 +256,9 @@ static int vtablogDisconnect(sqlite3_vtab *pVtab){
|
||||
*/
|
||||
static int vtablogDestroy(sqlite3_vtab *pVtab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
|
||||
printf("vtablogDestroy(%d)\n", pTab->iInst);
|
||||
printf("%s.%s.xDestroy()\n", pTab->zDb, pTab->zName);
|
||||
sqlite3_free(pTab->zDb);
|
||||
sqlite3_free(pTab->zName);
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -258,7 +269,8 @@ static int vtablogDestroy(sqlite3_vtab *pVtab){
|
||||
static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)p;
|
||||
vtablog_cursor *pCur;
|
||||
printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor);
|
||||
printf("%s.%s.xOpen(cursor=%d)\n", pTab->zDb, pTab->zName,
|
||||
++pTab->nCursor);
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
@@ -273,7 +285,7 @@ static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
static int vtablogClose(sqlite3_vtab_cursor *cur){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor);
|
||||
printf("%s.%s.xClose(cursor=%d)\n", pTab->zDb, pTab->zName, pCur->iCursor);
|
||||
sqlite3_free(cur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -285,8 +297,9 @@ static int vtablogClose(sqlite3_vtab_cursor *cur){
|
||||
static int vtablogNext(sqlite3_vtab_cursor *cur){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n",
|
||||
pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1);
|
||||
printf("%s.%s.xNext(cursor=%d) rowid %d -> %d\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor,
|
||||
(int)pCur->iRowid, (int)pCur->iRowid+1);
|
||||
pCur->iRowid++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -310,8 +323,8 @@ static int vtablogColumn(
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid);
|
||||
}
|
||||
printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n",
|
||||
pTab->iInst, pCur->iCursor, i, zVal);
|
||||
printf("%s.%s.xColumn(cursor=%d, i=%d): [%s]\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor, i, zVal);
|
||||
sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -323,8 +336,8 @@ static int vtablogColumn(
|
||||
static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogRowid(tab=%d, cursor=%d): %d\n",
|
||||
pTab->iInst, pCur->iCursor, (int)pCur->iRowid);
|
||||
printf("%s.%s.xRowid(cursor=%d): %d\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor, (int)pCur->iRowid);
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -337,8 +350,8 @@ static int vtablogEof(sqlite3_vtab_cursor *cur){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
int rc = pCur->iRowid >= pTab->nRow;
|
||||
printf("vtablogEof(tab=%d, cursor=%d): %d\n",
|
||||
pTab->iInst, pCur->iCursor, rc);
|
||||
printf("%s.%s.xEof(cursor=%d): %d\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -417,7 +430,7 @@ static int vtablogFilter(
|
||||
){
|
||||
vtablog_cursor *pCur = (vtablog_cursor *)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor);
|
||||
printf("%s.%s.xFilter(cursor=%d):\n", pTab->zDb, pTab->zName, pCur->iCursor);
|
||||
pCur->iRowid = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -430,12 +443,37 @@ static int vtablogFilter(
|
||||
*/
|
||||
static int vtablogBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
sqlite3_index_info *p
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("vtablogBestIndex(tab=%d):\n", pTab->iInst);
|
||||
pIdxInfo->estimatedCost = (double)500;
|
||||
pIdxInfo->estimatedRows = 500;
|
||||
int i;
|
||||
printf("%s.%s.xBestIndex():\n", pTab->zDb, pTab->zName);
|
||||
printf(" colUsed: 0x%016llx\n", p->colUsed);
|
||||
printf(" nConstraint: %d\n", p->nConstraint);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
printf(
|
||||
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
|
||||
i,
|
||||
p->aConstraint[i].iColumn,
|
||||
p->aConstraint[i].iTermOffset,
|
||||
p->aConstraint[i].op,
|
||||
p->aConstraint[i].usable,
|
||||
sqlite3_vtab_collation(p,i));
|
||||
}
|
||||
printf(" nOrderBy: %d\n", p->nOrderBy);
|
||||
for(i=0; i<p->nOrderBy; i++){
|
||||
printf(" orderby[%d]: col=%d desc=%d\n",
|
||||
i,
|
||||
p->aOrderBy[i].iColumn,
|
||||
p->aOrderBy[i].desc);
|
||||
}
|
||||
p->estimatedCost = (double)500;
|
||||
p->estimatedRows = 500;
|
||||
printf(" idxNum=%d\n", p->idxNum);
|
||||
printf(" idxStr=NULL\n");
|
||||
printf(" orderByConsumed=%d\n", p->orderByConsumed);
|
||||
printf(" estimatedCost=%g\n", p->estimatedCost);
|
||||
printf(" estimatedRows=%lld\n", p->estimatedRows);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -454,7 +492,7 @@ static int vtablogUpdate(
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
int i;
|
||||
printf("vtablogUpdate(tab=%d):\n", pTab->iInst);
|
||||
printf("%s.%s.xUpdate():\n", pTab->zDb, pTab->zName);
|
||||
printf(" argc=%d\n", argc);
|
||||
for(i=0; i<argc; i++){
|
||||
printf(" argv[%d]=", i);
|
||||
@@ -464,12 +502,88 @@ static int vtablogUpdate(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int vtablogBegin(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xBegin()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogSync(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xSync()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogCommit(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xCommit()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRollback(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRollback()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogSavepoint(sqlite3_vtab *tab, int N){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xSavepoint(%d)\n", pTab->zDb, pTab->zName, N);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRelease(sqlite3_vtab *tab, int N){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRelease(%d)\n", pTab->zDb, pTab->zName, N);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRollbackTo(sqlite3_vtab *tab, int N){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRollbackTo(%d)\n", pTab->zDb, pTab->zName, N);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int vtablogFindMethod(
|
||||
sqlite3_vtab *tab,
|
||||
int nArg,
|
||||
const char *zName,
|
||||
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void **ppArg
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xFindMethod(nArg=%d, zName=%s)\n",
|
||||
pTab->zDb, pTab->zName, nArg, zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRename(sqlite3_vtab *tab, const char *zNew){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRename('%s')\n", pTab->zDb, pTab->zName, zNew);
|
||||
sqlite3_free(pTab->zName);
|
||||
pTab->zName = sqlite3_mprintf("%s", zNew);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Any table name that contains the text "shadow" is seen as a
|
||||
** shadow table. Nothing else is.
|
||||
*/
|
||||
static int vtablogShadowName(const char *zName){
|
||||
printf("vtablog.xShadowName('%s')\n", zName);
|
||||
return sqlite3_strglob("*shadow*", zName)==0;
|
||||
}
|
||||
|
||||
static int vtablogIntegrity(
|
||||
sqlite3_vtab *tab,
|
||||
const char *zSchema,
|
||||
const char *zTabName,
|
||||
int mFlags,
|
||||
char **pzErr
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xIntegrity(mFlags=0x%x)\n", pTab->zDb, pTab->zName, mFlags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** vtablog virtual table.
|
||||
*/
|
||||
static sqlite3_module vtablogModule = {
|
||||
0, /* iVersion */
|
||||
4, /* iVersion */
|
||||
vtablogCreate, /* xCreate */
|
||||
vtablogConnect, /* xConnect */
|
||||
vtablogBestIndex, /* xBestIndex */
|
||||
@@ -483,17 +597,17 @@ static sqlite3_module vtablogModule = {
|
||||
vtablogColumn, /* xColumn - read data */
|
||||
vtablogRowid, /* xRowid - read data */
|
||||
vtablogUpdate, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
0 /* xIntegrity */
|
||||
vtablogBegin, /* xBegin */
|
||||
vtablogSync, /* xSync */
|
||||
vtablogCommit, /* xCommit */
|
||||
vtablogRollback, /* xRollback */
|
||||
vtablogFindMethod, /* xFindMethod */
|
||||
vtablogRename, /* xRename */
|
||||
vtablogSavepoint, /* xSavepoint */
|
||||
vtablogRelease, /* xRelease */
|
||||
vtablogRollbackTo, /* xRollbackTo */
|
||||
vtablogShadowName, /* xShadowName */
|
||||
vtablogIntegrity /* xIntegrity */
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
+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
|
||||
|
||||
@@ -363,8 +363,8 @@ static int recoverError(
|
||||
va_start(ap, zFmt);
|
||||
if( zFmt ){
|
||||
z = sqlite3_vmprintf(zFmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
va_end(ap);
|
||||
sqlite3_free(p->zErrMsg);
|
||||
p->zErrMsg = z;
|
||||
p->errCode = errCode;
|
||||
@@ -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"]
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -1547,6 +1554,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
case capi.SQLITE_CONFIG_SQLLOG: // 21 /* xSqllog, void* */
|
||||
case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23 /* int nByte */
|
||||
default:
|
||||
/* maintenance note: we specifically do not include
|
||||
SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
|
||||
it's only for legacy support and no apps written with
|
||||
this API require that. */
|
||||
return capi.SQLITE_NOTFOUND;
|
||||
}
|
||||
};
|
||||
|
||||
+223
-51
@@ -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
|
||||
@@ -433,40 +574,56 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
out.returnVal = ()=>opt.resultRows;
|
||||
}
|
||||
if(opt.callback || opt.resultRows){
|
||||
switch((undefined===opt.rowMode)
|
||||
? 'array' : opt.rowMode) {
|
||||
case 'object': out.cbArg = (stmt)=>stmt.get(Object.create(null)); break;
|
||||
case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
|
||||
case 'stmt':
|
||||
if(Array.isArray(opt.resultRows)){
|
||||
toss3("exec(): invalid rowMode for a resultRows array: must",
|
||||
"be one of 'array', 'object',",
|
||||
"a result column number, or column name reference.");
|
||||
}
|
||||
out.cbArg = (stmt)=>stmt;
|
||||
switch((undefined===opt.rowMode) ? 'array' : opt.rowMode) {
|
||||
case 'object':
|
||||
out.cbArg = (stmt,cache)=>{
|
||||
if( !cache.columnNames ) cache.columnNames = stmt.getColumnNames([]);
|
||||
/* https://sqlite.org/forum/forumpost/3632183d2470617d:
|
||||
conversion of rows to objects (key/val pairs) is
|
||||
somewhat expensive for large data sets because of the
|
||||
native-to-JS conversion of the column names. If we
|
||||
instead cache the names and build objects from that
|
||||
list of strings, it can run twice as fast. The
|
||||
difference is not noticeable for small data sets but
|
||||
becomes human-perceivable when enough rows are
|
||||
involved. */
|
||||
const row = stmt.get([]);
|
||||
const rv = Object.create(null);
|
||||
for( const i in cache.columnNames ) rv[cache.columnNames[i]] = row[i];
|
||||
return rv;
|
||||
};
|
||||
break;
|
||||
case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
|
||||
case 'stmt':
|
||||
if(Array.isArray(opt.resultRows)){
|
||||
toss3("exec(): invalid rowMode for a resultRows array: must",
|
||||
"be one of 'array', 'object',",
|
||||
"a result column number, or column name reference.");
|
||||
}
|
||||
out.cbArg = (stmt)=>stmt;
|
||||
break;
|
||||
default:
|
||||
if(util.isInt32(opt.rowMode)){
|
||||
out.cbArg = (stmt)=>stmt.get(opt.rowMode);
|
||||
break;
|
||||
default:
|
||||
if(util.isInt32(opt.rowMode)){
|
||||
out.cbArg = (stmt)=>stmt.get(opt.rowMode);
|
||||
break;
|
||||
}else if('string'===typeof opt.rowMode
|
||||
&& opt.rowMode.length>1
|
||||
&& '$'===opt.rowMode[0]){
|
||||
/* "$X": fetch column named "X" (case-sensitive!). Prior
|
||||
to 2022-12-14 ":X" and "@X" were also permitted, but
|
||||
having so many options is unnecessary and likely to
|
||||
cause confusion. */
|
||||
const $colName = opt.rowMode.substr(1);
|
||||
out.cbArg = (stmt)=>{
|
||||
const rc = stmt.get(Object.create(null))[$colName];
|
||||
return (undefined===rc)
|
||||
? toss3(capi.SQLITE_NOTFOUND,
|
||||
"exec(): unknown result column:",$colName)
|
||||
: rc;
|
||||
};
|
||||
break;
|
||||
}
|
||||
toss3("Invalid rowMode:",opt.rowMode);
|
||||
}else if('string'===typeof opt.rowMode
|
||||
&& opt.rowMode.length>1
|
||||
&& '$'===opt.rowMode[0]){
|
||||
/* "$X": fetch column named "X" (case-sensitive!). Prior
|
||||
to 2022-12-14 ":X" and "@X" were also permitted, but
|
||||
having so many options is unnecessary and likely to
|
||||
cause confusion. */
|
||||
const $colName = opt.rowMode.substr(1);
|
||||
out.cbArg = (stmt)=>{
|
||||
const rc = stmt.get(Object.create(null))[$colName];
|
||||
return (undefined===rc)
|
||||
? toss3(capi.SQLITE_NOTFOUND,
|
||||
"exec(): unknown result column:",$colName)
|
||||
: rc;
|
||||
};
|
||||
break;
|
||||
}
|
||||
toss3("Invalid rowMode:",opt.rowMode);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
@@ -884,10 +1041,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
and names. */) ? 0 : 1;
|
||||
evalFirstResult = false;
|
||||
if(arg.cbArg || resultRows){
|
||||
const cbArgCache = Object.create(null)
|
||||
/* 2nd arg for arg.cbArg, used by (at least) row-to-object
|
||||
converter */;
|
||||
for(; stmt.step(); stmt._lockedByExec = false){
|
||||
if(0===gotColNames++) stmt.getColumnNames(opt.columnNames);
|
||||
if(0===gotColNames++){
|
||||
stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || []));
|
||||
}
|
||||
stmt._lockedByExec = true;
|
||||
const row = arg.cbArg(stmt);
|
||||
const row = arg.cbArg(stmt,cbArgCache);
|
||||
if(resultRows) resultRows.push(row);
|
||||
if(callback && false === callback.call(opt, row, stmt)){
|
||||
break;
|
||||
@@ -1522,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
|
||||
@@ -1706,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,
|
||||
@@ -1906,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");
|
||||
|
||||
@@ -87,35 +87,6 @@ const installAsyncProxy = function(){
|
||||
const log = (...args)=>logImpl(2, ...args);
|
||||
const warn = (...args)=>logImpl(1, ...args);
|
||||
const error = (...args)=>logImpl(0, ...args);
|
||||
const metrics = Object.create(null);
|
||||
metrics.reset = ()=>{
|
||||
let k;
|
||||
const r = (m)=>(m.count = m.time = m.wait = 0);
|
||||
for(k in state.opIds){
|
||||
r(metrics[k] = Object.create(null));
|
||||
}
|
||||
let s = metrics.s11n = Object.create(null);
|
||||
s = s.serialize = Object.create(null);
|
||||
s.count = s.time = 0;
|
||||
s = metrics.s11n.deserialize = Object.create(null);
|
||||
s.count = s.time = 0;
|
||||
};
|
||||
metrics.dump = ()=>{
|
||||
let k, n = 0, t = 0, w = 0;
|
||||
for(k in state.opIds){
|
||||
const m = metrics[k];
|
||||
n += m.count;
|
||||
t += m.time;
|
||||
w += m.wait;
|
||||
m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0;
|
||||
}
|
||||
console.log(globalThis?.location?.href,
|
||||
"metrics for",globalThis?.location?.href,":\n",
|
||||
metrics,
|
||||
"\nTotal of",n,"op(s) for",t,"ms",
|
||||
"approx",w,"ms spent waiting on OPFS APIs.");
|
||||
console.log("Serialization metrics:",metrics.s11n);
|
||||
};
|
||||
|
||||
/**
|
||||
__openFiles is a map of sqlite3_file pointers (integers) to
|
||||
@@ -265,23 +236,34 @@ const installAsyncProxy = function(){
|
||||
this.name = 'GetSyncHandleError';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Attempts to find a suitable SQLITE_xyz result code for Error
|
||||
object e. Returns either such a translation or rc if if it does
|
||||
not know how to translate the exception.
|
||||
*/
|
||||
GetSyncHandleError.convertRc = (e,rc)=>{
|
||||
if(1){
|
||||
return (
|
||||
e instanceof GetSyncHandleError
|
||||
&& ((e.cause.name==='NoModificationAllowedError')
|
||||
/* Inconsistent exception.name from Chrome/ium with the
|
||||
same exception.message text: */
|
||||
|| (e.cause.name==='DOMException'
|
||||
&& 0===e.cause.message.indexOf('Access Handles cannot')))
|
||||
) ? (
|
||||
/*console.warn("SQLITE_BUSY",e),*/
|
||||
state.sq3Codes.SQLITE_BUSY
|
||||
) : rc;
|
||||
}else{
|
||||
return rc;
|
||||
if( e instanceof GetSyncHandleError ){
|
||||
if( e.cause.name==='NoModificationAllowedError'
|
||||
/* Inconsistent exception.name from Chrome/ium with the
|
||||
same exception.message text: */
|
||||
|| (e.cause.name==='DOMException'
|
||||
&& 0===e.cause.message.indexOf('Access Handles cannot')) ){
|
||||
return state.sq3Codes.SQLITE_BUSY;
|
||||
}else if( 'NotFoundError'===e.cause.name ){
|
||||
/**
|
||||
Maintenance reminder: SQLITE_NOTFOUND, though it looks like
|
||||
a good match, has different semantics than NotFoundError
|
||||
and is not suitable here.
|
||||
*/
|
||||
return state.sq3Codes.SQLITE_CANTOPEN;
|
||||
}
|
||||
}else if( 'NotFoundError'===e?.name ){
|
||||
return state.sq3Codes.SQLITE_CANTOPEN;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
};
|
||||
|
||||
/**
|
||||
Returns the sync access handle associated with the given file
|
||||
handle object (which must be a valid handle object, as created by
|
||||
@@ -347,37 +329,6 @@ const installAsyncProxy = function(){
|
||||
if(fh.readOnly) toss(opName+"(): File is read-only: "+fh.filenameAbs);
|
||||
};
|
||||
|
||||
/**
|
||||
We track 2 different timers: the "metrics" timer records how much
|
||||
time we spend performing work. The "wait" timer records how much
|
||||
time we spend waiting on the underlying OPFS timer. See the calls
|
||||
to mTimeStart(), mTimeEnd(), wTimeStart(), and wTimeEnd()
|
||||
throughout this file to see how they're used.
|
||||
*/
|
||||
const __mTimer = Object.create(null);
|
||||
__mTimer.op = undefined;
|
||||
__mTimer.start = undefined;
|
||||
const mTimeStart = (op)=>{
|
||||
__mTimer.start = performance.now();
|
||||
__mTimer.op = op;
|
||||
//metrics[op] || toss("Maintenance required: missing metrics for",op);
|
||||
++metrics[op].count;
|
||||
};
|
||||
const mTimeEnd = ()=>(
|
||||
metrics[__mTimer.op].time += performance.now() - __mTimer.start
|
||||
);
|
||||
const __wTimer = Object.create(null);
|
||||
__wTimer.op = undefined;
|
||||
__wTimer.start = undefined;
|
||||
const wTimeStart = (op)=>{
|
||||
__wTimer.start = performance.now();
|
||||
__wTimer.op = op;
|
||||
//metrics[op] || toss("Maintenance required: missing metrics for",op);
|
||||
};
|
||||
const wTimeEnd = ()=>(
|
||||
metrics[__wTimer.op].wait += performance.now() - __wTimer.start
|
||||
);
|
||||
|
||||
/**
|
||||
Gets set to true by the 'opfs-async-shutdown' command to quit the
|
||||
wait loop. This is only intended for debugging purposes: we cannot
|
||||
@@ -388,37 +339,24 @@ const installAsyncProxy = function(){
|
||||
|
||||
/**
|
||||
Asynchronous wrappers for sqlite3_vfs and sqlite3_io_methods
|
||||
methods, as well as helpers like mkdir(). Maintenance reminder:
|
||||
members are in alphabetical order to simplify finding them.
|
||||
methods, as well as helpers like mkdir().
|
||||
*/
|
||||
const vfsAsyncImpls = {
|
||||
'opfs-async-metrics': async ()=>{
|
||||
mTimeStart('opfs-async-metrics');
|
||||
metrics.dump();
|
||||
storeAndNotify('opfs-async-metrics', 0);
|
||||
mTimeEnd();
|
||||
},
|
||||
'opfs-async-shutdown': async ()=>{
|
||||
flagAsyncShutdown = true;
|
||||
storeAndNotify('opfs-async-shutdown', 0);
|
||||
},
|
||||
mkdir: async (dirname)=>{
|
||||
mTimeStart('mkdir');
|
||||
let rc = 0;
|
||||
wTimeStart('mkdir');
|
||||
try {
|
||||
await getDirForFilename(dirname+"/filepart", true);
|
||||
}catch(e){
|
||||
state.s11n.storeException(2,e);
|
||||
rc = state.sq3Codes.SQLITE_IOERR;
|
||||
}finally{
|
||||
wTimeEnd();
|
||||
}
|
||||
storeAndNotify('mkdir', rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xAccess: async (filename)=>{
|
||||
mTimeStart('xAccess');
|
||||
/* OPFS cannot support the full range of xAccess() queries
|
||||
sqlite3 calls for. We can essentially just tell if the file
|
||||
is accessible, but if it is then it's automatically writable
|
||||
@@ -431,26 +369,20 @@ const installAsyncProxy = function(){
|
||||
accessible, non-0 means not accessible.
|
||||
*/
|
||||
let rc = 0;
|
||||
wTimeStart('xAccess');
|
||||
try{
|
||||
const [dh, fn] = await getDirForFilename(filename);
|
||||
await dh.getFileHandle(fn);
|
||||
}catch(e){
|
||||
state.s11n.storeException(2,e);
|
||||
rc = state.sq3Codes.SQLITE_IOERR;
|
||||
}finally{
|
||||
wTimeEnd();
|
||||
}
|
||||
storeAndNotify('xAccess', rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xClose: async function(fid/*sqlite3_file pointer*/){
|
||||
const opName = 'xClose';
|
||||
mTimeStart(opName);
|
||||
__implicitLocks.delete(fid);
|
||||
const fh = __openFiles[fid];
|
||||
let rc = 0;
|
||||
wTimeStart(opName);
|
||||
if(fh){
|
||||
delete __openFiles[fid];
|
||||
await closeSyncHandle(fh);
|
||||
@@ -462,15 +394,11 @@ const installAsyncProxy = function(){
|
||||
state.s11n.serialize();
|
||||
rc = state.sq3Codes.SQLITE_NOTFOUND;
|
||||
}
|
||||
wTimeEnd();
|
||||
storeAndNotify(opName, rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xDelete: async function(...args){
|
||||
mTimeStart('xDelete');
|
||||
const rc = await vfsAsyncImpls.xDeleteNoWait(...args);
|
||||
storeAndNotify('xDelete', rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xDeleteNoWait: async function(filename, syncDir = 0, recursive = false){
|
||||
/* The syncDir flag is, for purposes of the VFS API's semantics,
|
||||
@@ -486,7 +414,6 @@ const installAsyncProxy = function(){
|
||||
is false.
|
||||
*/
|
||||
let rc = 0;
|
||||
wTimeStart('xDelete');
|
||||
try {
|
||||
while(filename){
|
||||
const [hDir, filenamePart] = await getDirForFilename(filename, false);
|
||||
@@ -502,14 +429,11 @@ const installAsyncProxy = function(){
|
||||
state.s11n.storeException(2,e);
|
||||
rc = state.sq3Codes.SQLITE_IOERR_DELETE;
|
||||
}
|
||||
wTimeEnd();
|
||||
return rc;
|
||||
},
|
||||
xFileSize: async function(fid/*sqlite3_file pointer*/){
|
||||
mTimeStart('xFileSize');
|
||||
const fh = __openFiles[fid];
|
||||
let rc = 0;
|
||||
wTimeStart('xFileSize');
|
||||
try{
|
||||
const sz = await (await getSyncHandle(fh,'xFileSize')).getSize();
|
||||
state.s11n.serialize(Number(sz));
|
||||
@@ -518,19 +442,15 @@ const installAsyncProxy = function(){
|
||||
rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR);
|
||||
}
|
||||
await releaseImplicitLock(fh);
|
||||
wTimeEnd();
|
||||
storeAndNotify('xFileSize', rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xLock: async function(fid/*sqlite3_file pointer*/,
|
||||
lockType/*SQLITE_LOCK_...*/){
|
||||
mTimeStart('xLock');
|
||||
const fh = __openFiles[fid];
|
||||
let rc = 0;
|
||||
const oldLockType = fh.xLock;
|
||||
fh.xLock = lockType;
|
||||
if( !fh.syncHandle ){
|
||||
wTimeStart('xLock');
|
||||
try {
|
||||
await getSyncHandle(fh,'xLock');
|
||||
__implicitLocks.delete(fid);
|
||||
@@ -539,18 +459,14 @@ const installAsyncProxy = function(){
|
||||
rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_LOCK);
|
||||
fh.xLock = oldLockType;
|
||||
}
|
||||
wTimeEnd();
|
||||
}
|
||||
storeAndNotify('xLock',rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xOpen: async function(fid/*sqlite3_file pointer*/, filename,
|
||||
flags/*SQLITE_OPEN_...*/,
|
||||
opfsFlags/*OPFS_...*/){
|
||||
const opName = 'xOpen';
|
||||
mTimeStart(opName);
|
||||
const create = (state.sq3Codes.SQLITE_OPEN_CREATE & flags);
|
||||
wTimeStart('xOpen');
|
||||
try{
|
||||
let hDir, filenamePart;
|
||||
try {
|
||||
@@ -558,8 +474,6 @@ const installAsyncProxy = function(){
|
||||
}catch(e){
|
||||
state.s11n.storeException(1,e);
|
||||
storeAndNotify(opName, state.sq3Codes.SQLITE_NOTFOUND);
|
||||
mTimeEnd();
|
||||
wTimeEnd();
|
||||
return;
|
||||
}
|
||||
if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){
|
||||
@@ -571,7 +485,6 @@ const installAsyncProxy = function(){
|
||||
}
|
||||
}
|
||||
const hFile = await hDir.getFileHandle(filenamePart, {create});
|
||||
wTimeEnd();
|
||||
const fh = Object.assign(Object.create(null),{
|
||||
fid: fid,
|
||||
filenameAbs: filename,
|
||||
@@ -586,76 +499,50 @@ const installAsyncProxy = function(){
|
||||
fh.releaseImplicitLocks =
|
||||
(opfsFlags & state.opfsFlags.OPFS_UNLOCK_ASAP)
|
||||
|| state.opfsFlags.defaultUnlockAsap;
|
||||
if(0 /* this block is modelled after something wa-sqlite
|
||||
does but it leads to immediate contention on journal files.
|
||||
Update: this approach reportedly only works for DELETE journal
|
||||
mode. */
|
||||
&& (0===(flags & state.sq3Codes.SQLITE_OPEN_MAIN_DB))){
|
||||
/* sqlite does not lock these files, so go ahead and grab an OPFS
|
||||
lock. */
|
||||
fh.xLock = "xOpen"/* Truthy value to keep entry from getting
|
||||
flagged as auto-locked. String value so
|
||||
that we can easily distinguish is later
|
||||
if needed. */;
|
||||
await getSyncHandle(fh,'xOpen');
|
||||
}
|
||||
__openFiles[fid] = fh;
|
||||
storeAndNotify(opName, 0);
|
||||
}catch(e){
|
||||
wTimeEnd();
|
||||
error(opName,e);
|
||||
state.s11n.storeException(1,e);
|
||||
storeAndNotify(opName, state.sq3Codes.SQLITE_IOERR);
|
||||
}
|
||||
mTimeEnd();
|
||||
},
|
||||
xRead: async function(fid/*sqlite3_file pointer*/,n,offset64){
|
||||
mTimeStart('xRead');
|
||||
let rc = 0, nRead;
|
||||
const fh = __openFiles[fid];
|
||||
try{
|
||||
wTimeStart('xRead');
|
||||
nRead = (await getSyncHandle(fh,'xRead')).read(
|
||||
fh.sabView.subarray(0, n),
|
||||
{at: Number(offset64)}
|
||||
);
|
||||
wTimeEnd();
|
||||
if(nRead < n){/* Zero-fill remaining bytes */
|
||||
fh.sabView.fill(0, nRead, n);
|
||||
rc = state.sq3Codes.SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
}catch(e){
|
||||
if(undefined===nRead) wTimeEnd();
|
||||
error("xRead() failed",e,fh);
|
||||
state.s11n.storeException(1,e);
|
||||
rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_READ);
|
||||
}
|
||||
await releaseImplicitLock(fh);
|
||||
storeAndNotify('xRead',rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xSync: async function(fid/*sqlite3_file pointer*/,flags/*ignored*/){
|
||||
mTimeStart('xSync');
|
||||
const fh = __openFiles[fid];
|
||||
let rc = 0;
|
||||
if(!fh.readOnly && fh.syncHandle){
|
||||
try {
|
||||
wTimeStart('xSync');
|
||||
await fh.syncHandle.flush();
|
||||
}catch(e){
|
||||
state.s11n.storeException(2,e);
|
||||
rc = state.sq3Codes.SQLITE_IOERR_FSYNC;
|
||||
}
|
||||
wTimeEnd();
|
||||
}
|
||||
storeAndNotify('xSync',rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xTruncate: async function(fid/*sqlite3_file pointer*/,size){
|
||||
mTimeStart('xTruncate');
|
||||
let rc = 0;
|
||||
const fh = __openFiles[fid];
|
||||
wTimeStart('xTruncate');
|
||||
try{
|
||||
affirmNotRO('xTruncate', fh);
|
||||
await (await getSyncHandle(fh,'xTruncate')).truncate(size);
|
||||
@@ -665,33 +552,25 @@ const installAsyncProxy = function(){
|
||||
rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_TRUNCATE);
|
||||
}
|
||||
await releaseImplicitLock(fh);
|
||||
wTimeEnd();
|
||||
storeAndNotify('xTruncate',rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xUnlock: async function(fid/*sqlite3_file pointer*/,
|
||||
lockType/*SQLITE_LOCK_...*/){
|
||||
mTimeStart('xUnlock');
|
||||
let rc = 0;
|
||||
const fh = __openFiles[fid];
|
||||
if( state.sq3Codes.SQLITE_LOCK_NONE===lockType
|
||||
&& fh.syncHandle ){
|
||||
wTimeStart('xUnlock');
|
||||
try { await closeSyncHandle(fh) }
|
||||
catch(e){
|
||||
state.s11n.storeException(1,e);
|
||||
rc = state.sq3Codes.SQLITE_IOERR_UNLOCK;
|
||||
}
|
||||
wTimeEnd();
|
||||
}
|
||||
storeAndNotify('xUnlock',rc);
|
||||
mTimeEnd();
|
||||
},
|
||||
xWrite: async function(fid/*sqlite3_file pointer*/,n,offset64){
|
||||
mTimeStart('xWrite');
|
||||
let rc;
|
||||
const fh = __openFiles[fid];
|
||||
wTimeStart('xWrite');
|
||||
try{
|
||||
affirmNotRO('xWrite', fh);
|
||||
rc = (
|
||||
@@ -705,9 +584,7 @@ const installAsyncProxy = function(){
|
||||
rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_WRITE);
|
||||
}
|
||||
await releaseImplicitLock(fh);
|
||||
wTimeEnd();
|
||||
storeAndNotify('xWrite',rc);
|
||||
mTimeEnd();
|
||||
}
|
||||
}/*vfsAsyncImpls*/;
|
||||
|
||||
@@ -741,8 +618,6 @@ const installAsyncProxy = function(){
|
||||
}
|
||||
};
|
||||
state.s11n.deserialize = function(clear=false){
|
||||
++metrics.s11n.deserialize.count;
|
||||
const t = performance.now();
|
||||
const argc = viewU8[0];
|
||||
const rc = argc ? [] : null;
|
||||
if(argc){
|
||||
@@ -767,12 +642,9 @@ const installAsyncProxy = function(){
|
||||
}
|
||||
if(clear) viewU8[0] = 0;
|
||||
//log("deserialize:",argc, rc);
|
||||
metrics.s11n.deserialize.time += performance.now() - t;
|
||||
return rc;
|
||||
};
|
||||
state.s11n.serialize = function(...args){
|
||||
const t = performance.now();
|
||||
++metrics.s11n.serialize.count;
|
||||
if(args.length){
|
||||
//log("serialize():",args);
|
||||
const typeIds = [];
|
||||
@@ -803,7 +675,6 @@ const installAsyncProxy = function(){
|
||||
}else{
|
||||
viewU8[0] = 0;
|
||||
}
|
||||
metrics.s11n.serialize.time += performance.now() - t;
|
||||
};
|
||||
|
||||
state.s11n.storeException = state.asyncS11nExceptions
|
||||
@@ -885,7 +756,6 @@ const installAsyncProxy = function(){
|
||||
}
|
||||
});
|
||||
initS11n();
|
||||
metrics.reset();
|
||||
log("init state",state);
|
||||
wPost('opfs-async-inited');
|
||||
waitLoop();
|
||||
@@ -898,9 +768,6 @@ const installAsyncProxy = function(){
|
||||
waitLoop();
|
||||
}
|
||||
break;
|
||||
case 'opfs-async-metrics':
|
||||
metrics.dump();
|
||||
break;
|
||||
}
|
||||
};
|
||||
wPost('opfs-async-loaded');
|
||||
|
||||
@@ -1272,7 +1272,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return poolUtil;
|
||||
}).catch(async (e)=>{
|
||||
await thePool.removeVfs().catch(()=>{});
|
||||
return e;
|
||||
throw e;
|
||||
});
|
||||
}).catch((err)=>{
|
||||
//error("rejecting promise:",err);
|
||||
|
||||
@@ -392,6 +392,7 @@ const installOpfsVfs = function callee(options){
|
||||
'SQLITE_ACCESS_EXISTS',
|
||||
'SQLITE_ACCESS_READWRITE',
|
||||
'SQLITE_BUSY',
|
||||
'SQLITE_CANTOPEN',
|
||||
'SQLITE_ERROR',
|
||||
'SQLITE_IOERR',
|
||||
'SQLITE_IOERR_ACCESS',
|
||||
@@ -444,7 +445,7 @@ const installOpfsVfs = function callee(options){
|
||||
OPFS_UNLINK_BEFORE_OPEN: 0x02,
|
||||
/**
|
||||
If true, any async routine which implicitly acquires a sync
|
||||
access handle (i.e. an OPFS lock) will release that locks at
|
||||
access handle (i.e. an OPFS lock) will release that lock at
|
||||
the end of the call which acquires it. If false, such
|
||||
"autolocks" are not released until the VFS is idle for some
|
||||
brief amount of time.
|
||||
@@ -471,9 +472,22 @@ const installOpfsVfs = function callee(options){
|
||||
Atomics.notify(state.sabOPView, state.opIds.whichOp)
|
||||
/* async thread will take over here */;
|
||||
const t = performance.now();
|
||||
Atomics.wait(state.sabOPView, state.opIds.rc, -1)
|
||||
/* When this wait() call returns, the async half will have
|
||||
completed the operation and reported its results. */;
|
||||
while('not-equal'!==Atomics.wait(state.sabOPView, state.opIds.rc, -1)){
|
||||
/*
|
||||
The reason for this loop is buried in the details of a long
|
||||
discussion at:
|
||||
|
||||
https://github.com/sqlite/sqlite-wasm/issues/12
|
||||
|
||||
Summary: in at least one browser flavor, under high loads,
|
||||
the wait()/notify() pairings can get out of sync. Calling
|
||||
wait() here until it returns 'not-equal' gets them back in
|
||||
sync.
|
||||
*/
|
||||
}
|
||||
/* When the above wait() call returns 'not-equal', the async
|
||||
half will have completed the operation and reported its results
|
||||
in the state.opIds.rc slot of the SAB. */
|
||||
const rc = Atomics.load(state.sabOPView, state.opIds.rc);
|
||||
metrics[op].wait += performance.now() - t;
|
||||
if(rc && state.asyncS11nExceptions){
|
||||
@@ -720,9 +734,18 @@ const installOpfsVfs = function callee(options){
|
||||
involve an inherent race condition. For the time being,
|
||||
pending a better solution, we simply report whether the
|
||||
given pFile is open.
|
||||
|
||||
Update 2024-06-12: based on forum discussions, this
|
||||
function now always sets pOut to 0 (false):
|
||||
|
||||
https://sqlite.org/forum/forumpost/a2f573b00cda1372
|
||||
*/
|
||||
const f = __openFiles[pFile];
|
||||
wasm.poke(pOut, f.lockType ? 1 : 0, 'i32');
|
||||
if(1){
|
||||
wasm.poke(pOut, 0, 'i32');
|
||||
}else{
|
||||
const f = __openFiles[pFile];
|
||||
wasm.poke(pOut, f.lockType ? 1 : 0, 'i32');
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
xClose: function(pFile){
|
||||
@@ -738,7 +761,6 @@ const installOpfsVfs = function callee(options){
|
||||
return rc;
|
||||
},
|
||||
xDeviceCharacteristics: function(pFile){
|
||||
//debug("xDeviceCharacteristics(",pFile,")");
|
||||
return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
|
||||
},
|
||||
xFileControl: function(pFile, opId, pArg){
|
||||
|
||||
+16
-23
@@ -545,6 +545,10 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
DefInt(SQLITE_CONFIG_SMALL_MALLOC);
|
||||
DefInt(SQLITE_CONFIG_SORTERREF_SIZE);
|
||||
DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE);
|
||||
/* maintenance note: we specifically do not include
|
||||
SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
|
||||
it's only for legacy support and no apps written with
|
||||
this API require that. */
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(dataTypes) {
|
||||
@@ -1674,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 */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Change\sEXPLAIN\sQUERY\sPLAN\soutput\sto\ssay\s"USE\sTEMP\sB-TREE\sFOR\sLAST\sTERM\sOF\sORDER\sBY",\sor\s"LAST\sN\sTERMS\sOF\sORDER\sBY",\sinstead\sof\s"RIGHT\sPART\sOF\sORDER\sBY".
|
||||
D 2024-03-20T16:27:08.690
|
||||
C Version\s3.46.1
|
||||
D 2024-08-13T09:16:08.704
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -7,7 +7,7 @@ F Makefile.in 993a7874e3d3721df61846f03dda4a9ef7490da11953ae36ba1bb0c0346eaf4a
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc e64a52619310d3067f6c38f56eedd15918a82dade70954197d6da486ad99d7f4
|
||||
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
|
||||
F VERSION c84541c6a9e8426462176fbb1f9ecb5cfd7d1bb56228053ff7eeba8841673eb6
|
||||
F VERSION 01b0b94ee03b29c27cb72ef03c460cd9476dee97b0cf8cf74b17a201e199820a
|
||||
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 629148599fb2c29003b34e72dd161473b5fe23b6f26a2281200e9581daaede95
|
||||
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 1728380292e4153caf04870b0734c771b9cdc73be655181618f7b8253f2d9d5c x
|
||||
F configure.ac f25bd7843120f2c2b8bc9db5a92b0502bbdd28e68907415c3d42fc8e57c657b9
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
@@ -53,12 +53,12 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
|
||||
F ext/consio/console_io.c f32b757c9ee7fdf68e7586bee306f8368759e7cd12febb2a6839199b1c1af395 x
|
||||
F ext/consio/console_io.c b4885dfea71ed583315de8f0792a29d5fc7c7460b4a26c0aebe5cda5da8b38f8 x
|
||||
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 53a749de08939e3bc14f804e97410927d46fa772cbce0247d7e8fa6fc2523b0c
|
||||
F ext/expert/sqlite3expert.c c8cea5ff15fbe792cccc4992a9b40b706411c41d32611f617897fecac6ff06a4
|
||||
F ext/expert/expert1.test 661f873fd451127edf822ef0d520088faa319135f6a15bd10be6801ac284ac9b
|
||||
F ext/expert/sqlite3expert.c 8b09aeb2b95a9fca8b6628b522bf4d69aa746ff64c38eb1e99a9b5fad8cf03b9
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
|
||||
@@ -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
|
||||
@@ -92,20 +92,20 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl bc3a0ca78be7d3df08e7602c00ca48021ebae40682d75eb001bfdf6e54ffb44e
|
||||
F ext/fts5/fts5.h ecba24fed7b359b3a53016bb07e411b3b4c9cdf163aa141006536423a63b611e
|
||||
F ext/fts5/fts5.h 8856e11a5f0269cd346754cea0765efe8089635b80cad3222e8bfdb08cd5348a
|
||||
F ext/fts5/fts5Int.h defa43c0932265138ee910ca416e6baccf8b774e0f3d610e74be1ab2880e9834
|
||||
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_expr.c d6a48d81aa96d68090187059f48dba2184e0cb0fd3b50a5a84a649a865cb31a5
|
||||
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 0a8fc885851d76af6ea670090231ed23b9f8f349f44080e79a0f59b1d54511bb
|
||||
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 2321cbcef0bb99ed326d58f02cbd907e678c86572a72a434d08f6cb78e346dbd
|
||||
F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c 209e0c151e108d5f3621fa24b91e9b02f3750ee6c3f9ccec312df39481b68a09
|
||||
@@ -126,7 +126,7 @@ 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 e0866d924289423164c539576229ea589990e6dd38d05a0b6f8752ad51d70bb4
|
||||
F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
|
||||
F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
|
||||
F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
|
||||
@@ -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 f7a9dc2c2b8db0db024eaa546ed56add97f869b67064e258c36dcdd0243f25f2
|
||||
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
|
||||
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
@@ -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
|
||||
@@ -228,9 +228,9 @@ F ext/fts5/test/fts5synonym2.test e2f6ff68c4fbe12a866a3a87510f553d9dac99bcb74c10
|
||||
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/fts5tokenizer2.test cb5428c7cfb3b6a74b7adfcde65506e329112003e8dffa7501d01c2d18d02569
|
||||
F ext/fts5/test/fts5trigram.test 6c4e37864f3e7d90673db5563d9736d7e40080ab94d10ebdffa94c1b77941da0
|
||||
F ext/fts5/test/fts5trigram2.test 9fe4207f8a4241747aff1005258b564958588d21bfd240d6cd4c2e955d31c156
|
||||
F ext/fts5/test/fts5tokenizer2.test b9d734c1b10bc317a377ffea3ecb5c2937313113a02e364f167d0c7f8c81c282
|
||||
F ext/fts5/test/fts5trigram.test be914555deb8504dde682bd5aa343d00c4da37dfad20709a5bac30d5f97f2ef5
|
||||
F ext/fts5/test/fts5trigram2.test 4043f8836bbbb0ce37b86dd1e741431c6c595c7e4ba4fc8e26f21dc3b540e228
|
||||
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 c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
||||
F ext/icu/icu.c 3add8197e0a86c1761771a39500ebae749438bcf1836160b407a56b4eaa8721c
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/intck/intck1.test f3a3cba14b6aeff145ffa5515546dd22f7510dad91512e519f43b92b56514012
|
||||
F ext/intck/intck2.test d2457c7e5e5b688046d15ebe08a1e1427cc5e7a6dc8d6af215f42e8bcaf67304
|
||||
@@ -391,7 +391,7 @@ F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f82
|
||||
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,12 +411,12 @@ 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/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
|
||||
F ext/misc/totype.c 75ed9827d19cc3b434fc2aeb60725d4d46e1534373615612a4d1cfdcc3d60922
|
||||
@@ -426,7 +426,7 @@ F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917
|
||||
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
||||
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
||||
F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808d269d
|
||||
F ext/misc/vtablog.c f2c9d41afe00b51b2c8307b79f508eb0c2dcd57bae074807944e73376fcf15b7
|
||||
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
|
||||
F ext/misc/zipfile.c 64cb3d98b6316586e6056d182051aa9d28fdedfbf4b908e6b7a7d70209b1db11
|
||||
@@ -478,13 +478,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 +494,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 2dcf6b56c5e0e2b43fc4c6115b689ab194c374ced7f7f8380ad9a24d8ef24ac9
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
@@ -566,6 +568,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 +584,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 +609,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 587dc6db2d69329a5f4cb9635c377f516cf4a8e30f443f33380e5044889ec71b
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
|
||||
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 9704b77b5eb9d0d498ceeaf3e7a837021b14c52ac15d6556c7f97e278ec725c3
|
||||
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-opfs-async-proxy.js dd4054e4f673027c330c96a04cf0a03b118156f01b076dc4e9d604dbdd7bfc51
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 5a430874906ff3f4a6ca69aadf0c2aaedc1bb45489b8365bff7e955a83a8d42a
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 8433ee332d5f5e39fb19427fccb7bad7f44aa99b5504daad3343fc128c311e78
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 834dcea56e27064ae8429780c85393c82b8f83fc23a1ebebb41849392bfe30bf
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309
|
||||
F ext/wasm/api/sqlite3-wasm.c d33a16495ca871781e78812d3a18fed78b797468fffee657b8d7199b277ff359
|
||||
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 +630,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 +640,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 +666,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
|
||||
@@ -682,35 +686,35 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
|
||||
F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc
|
||||
F src/alter.c bb663fddf1fe0e2e6d8758b2b7fb6374e7c057a6ca3955f37a48986806029765
|
||||
F src/analyze.c a3df28274e2565ba5656577d7e3fd262169a213e6eb0bd47890e0f0729a4031c
|
||||
F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39
|
||||
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 71b80e77b255144db47180fda8138740608e382a44231942464029b1a45fc036
|
||||
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c fff536730a6d83120ae38d960f812b548394e8af6907249effb1764d69178106
|
||||
F src/build.c 237ccc0290d131d646be722f418e92ee0a38043aee25e7dfdc75f8ce5b3abe4e
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
|
||||
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
|
||||
F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
||||
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
||||
F src/expr.c 94f48513fbec07725501298dee3f16d95b1762bb4a12296455f544b2d7f2d74a
|
||||
F src/expr.c f7bad20d2f74005f1f876e7fbb627222ea28250e44b296b047403720c5c21818
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
||||
F src/func.c 283d4f3b2751a1d9339fd93a8a013d1948fd5f4474a3cab0955eb4fafd445d0f
|
||||
F src/func.c f1f57c6863c1380f31ecf3d61732495bfff847a8e35a832c7e306e310db5a799
|
||||
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 06ce505713e86172612f9e01febefd2d3331d1f70461b4ada0eae5a76bb6349f
|
||||
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
|
||||
F src/insert.c 8ff11e9e54c5fc1fe89707b3d41cf44ad2822f712bd3b5da68338ea42518847e
|
||||
F src/json.c bf1b51e32158b3d01d96a878d3dba8d2e633a7e5bf2534d4617f89de8a6b9a91
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 8a59d297ec77e6b78550433bfccb95a1b26f2fb69aaaf233206e21579a1cfcc1
|
||||
@@ -734,28 +738,28 @@ 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 8d7533b3b4d0d2d6ddd34d1ebc92f50a91f04e722a3a9295a000bc3c25128e2f
|
||||
F src/os_unix.c 6227cbc4ac93046f121436886cf3712da6f4e2082af6314f976eeae1d86b794a
|
||||
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 1a526e56da1d8255196bd59d4ca3e26d912d3dc26d18663ade25dd328945062e
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||
F src/pragma.c e8221d6310c9923c80f6fa6d09b7ea7c5263a671f53db8d0894df23efcdb617b
|
||||
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 eb1860b134fb044fd819c4347105c148d5aac7c6498032be2829e5cc95619b28
|
||||
F src/resolve.c 4f4c99b8714fa04844a0f1f96ee69eefc8928e300af9247a46cfe80f78f8997c
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ced6678ead94c08d58cdb65cdda00a4871a3048e7834146f2a58ce71171808f8
|
||||
F src/shell.c.in 0354ca51eee5fbf6af394a7ef9f5ef6823ef45b743db65431f6777e4d5be2199
|
||||
F src/sqlite.h.in 41c5febd217b1e475aae022895c60f57fbe39ff6136450110662cfad67002d43
|
||||
F src/select.c 1a841c38974d45cf15a7611398479182b61ad4c187423c380741d8b1688fe607
|
||||
F src/shell.c.in ebb698028ec031e0b1595865500097d2005f977be0efd14bd8b0ddf634d5ed8d
|
||||
F src/sqlite.h.in c71d9ef76a6d32dc7ff2d373f2e57ce09056af26c1457bcadae5358b7628c7c3
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h f8928f0397d797046396dd9d360a6af8ce6dcb48bd72ea290165b07c8c518744
|
||||
F src/sqliteInt.h 9d022fc8dc3fccd69e518c115101ab4c3d4cb45a79549c1a4c26fec492eb2cfb
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -771,7 +775,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 f6af1e41cb7901edafb065a8198e4a0192dd42432b642d038965be5e628dec12
|
||||
F src/test_bestindex.c 770429c434221afe6216ec81fe4c00ad3bbdad1d5e64576aa613ffb7c5a984f0
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 5fa77ee6064ba546e144c4fea870c5ede2c54314616f81485c6a9c4192100c75
|
||||
@@ -813,32 +817,32 @@ 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/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
|
||||
F src/treeview.c 38eefdc85d2793c4059ae651a611b30eb034389fb428f69e572bbea565da6c78
|
||||
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/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vdbe.c da8407be6055f5751bf85681542d130a320b4fd1f4d8719bf83a464743d9aae4
|
||||
F src/vdbe.c 3b1793c5d2235ae89b01ef051a33d7d2ad3704c71799653b112686735ad401ff
|
||||
F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
|
||||
F src/vdbeaux.c 6385727adf51a649e4993098870a62c3945fe21dbc0e0fd9013772aff930b8fb
|
||||
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
|
||||
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 38fcf63832f7e606755fa47b028c2eb6d6cd5facb40e280d66fbda4ed9a52188
|
||||
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 5e9a5d642cceb666152c59091a3dbb645a9dda209b4e65a2f9215ee9298d26cf
|
||||
F src/where.c 839956666ce9f6b5d4951fc1f27e976951aac66920c82f9cdc5036b61b54ef7b
|
||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||
F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435
|
||||
F src/wherecode.c f5255f49d1f42b6e7e6b0362ff3522fa88cbcaa7213e52f9374744027ecdebca
|
||||
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
|
||||
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
@@ -866,8 +870,8 @@ 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/altertab3.test e167ce3b8e243b52306c1e40b13eb868f402a969513c063998593862cc643b44
|
||||
F test/altertab2.test fff90e3f01e8eb0e09282f538b8ec7cfeb035dbedbe570fe1983440f4613ad0e
|
||||
F test/altertab3.test b331ae34e69594e19605e3297805202d6156fcc8f75379dfd972a2e51cae8721
|
||||
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
|
||||
@@ -931,10 +935,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 9e6f184be080fd9c4605a7e5c7097eed1a259372f9af78151c37b072a9086f86
|
||||
F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@@ -964,7 +969,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
|
||||
@@ -1019,7 +1024,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
|
||||
@@ -1057,7 +1062,7 @@ F test/dbpagefault.test 35f06cfb2ef100a9b19d25754e8141b9cba9b7daabd4c60fa5af93fc
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
|
||||
F test/decimal.test ef731887b43ee32ef86e1c8fddb61a40789f988332c029c601dcf2c319277e9e
|
||||
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
|
||||
F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277
|
||||
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
@@ -1111,6 +1116,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 +1206,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 +1237,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
|
||||
@@ -1246,7 +1252,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c e6a40f53ac5624aa5b7c4f31c385f09ba088d524cecc4512fd3057caeed8f530
|
||||
F test/fuzzcheck.c dc159967609d00b0cfe619e735cbbf8482570aca85711397034b0662b6c18fc7
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1258,7 +1264,7 @@ F test/fuzzdata8.db 4a53b6d077c6a5c23b609d8d3ac66996fa55ba3f8d02f9b6efdd0214a767
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
|
||||
F test/fuzzinvariants.c 4355043e98cd8555c62462fcbba91c17c6492b0b017bbbe68656d5f2208f6444
|
||||
F test/fuzzinvariants.c 0729b9d8ed77ad0f8c5c7601168a707d5803087d2da030ede9057c51c809cc6c
|
||||
F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d
|
||||
F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
@@ -1267,15 +1273,16 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 18cae9140fa7f9a6f346e892a3fe3e31b2ca0be1494cd01b918adb74281016a6
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
|
||||
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
|
||||
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
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 +1305,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
|
||||
@@ -1338,7 +1345,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
|
||||
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test d5054173442fdf98260eeb6bb9751daa733b0ae6842fe50dcbd5469945b86985
|
||||
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
|
||||
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
|
||||
@@ -1351,7 +1358,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 +1372,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
|
||||
@@ -1433,14 +1440,14 @@ F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db
|
||||
F test/misc5.test 027cf0ac10314ea534173f335a33bb4059907ddabbac2c16786766d6f26c8923
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
|
||||
F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
|
||||
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
|
||||
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
|
||||
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 +1505,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 9559cf5173864bf47c0431873d158fbeb72f920a59905b1f46069d8543eccdab
|
||||
F test/pragma4.test f93f317693e90ece4ed0f5505d9035cae03f9fc684b718278433f2e48703f693
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
@@ -1510,7 +1517,7 @@ F test/printf.test 685fec5a0c5af2490ab0632775a301554361d674211d690f5bee0a97b0533
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 1495a09837a1cedfc0adf07ba42dc6b83be05a2c15de331b67c39a0e22078238
|
||||
F test/pushdown.test 3330746a897ea271b1021bc1e7e57c6f8d49bcb8ca7d58a823d01aa64a303cc7
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quickcheck.test a4b7e878cd97e46108291c409b0bf8214f29e18fddd68a42bc5c1375ad1fb80a
|
||||
@@ -1522,13 +1529,14 @@ F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/readonly.test c1985f0b4ab55041f2ba629dadc6578a3ff0f0e5b0ec7912e85c51f49c3e82fe
|
||||
F test/recover.test 6463509a7404e0c35431dd9b4a1c3b4a29d7a6af8a08462b31670c8a5a616d3a
|
||||
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
|
||||
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
|
||||
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
|
||||
@@ -1536,7 +1544,7 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190cfd4
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test aaa2572271edf58f8f88ac4d39f69e57ee5ae7a858332cdce9106e7cff8b7963
|
||||
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
|
||||
F test/rowvalue.test baf4fa3ec1a8c1c920c3faa5fd25959cb454bbd99ac8960397c34549d9fc4abe
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 1347e25ca11c547c5a6ff0cc5626f95aa9740e9275bfaec096029f57cb2130ce
|
||||
@@ -1559,7 +1567,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
|
||||
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
|
||||
F test/scanstatus.test b249328caf4d317e71058006872b8012598a5fa045b30bf24a81eeff650ab49e
|
||||
F test/scanstatus2.test 317670daf7f3eef48a9598cb7800ba8eccab51949cf52bca3f7da3b83a0c1c8c
|
||||
F test/scanstatus2.test 688adc0c3ab1ffadead218cbce6446b10aa892004a8ea5e3640d59257fb836f2
|
||||
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
|
||||
@@ -1576,7 +1584,7 @@ F test/select3.test 180223af31e1ca5537dd395ef9708ae18e651a233777fd366fd0d75469fc
|
||||
F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
|
||||
F test/select5.test 8afc5e5dcdebc2be54472e73ebd9cd1adef1225fd15d37a1c62f969159f390ae
|
||||
F test/select6.test 9b2fb4ffedf52e1b5703cfcae1212e7a4a063f014c0458d78d29aca3db766d1f
|
||||
F test/select7.test f659f231489349e8c5734e610803d7654207318f
|
||||
F test/select7.test b825420da8a0b5722fdb77f3369f6396a3d198c46e8787eb26ff9425d4ac9d27
|
||||
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||
F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812
|
||||
F test/selectA.test 1da8ce3884c326e11d2855baffb76436b0d7e044404af8a2a70d1399a4ff7e29
|
||||
@@ -1589,7 +1597,7 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
|
||||
F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b7871aac
|
||||
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
||||
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
|
||||
F test/sessionfuzz.c 666b47e177c7b25f01ba645d41fb9131d2d54ae673f0d81c08f5af2b3e6ecbda
|
||||
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
|
||||
F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
|
||||
@@ -1606,10 +1614,10 @@ F test/shell1.test 17a5ca9c6f24f807b2f505b4b38fcbce143d96cd8664c06c34bbbe0672bf7
|
||||
F test/shell2.test 56da24128304c9ab67da2964cc80beff7b35761c446ec6e6e98bff2775b15026
|
||||
F test/shell3.test 5ad4b2813717956414f2c0c8a2027895cd98ccf7dd54dbacbde4d4f5591ce5a1
|
||||
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
|
||||
@@ -1660,7 +1668,7 @@ F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b3594
|
||||
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
|
||||
@@ -1676,7 +1684,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
|
||||
@@ -1689,8 +1697,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf
|
||||
F test/testrunner.tcl 01bc3b5bc900dc73b076180727eb2869dc61426b1ab95ac2f42def5d1f3d407e
|
||||
F test/testrunner_data.tcl 7032a64e4757db0bf83c6874cab2ccbb14a8708b4d68c1ddc8b359e204139cb7
|
||||
F test/testrunner.tcl 1386667c04207d0a540ce1a9bc5ee0b734f7a3ba856c14a03943fb4f32de55bb
|
||||
F test/testrunner_data.tcl 3d36660cfd55ea5e20e661e8f94c0520feebcb437848f9b98b33c483cc479c0c
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1905,7 +1913,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
|
||||
@@ -1915,7 +1923,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
|
||||
@@ -1923,11 +1931,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 e7c156f92d32ed645908fbad0a1144f0f31650376cdcb212fde701978c89d3b1
|
||||
F test/values.test 52102ad9e5068b449429e40a976486a52246041f7cd79d086a2b170e77dec925
|
||||
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
|
||||
@@ -1950,6 +1958,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 c7b7f537978005d063fa2f53a3cd5a46ecf651ecd19970cb9ed4203698398deb
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
@@ -2015,6 +2024,7 @@ F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08a
|
||||
F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
|
||||
F test/whereL.test 438a397fa883b77bb6361c08a8befa41b52e9cfbe15a2a43715d122f8cfa8649
|
||||
F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250
|
||||
F test/whereN.test 63a3584b71acfb6963416de82f26c6b1644abc5ca6080c76546b9246734c8803
|
||||
F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
|
||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||
F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
|
||||
@@ -2024,7 +2034,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
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
|
||||
@@ -2101,7 +2111,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl a16682eae5f01f85e5861b2aa215ca0d46b4230658ee25977e02b4508566fb75 x
|
||||
F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
|
||||
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
|
||||
F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
@@ -2181,11 +2191,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P b6802565df0f63286a7ef26c92d3ed817895f244920a24909cd855090fdfa08c
|
||||
R 8123b01b9bcdf105a2e2ddc317d657f0
|
||||
T *branch * eqp-orderby
|
||||
T *sym-eqp-orderby *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z b979ee1c2ca7e0d90b1c38ab5826e1ad
|
||||
P fc956353d3762d0e655b88f9d0c1a3840b40453a22e97160ccdf60485be56a92
|
||||
R 47b9d94ac84047bf00fd35221bcbfde9
|
||||
T +sym-release *
|
||||
T +sym-version-3.46.1 *
|
||||
U drh
|
||||
Z 519cc14a63561bb4dfa17935ffe00a32
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
cd547c500442f3f58c05d6da8a67c3238560c5204ea62ec14afa844cc8fb94f0
|
||||
c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33
|
||||
|
||||
+6
-1
@@ -1320,7 +1320,7 @@ static int renameResolveTrigger(Parse *pParse){
|
||||
/* ALWAYS() because if the table of the trigger does not exist, the
|
||||
** error would have been hit before this point */
|
||||
if( ALWAYS(pParse->pTriggerTab) ){
|
||||
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
|
||||
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab)!=0;
|
||||
}
|
||||
|
||||
/* Resolve symbols in WHEN clause */
|
||||
@@ -2262,7 +2262,12 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
|
||||
if( i==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
|
||||
}else{
|
||||
char aff = pTab->aCol[i].affinity;
|
||||
if( aff==SQLITE_AFF_REAL ){
|
||||
pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
|
||||
}
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
|
||||
pTab->aCol[i].affinity = aff;
|
||||
}
|
||||
nField++;
|
||||
}
|
||||
|
||||
+27
-14
@@ -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;
|
||||
}
|
||||
@@ -9521,7 +9534,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 +9564,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()
|
||||
|
||||
+10
-12
@@ -2828,20 +2828,20 @@ void sqlite3EndTable(
|
||||
int regRowid; /* Rowid of the next row to insert */
|
||||
int addrInsLoop; /* Top of the loop for inserting rows */
|
||||
Table *pSelTab; /* A table that describes the SELECT results */
|
||||
int iCsr; /* Write cursor on the new table */
|
||||
|
||||
if( IN_SPECIAL_PARSE ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
iCsr = pParse->nTab++;
|
||||
regYield = ++pParse->nMem;
|
||||
regRec = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
assert(pParse->nTab==1);
|
||||
sqlite3MayAbort(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
|
||||
pParse->nTab = 2;
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
if( pParse->nErr ) return;
|
||||
@@ -2862,11 +2862,11 @@ void sqlite3EndTable(
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
|
||||
sqlite3TableAffinity(v, p, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid);
|
||||
sqlite3VdbeGoto(v, addrInsLoop);
|
||||
sqlite3VdbeJumpHere(v, addrInsLoop);
|
||||
sqlite3VdbeAddOp1(v, OP_Close, 1);
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
|
||||
}
|
||||
|
||||
/* Compute the complete text of the CREATE statement */
|
||||
@@ -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 );
|
||||
|
||||
@@ -65,6 +65,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
||||
# endif
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
"ALLOW_ROWID_IN_VIEW",
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
||||
"ALLOW_URI_AUTHORITY",
|
||||
#endif
|
||||
|
||||
+79
-25
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2474,9 +2487,11 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
case TK_IF_NULL_ROW:
|
||||
case TK_REGISTER:
|
||||
case TK_DOT:
|
||||
case TK_RAISE:
|
||||
testcase( pExpr->op==TK_REGISTER );
|
||||
testcase( pExpr->op==TK_IF_NULL_ROW );
|
||||
testcase( pExpr->op==TK_DOT );
|
||||
testcase( pExpr->op==TK_RAISE );
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
case TK_VARIABLE:
|
||||
@@ -2498,7 +2513,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
|
||||
static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
|
||||
Walker w;
|
||||
w.eCode = initFlag;
|
||||
w.pParse = pParse;
|
||||
@@ -2507,7 +2522,6 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
}
|
||||
@@ -2527,7 +2541,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
|
||||
** function and on its parameters.
|
||||
*/
|
||||
int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
|
||||
return exprIsConst(pParse, p, 1, 0);
|
||||
return exprIsConst(pParse, p, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2544,7 +2558,23 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
|
||||
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
|
||||
*/
|
||||
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
|
||||
return exprIsConst(pParse, p, 2, 0);
|
||||
return exprIsConst(pParse, p, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine examines sub-SELECT statements as an expression is being
|
||||
** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
|
||||
** constant as long as they are uncorrelated - meaning that they do not
|
||||
** contain any terms from outer contexts.
|
||||
*/
|
||||
static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
|
||||
assert( pSelect!=0 );
|
||||
assert( pWalker->eCode==3 || pWalker->eCode==0 );
|
||||
if( (pSelect->selFlags & SF_Correlated)!=0 ){
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2552,9 +2582,26 @@ static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
|
||||
** for any single row of the table with cursor iCur. In other words, the
|
||||
** expression must not refer to any non-deterministic function nor any
|
||||
** table other than iCur.
|
||||
**
|
||||
** Consider uncorrelated subqueries to be constants if the bAllowSubq
|
||||
** parameter is true.
|
||||
*/
|
||||
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
return exprIsConst(0, p, 3, iCur);
|
||||
static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
|
||||
Walker w;
|
||||
w.eCode = 3;
|
||||
w.pParse = 0;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
if( bAllowSubq ){
|
||||
w.xSelectCallback = exprSelectWalkTableConstant;
|
||||
}else{
|
||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
}
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2572,7 +2619,10 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
**
|
||||
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
|
||||
**
|
||||
** (2) pExpr cannot use subqueries or non-deterministic functions.
|
||||
** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
|
||||
** true and the subquery is non-correlated
|
||||
**
|
||||
** (2b) pExpr cannot use non-deterministic functions.
|
||||
**
|
||||
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
|
||||
** (Is there some way to relax this constraint?)
|
||||
@@ -2601,7 +2651,8 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
int sqlite3ExprIsSingleTableConstraint(
|
||||
Expr *pExpr, /* The constraint */
|
||||
const SrcList *pSrcList, /* Complete FROM clause */
|
||||
int iSrc /* Which element of pSrcList to use */
|
||||
int iSrc, /* Which element of pSrcList to use */
|
||||
int bAllowSubq /* Allow non-correlated subqueries */
|
||||
){
|
||||
const SrcItem *pSrc = &pSrcList->a[iSrc];
|
||||
if( pSrc->fg.jointype & JT_LTORJ ){
|
||||
@@ -2626,7 +2677,8 @@ int sqlite3ExprIsSingleTableConstraint(
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
|
||||
/* Rules (1), (2a), and (2b) handled by the following: */
|
||||
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
|
||||
}
|
||||
|
||||
|
||||
@@ -2711,7 +2763,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
|
||||
*/
|
||||
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||
assert( isInit==0 || isInit==1 );
|
||||
return exprIsConst(0, p, 4+isInit, 0);
|
||||
return exprIsConst(0, p, 4+isInit);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
@@ -2801,9 +2853,12 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
||||
return 0;
|
||||
case TK_COLUMN:
|
||||
assert( ExprUseYTab(p) );
|
||||
return ExprHasProperty(p, EP_CanBeNull) ||
|
||||
NEVER(p->y.pTab==0) || /* Reference to column of index on expr */
|
||||
(p->iColumn>=0
|
||||
return ExprHasProperty(p, EP_CanBeNull)
|
||||
|| NEVER(p->y.pTab==0) /* Reference to column of index on expr */
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
|| (p->iColumn==XN_ROWID && IsView(p->y.pTab))
|
||||
#endif
|
||||
|| (p->iColumn>=0
|
||||
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
|
||||
&& ALWAYS(p->iColumn<p->y.pTab->nCol)
|
||||
&& p->y.pTab->aCol[p->iColumn].notNull==0);
|
||||
@@ -5026,8 +5081,9 @@ expr_code_doover:
|
||||
if( !ExprHasProperty(pExpr, EP_Collate) ){
|
||||
/* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
|
||||
** "SOFT-COLLATE" that is added to constraints that are pushed down
|
||||
** from outer queries into sub-queries by the push-down optimization.
|
||||
** Clear subtypes as subtypes may not cross a subquery boundary.
|
||||
** from outer queries into sub-queries by the WHERE-clause push-down
|
||||
** optimization. Clear subtypes as subtypes may not cross a subquery
|
||||
** boundary.
|
||||
*/
|
||||
assert( pExpr->pLeft );
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft, target);
|
||||
@@ -6625,9 +6681,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{
|
||||
@@ -6636,9 +6691,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
+9
-3
@@ -610,8 +610,10 @@ static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
|
||||
int ii;
|
||||
if( exprListIsConstant(pParse,pRow)==0 ) return 0;
|
||||
for(ii=0; ii<pRow->nExpr; ii++){
|
||||
assert( pRow->a[ii].pExpr->affExpr==0 );
|
||||
if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0;
|
||||
Expr *pExpr = pRow->a[ii].pExpr;
|
||||
assert( pExpr->op!=TK_RAISE );
|
||||
assert( pExpr->affExpr==0 );
|
||||
if( 0!=sqlite3ExprAffinity(pExpr) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -715,6 +717,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
|
||||
pRet->pSrc->nSrc = 1;
|
||||
pRet->pPrior = pLeft->pPrior;
|
||||
pRet->op = pLeft->op;
|
||||
if( pRet->pPrior ) pRet->selFlags |= SF_Values;
|
||||
pLeft->pPrior = 0;
|
||||
pLeft->op = TK_SELECT;
|
||||
assert( pLeft->pNext==0 );
|
||||
@@ -3180,7 +3183,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
|
||||
|
||||
+1
-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;
|
||||
@@ -3866,7 +3859,7 @@ static void jsonExtractFunc(
|
||||
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
|
||||
*/
|
||||
jsonStringInit(&jx, ctx);
|
||||
if( jsonAllDigits(zPath, nPath) ){
|
||||
if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
|
||||
jsonAppendRawNZ(&jx, "[", 1);
|
||||
jsonAppendRaw(&jx, zPath, nPath);
|
||||
jsonAppendRawNZ(&jx, "]", 2);
|
||||
|
||||
+8
-1
@@ -6398,12 +6398,19 @@ static int unixOpen(
|
||||
rc = SQLITE_READONLY_DIRECTORY;
|
||||
}else if( errno!=EISDIR && isReadWrite ){
|
||||
/* Failed to open the file for read/write access. Try read-only. */
|
||||
UnixUnusedFd *pReadonly = 0;
|
||||
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
||||
openFlags &= ~(O_RDWR|O_CREAT);
|
||||
flags |= SQLITE_OPEN_READONLY;
|
||||
openFlags |= O_RDONLY;
|
||||
isReadonly = 1;
|
||||
fd = robust_open(zName, openFlags, openMode);
|
||||
pReadonly = findReusableFd(zName, flags);
|
||||
if( pReadonly ){
|
||||
fd = pReadonly->fd;
|
||||
sqlite3_free(pReadonly);
|
||||
}else{
|
||||
fd = robust_open(zName, openFlags, openMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( fd<0 ){
|
||||
|
||||
+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;
|
||||
|
||||
+15
-6
@@ -530,9 +530,9 @@ cmd ::= select(X). {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( (p->selFlags & SF_MultiValue)==0 &&
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
|
||||
cnt>mxSelect
|
||||
if( (p->selFlags & (SF_MultiValue|SF_Values))==0
|
||||
&& (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
|
||||
&& cnt>mxSelect
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||
}
|
||||
@@ -1282,8 +1282,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). {
|
||||
@@ -1929,8 +1938,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 */
|
||||
|
||||
+9
-7
@@ -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;
|
||||
}
|
||||
@@ -2870,9 +2870,9 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
seen[0] = 0;
|
||||
seen[1] = 0;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
if( pConstraint->iColumn < pTab->iHidden ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT;
|
||||
j = pConstraint->iColumn - pTab->iHidden;
|
||||
assert( j < 2 );
|
||||
seen[j] = i+1;
|
||||
@@ -2885,12 +2885,13 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
j = seen[0]-1;
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[j].omit = 1;
|
||||
if( seen[1]==0 ) return SQLITE_OK;
|
||||
pIdxInfo->estimatedCost = (double)20;
|
||||
pIdxInfo->estimatedRows = 20;
|
||||
j = seen[1]-1;
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[j].omit = 1;
|
||||
if( seen[1] ){
|
||||
j = seen[1]-1;
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[j].omit = 1;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -2910,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 ){
|
||||
|
||||
+27
-13
@@ -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;
|
||||
@@ -632,6 +633,11 @@ static int lookupName(
|
||||
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
|
||||
){
|
||||
cnt = cntTab;
|
||||
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
|
||||
if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
|
||||
eNewExprOp = TK_NULL;
|
||||
}
|
||||
#endif
|
||||
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
|
||||
pExpr->affExpr = SQLITE_AFF_INTEGER;
|
||||
}
|
||||
@@ -822,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;
|
||||
@@ -1275,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 ){
|
||||
@@ -1349,6 +1357,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pNC->ncFlags & NC_PartIdx );
|
||||
testcase( pNC->ncFlags & NC_IdxExpr );
|
||||
testcase( pNC->ncFlags & NC_GenCol );
|
||||
assert( pExpr->x.pSelect );
|
||||
if( pNC->ncFlags & NC_SelfRef ){
|
||||
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
|
||||
}else{
|
||||
@@ -1357,6 +1366,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
assert( pNC->nRef>=nRef );
|
||||
if( nRef!=pNC->nRef ){
|
||||
ExprSetProperty(pExpr, EP_VarSelect);
|
||||
pExpr->x.pSelect->selFlags |= SF_Correlated;
|
||||
}
|
||||
pNC->ncFlags |= NC_Subquery;
|
||||
}
|
||||
@@ -1882,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;
|
||||
@@ -2143,6 +2154,9 @@ int sqlite3ResolveExprNames(
|
||||
** Resolve all names for all expression in an expression list. This is
|
||||
** just like sqlite3ResolveExprNames() except that it works for an expression
|
||||
** list rather than a single expression.
|
||||
**
|
||||
** The return value is SQLITE_OK (0) for success or SQLITE_ERROR (1) for a
|
||||
** failure.
|
||||
*/
|
||||
int sqlite3ResolveExprListNames(
|
||||
NameContext *pNC, /* Namespace to resolve expressions in. */
|
||||
@@ -2151,7 +2165,7 @@ int sqlite3ResolveExprListNames(
|
||||
int i;
|
||||
int savedHasAgg = 0;
|
||||
Walker w;
|
||||
if( pList==0 ) return WRC_Continue;
|
||||
if( pList==0 ) return SQLITE_OK;
|
||||
w.pParse = pNC->pParse;
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
@@ -2165,7 +2179,7 @@ int sqlite3ResolveExprListNames(
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
w.pParse->nHeight += pExpr->nHeight;
|
||||
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
|
||||
return WRC_Abort;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
sqlite3WalkExprNN(&w, pExpr);
|
||||
@@ -2182,10 +2196,10 @@ int sqlite3ResolveExprListNames(
|
||||
(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
|
||||
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
|
||||
}
|
||||
if( w.pParse->nErr>0 ) return WRC_Abort;
|
||||
if( w.pParse->nErr>0 ) return SQLITE_ERROR;
|
||||
}
|
||||
pNC->ncFlags |= savedHasAgg;
|
||||
return WRC_Continue;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+49
-17
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -5060,6 +5064,18 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
|
||||
** The hope is that the terms added to the inner query will make it more
|
||||
** efficient.
|
||||
**
|
||||
** NAME AMBIGUITY
|
||||
**
|
||||
** This optimization is called the "WHERE-clause push-down optimization".
|
||||
**
|
||||
** Do not confuse this optimization with another unrelated optimization
|
||||
** with a similar name: The "MySQL push-down optimization" causes WHERE
|
||||
** clause terms that can be evaluated using only the index and without
|
||||
** reference to the table are run first, so that if they are false,
|
||||
** unnecessary table seeks are avoided.
|
||||
**
|
||||
** RULES
|
||||
**
|
||||
** Do not attempt this optimization if:
|
||||
**
|
||||
** (1) (** This restriction was removed on 2017-09-29. We used to
|
||||
@@ -5125,15 +5141,19 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
|
||||
** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
|
||||
** clause and the subquery.
|
||||
**
|
||||
** Without this restriction, the push-down optimization might move
|
||||
** the ON/USING filter expression from the left side of a RIGHT JOIN
|
||||
** over to the right side, which leads to incorrect answers. See
|
||||
** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
|
||||
** Without this restriction, the WHERE-clause push-down optimization
|
||||
** might move the ON/USING filter expression from the left side of a
|
||||
** RIGHT JOIN over to the right side, which leads to incorrect answers.
|
||||
** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
|
||||
**
|
||||
** (10) The inner query is not the right-hand table of a RIGHT JOIN.
|
||||
**
|
||||
** (11) The subquery is not a VALUES clause
|
||||
**
|
||||
** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This
|
||||
** case only comes up if SQLite is compiled using
|
||||
** SQLITE_ALLOW_ROWID_IN_VIEW.
|
||||
**
|
||||
** Return 0 if no changes are made and non-zero if one or more WHERE clause
|
||||
** terms are duplicated into the subquery.
|
||||
*/
|
||||
@@ -5244,7 +5264,19 @@ static int pushDownWhereTerms(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){
|
||||
Expr *pLeft = pWhere->pLeft;
|
||||
if( ALWAYS(pLeft)
|
||||
&& pLeft->op==TK_COLUMN
|
||||
&& pLeft->iColumn < 0
|
||||
){
|
||||
return 0; /* Restriction (12) */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
|
||||
nChng++;
|
||||
pSubq->selFlags |= SF_PushDown;
|
||||
while( pSubq ){
|
||||
@@ -5871,6 +5903,7 @@ int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
|
||||
while( pSel->pPrior ){ pSel = pSel->pPrior; }
|
||||
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
|
||||
pTab->iPKey = -1;
|
||||
pTab->eTabType = TABTYP_VIEW;
|
||||
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
/* The usual case - do not allow ROWID on a subquery */
|
||||
@@ -6378,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;
|
||||
@@ -7672,7 +7704,7 @@ int sqlite3Select(
|
||||
#endif
|
||||
assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
|
||||
}else{
|
||||
TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
|
||||
TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
|
||||
}
|
||||
|
||||
/* Convert unused result columns of the subquery into simple NULL
|
||||
|
||||
+33
-9
@@ -7940,7 +7940,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 +7952,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 +7963,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;
|
||||
}
|
||||
|
||||
@@ -8970,7 +8977,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 +8995,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 +9018,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);
|
||||
}
|
||||
@@ -11121,17 +11133,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 +11160,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 +11187,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;
|
||||
|
||||
+43
-16
@@ -3305,8 +3305,8 @@ int sqlite3_set_authorizer(
|
||||
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** METHOD: sqlite3
|
||||
** CAPI3REF: Deprecated Tracing And Profiling Functions
|
||||
** DEPRECATED
|
||||
**
|
||||
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
|
||||
** instead of the routines described here.
|
||||
@@ -6887,6 +6887,12 @@ int sqlite3_autovacuum_pages(
|
||||
** The exceptions defined in this paragraph might change in a future
|
||||
** release of SQLite.
|
||||
**
|
||||
** Whether the update hook is invoked before or after the
|
||||
** corresponding change is currently unspecified and may differ
|
||||
** depending on the type of change. Do not rely on the order of the
|
||||
** hook call with regards to the final result of the operation which
|
||||
** triggers the hook.
|
||||
**
|
||||
** The update hook implementation must not do anything that will modify
|
||||
** the database connection that invoked the update hook. Any actions
|
||||
** to modify the database connection must be deferred until after the
|
||||
@@ -8357,7 +8363,7 @@ int sqlite3_test_control(int op, ...);
|
||||
** The sqlite3_keyword_count() interface returns the number of distinct
|
||||
** keywords understood by SQLite.
|
||||
**
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
|
||||
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
||||
** of bytes in the keyword into *L. The string that *Z points to is not
|
||||
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
||||
@@ -9936,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"
|
||||
|
||||
+10
-7
@@ -1156,7 +1156,7 @@ extern u32 sqlite3WhereTrace;
|
||||
** 0x00000010 Display sqlite3_index_info xBestIndex calls
|
||||
** 0x00000020 Range an equality scan metrics
|
||||
** 0x00000040 IN operator decisions
|
||||
** 0x00000080 WhereLoop cost adjustements
|
||||
** 0x00000080 WhereLoop cost adjustments
|
||||
** 0x00000100
|
||||
** 0x00000200 Covering index decisions
|
||||
** 0x00000400 OR optimization
|
||||
@@ -1906,7 +1906,7 @@ struct sqlite3 {
|
||||
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
|
||||
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
|
||||
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
|
||||
#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
|
||||
#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
|
||||
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
|
||||
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
|
||||
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
|
||||
@@ -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 */
|
||||
|
||||
@@ -3580,11 +3581,12 @@ struct Select {
|
||||
#define SF_View 0x0200000 /* SELECT statement is a view */
|
||||
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
|
||||
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
|
||||
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
|
||||
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
|
||||
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
|
||||
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
|
||||
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
|
||||
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
|
||||
#define SF_Correlated 0x20000000 /* True if references the outer context */
|
||||
|
||||
/* True if S exists and has SF_NestedFrom */
|
||||
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
|
||||
@@ -4855,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*);
|
||||
@@ -5081,8 +5083,7 @@ int sqlite3ExprTruthValue(const Expr*);
|
||||
int sqlite3ExprIsConstant(Parse*,Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
int sqlite3ExprContainsSubquery(Expr*);
|
||||
#endif
|
||||
@@ -5267,7 +5268,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 **);
|
||||
|
||||
|
||||
@@ -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 ){
|
||||
@@ -226,7 +229,7 @@ static int tclConnect(
|
||||
}
|
||||
|
||||
sqlite3_free(zCmd);
|
||||
*ppVtab = &pTab->base;
|
||||
*ppVtab = pTab ? &pTab->base : 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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++){
|
||||
|
||||
@@ -921,6 +921,9 @@ void sqlite3Update(
|
||||
}
|
||||
}
|
||||
if( chngRowid==0 && pPk==0 ){
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
|
||||
#endif
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-6
@@ -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;
|
||||
}
|
||||
|
||||
@@ -4582,7 +4584,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;
|
||||
@@ -6192,7 +6195,8 @@ case OP_Last: { /* jump0, ncycle */
|
||||
**
|
||||
** Let N be the approximate number of rows in the table or index
|
||||
** with cursor P1 and let X be 10*log2(N) if N is positive or -1
|
||||
** if N is zero. Thus X will be within the range of -1 to 640, inclusive
|
||||
** if N is zero.
|
||||
**
|
||||
** Jump to P2 if X is in between P3 and P4, inclusive.
|
||||
*/
|
||||
case OP_IfSizeBetween: { /* jump */
|
||||
@@ -6203,8 +6207,8 @@ case OP_IfSizeBetween: { /* jump */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
assert( pOp->p3>=-1 && pOp->p3<=640 );
|
||||
assert( pOp->p4.i>=-1 && pOp->p4.i<=640 );
|
||||
assert( pOp->p3>=-1 && pOp->p3<=640*2 );
|
||||
assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
pCrsr = pC->uc.pCursor;
|
||||
|
||||
+2
-1
@@ -2404,7 +2404,6 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
}
|
||||
if( flags & SQLITE_SCANSTAT_COMPLEX ){
|
||||
idx = iScan;
|
||||
pScan = &p->aScan[idx];
|
||||
}else{
|
||||
/* If the COMPLEX flag is clear, then this function must ignore any
|
||||
** ScanStatus structures with ScanStatus.addrLoop set to 0. */
|
||||
@@ -2417,6 +2416,8 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
}
|
||||
}
|
||||
if( idx>=p->nScan ) return 1;
|
||||
assert( pScan==0 || pScan==&p->aScan[idx] );
|
||||
pScan = &p->aScan[idx];
|
||||
|
||||
switch( iScanStatusOp ){
|
||||
case SQLITE_SCANSTAT_NLOOP: {
|
||||
|
||||
+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 */
|
||||
|
||||
+23
-5
@@ -813,12 +813,30 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
Table *pTab;
|
||||
Parse sParse;
|
||||
int initBusy;
|
||||
int i;
|
||||
const unsigned char *z;
|
||||
static const u8 aKeyword[] = { TK_CREATE, TK_TABLE, 0 };
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Verify that the first two keywords in the CREATE TABLE statement
|
||||
** really are "CREATE" and "TABLE". If this is not the case, then
|
||||
** sqlite3_declare_vtab() is being misused.
|
||||
*/
|
||||
z = (const unsigned char*)zCreateTable;
|
||||
for(i=0; aKeyword[i]; i++){
|
||||
int tokenType = 0;
|
||||
do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
|
||||
if( tokenType!=aKeyword[i] ){
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pCtx = db->pVtabCtx;
|
||||
if( !pCtx || pCtx->bDeclared ){
|
||||
@@ -826,6 +844,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
pTab = pCtx->pTab;
|
||||
assert( IsVirtual(pTab) );
|
||||
|
||||
@@ -839,11 +858,10 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
initBusy = db->init.busy;
|
||||
db->init.busy = 0;
|
||||
sParse.nQueryLoop = 1;
|
||||
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable)
|
||||
&& ALWAYS(sParse.pNewTable!=0)
|
||||
&& ALWAYS(!db->mallocFailed)
|
||||
&& IsOrdinaryTable(sParse.pNewTable)
|
||||
){
|
||||
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) ){
|
||||
assert( sParse.pNewTable!=0 );
|
||||
assert( !db->mallocFailed );
|
||||
assert( IsOrdinaryTable(sParse.pNewTable) );
|
||||
assert( sParse.zErrMsg==0 );
|
||||
if( !pTab->aCol ){
|
||||
Table *pNew = sParse.pNewTable;
|
||||
|
||||
+269
-80
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -713,9 +757,13 @@ static void translateColumnToCopy(
|
||||
** are no-ops.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
|
||||
static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
|
||||
static void whereTraceIndexInfoInputs(
|
||||
sqlite3_index_info *p, /* The IndexInfo object */
|
||||
Table *pTab /* The TABLE that is the virtual table */
|
||||
){
|
||||
int i;
|
||||
if( (sqlite3WhereTrace & 0x10)==0 ) return;
|
||||
sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
sqlite3DebugPrintf(
|
||||
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
|
||||
@@ -733,9 +781,13 @@ static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
|
||||
p->aOrderBy[i].desc);
|
||||
}
|
||||
}
|
||||
static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
|
||||
static void whereTraceIndexInfoOutputs(
|
||||
sqlite3_index_info *p, /* The IndexInfo object */
|
||||
Table *pTab /* The TABLE that is the virtual table */
|
||||
){
|
||||
int i;
|
||||
if( (sqlite3WhereTrace & 0x10)==0 ) return;
|
||||
sqlite3DebugPrintf("sqlite3_index_info outputs for %s:\n", pTab->zName);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
|
||||
i,
|
||||
@@ -749,8 +801,8 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
|
||||
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
|
||||
}
|
||||
#else
|
||||
#define whereTraceIndexInfoInputs(A)
|
||||
#define whereTraceIndexInfoOutputs(A)
|
||||
#define whereTraceIndexInfoInputs(A,B)
|
||||
#define whereTraceIndexInfoOutputs(A,B)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -934,7 +986,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
** WHERE clause (or the ON clause of a LEFT join) that constrain which
|
||||
** rows of the target table (pSrc) that can be used. */
|
||||
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
|
||||
){
|
||||
pPartial = sqlite3ExprAnd(pParse, pPartial,
|
||||
sqlite3ExprDup(pParse->db, pExpr, 0));
|
||||
@@ -976,7 +1028,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
** if they go out of sync.
|
||||
*/
|
||||
if( IsView(pTable) ){
|
||||
extraCols = ALLBITS;
|
||||
extraCols = ALLBITS & ~idxCols;
|
||||
}else{
|
||||
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
|
||||
}
|
||||
@@ -1203,7 +1255,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0)
|
||||
){
|
||||
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
|
||||
}
|
||||
@@ -1364,7 +1416,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;
|
||||
@@ -1493,11 +1545,11 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
|
||||
int rc;
|
||||
|
||||
whereTraceIndexInfoInputs(p);
|
||||
whereTraceIndexInfoInputs(p, pTab);
|
||||
pParse->db->nSchemaLock++;
|
||||
rc = pVtab->pModule->xBestIndex(pVtab, p);
|
||||
pParse->db->nSchemaLock--;
|
||||
whereTraceIndexInfoOutputs(p);
|
||||
whereTraceIndexInfoOutputs(p, pTab);
|
||||
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
@@ -3244,10 +3296,13 @@ static int whereLoopAddBtreeIndex(
|
||||
}
|
||||
}
|
||||
|
||||
/* Set rCostIdx to the cost of visiting selected rows in index. Add
|
||||
** it to pNew->rRun, which is currently set to the cost of the index
|
||||
** seek only. Then, if this is a non-covering index, add the cost of
|
||||
** visiting the rows in the main table. */
|
||||
/* Set rCostIdx to the estimated cost of visiting selected rows in the
|
||||
** index. The estimate is the sum of two values:
|
||||
** 1. The cost of doing one search-by-key to find the first matching
|
||||
** entry
|
||||
** 2. Stepping forward in the index pNew->nOut times to find all
|
||||
** additional matching entries.
|
||||
*/
|
||||
assert( pSrc->pTab->szTabRow>0 );
|
||||
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
|
||||
/* The pProbe->szIdxRow is low for an IPK table since the interior
|
||||
@@ -3258,7 +3313,15 @@ static int whereLoopAddBtreeIndex(
|
||||
}else{
|
||||
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
|
||||
}
|
||||
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
|
||||
rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
|
||||
|
||||
/* Estimate the cost of running the loop. If all data is coming
|
||||
** from the index, then this is just the cost of doing the index
|
||||
** lookup and scan. But if some data is coming out of the main table,
|
||||
** we also have to add in the cost of doing pNew->nOut searches to
|
||||
** locate the row in the main table that corresponds to the index entry.
|
||||
*/
|
||||
pNew->rRun = rCostIdx;
|
||||
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
|
||||
}
|
||||
@@ -3896,7 +3959,9 @@ static int whereLoopAddBtree(
|
||||
" according to whereIsCoveringIndex()\n", pProbe->zName));
|
||||
}
|
||||
}
|
||||
}else if( m==0 ){
|
||||
}else if( m==0
|
||||
&& (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
|
||||
){
|
||||
WHERETRACE(0x200,
|
||||
("-> %s a covering index according to bitmasks\n",
|
||||
pProbe->zName, m==0 ? "is" : "is not"));
|
||||
@@ -3994,6 +4059,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
|
||||
@@ -4134,13 +4214,20 @@ 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. */
|
||||
** 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. */
|
||||
if( pIdxInfo->needToFreeIdxStr ){
|
||||
sqlite3_free(pIdxInfo->idxStr);
|
||||
pIdxInfo->idxStr = 0;
|
||||
@@ -5511,7 +5598,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pWInfo->nRowOut = pFrom->nRow;
|
||||
|
||||
/* Free temporary memory and return success */
|
||||
@@ -5519,6 +5605,83 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine implements a heuristic designed to improve query planning.
|
||||
** This routine is called in between the first and second call to
|
||||
** wherePathSolver(). Hence the name "Interstage" "Heuristic".
|
||||
**
|
||||
** The first call to wherePathSolver() (hereafter just "solver()") computes
|
||||
** the best path without regard to the order of the outputs. The second call
|
||||
** to the solver() builds upon the first call to try to find an alternative
|
||||
** path that satisfies the ORDER BY clause.
|
||||
**
|
||||
** This routine looks at the results of the first solver() run, and for
|
||||
** every FROM clause term in the resulting query plan that uses an equality
|
||||
** constraint against an index, disable other WhereLoops for that same
|
||||
** FROM clause term that would try to do a full-table scan. This prevents
|
||||
** an index search from being converted into a full-table scan in order to
|
||||
** satisfy an ORDER BY clause, since even though we might get slightly better
|
||||
** performance using the full-scan without sorting if the output size
|
||||
** estimates are very precise, we might also get severe performance
|
||||
** degradation using the full-scan if the output size estimate is too large.
|
||||
** It is better to err on the side of caution.
|
||||
**
|
||||
** Except, if the first solver() call generated a full-table scan in an outer
|
||||
** loop then stop this analysis at the first full-scan, since the second
|
||||
** solver() run might try to swap that full-scan for another in order to
|
||||
** get the output into the correct order. In other words, we allow a
|
||||
** rewrite like this:
|
||||
**
|
||||
** First Solver() Second Solver()
|
||||
** |-- SCAN t1 |-- SCAN t2
|
||||
** |-- SEARCH t2 `-- SEARCH t1
|
||||
** `-- SORT USING B-TREE
|
||||
**
|
||||
** The purpose of this routine is to disallow rewrites such as:
|
||||
**
|
||||
** First Solver() Second Solver()
|
||||
** |-- SEARCH t1 |-- SCAN t2 <--- bad!
|
||||
** |-- SEARCH t2 `-- SEARCH t1
|
||||
** `-- SORT USING B-TREE
|
||||
**
|
||||
** See test cases in test/whereN.test for the real-world query that
|
||||
** originally provoked this heuristic.
|
||||
*/
|
||||
static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){
|
||||
int i;
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
int once = 0;
|
||||
#endif
|
||||
for(i=0; i<pWInfo->nLevel; i++){
|
||||
WhereLoop *p = pWInfo->a[i].pWLoop;
|
||||
if( p==0 ) break;
|
||||
if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;
|
||||
if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
|
||||
u8 iTab = p->iTab;
|
||||
WhereLoop *pLoop;
|
||||
for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
|
||||
if( pLoop->iTab!=iTab ) continue;
|
||||
if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
|
||||
/* Auto-index and index-constrained loops allowed to remain */
|
||||
continue;
|
||||
}
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace & 0x80 ){
|
||||
if( once==0 ){
|
||||
sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n");
|
||||
once = 1;
|
||||
}
|
||||
sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC);
|
||||
}
|
||||
#endif /* WHERETRACE_ENABLED */
|
||||
pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Most queries use only a single table (they are not joins) and have
|
||||
** simple == constraints against indexed fields. This routine attempts
|
||||
@@ -5687,6 +5850,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:
|
||||
**
|
||||
@@ -5828,6 +5995,58 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** 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
|
||||
@@ -5853,33 +6072,19 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
Expr *pExpr;
|
||||
int j = pIdx->aiColumn[i];
|
||||
int bMaybeNullRow;
|
||||
if( j==XN_EXPR ){
|
||||
pExpr = pIdx->aColExpr->a[i].pExpr;
|
||||
testcase( pTabItem->fg.jointype & JT_LEFT );
|
||||
testcase( pTabItem->fg.jointype & JT_RIGHT );
|
||||
testcase( pTabItem->fg.jointype & JT_LTORJ );
|
||||
bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
|
||||
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
|
||||
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
|
||||
bMaybeNullRow = 0;
|
||||
}else{
|
||||
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;
|
||||
@@ -5894,7 +6099,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
||||
p->iDataCur = pTabItem->iCursor;
|
||||
p->iIdxCur = iIdxCur;
|
||||
p->iIdxCol = i;
|
||||
p->bMaybeNullRow = bMaybeNullRow;
|
||||
p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
|
||||
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
|
||||
p->aff = pIdx->zColAff[i];
|
||||
}
|
||||
@@ -6062,6 +6267,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
|
||||
@@ -6301,6 +6507,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
wherePathSolver(pWInfo, 0);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
if( pWInfo->pOrderBy ){
|
||||
whereInterstageHeuristic(pWInfo);
|
||||
wherePathSolver(pWInfo, pWInfo->nRowOut+1);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}
|
||||
@@ -6361,10 +6568,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;
|
||||
@@ -6684,26 +6891,6 @@ whereBeginError:
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Return true if cursor iCur is opened by instruction k of the
|
||||
** bytecode. Used inside of assert() only.
|
||||
*/
|
||||
static int cursorIsOpen(Vdbe *v, int iCur, int k){
|
||||
while( k>=0 ){
|
||||
VdbeOp *pOp = sqlite3VdbeGetOp(v,k--);
|
||||
if( pOp->p1!=iCur ) continue;
|
||||
if( pOp->opcode==OP_Close ) return 0;
|
||||
if( pOp->opcode==OP_OpenRead ) return 1;
|
||||
if( pOp->opcode==OP_OpenWrite ) return 1;
|
||||
if( pOp->opcode==OP_OpenDup ) return 1;
|
||||
if( pOp->opcode==OP_OpenAutoindex ) return 1;
|
||||
if( pOp->opcode==OP_OpenEphemeral ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** Generate the end of the WHERE loop. See comments on
|
||||
** sqlite3WhereBegin() for additional information.
|
||||
@@ -6850,7 +7037,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)
|
||||
@@ -6995,16 +7190,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
** reference. Verify that this is harmless - that the
|
||||
** table being referenced really is open.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|
||||
|| cursorIsOpen(v,pOp->p1,k)
|
||||
|| pOp->opcode==OP_Offset
|
||||
);
|
||||
#else
|
||||
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|
||||
|| cursorIsOpen(v,pOp->p1,k)
|
||||
);
|
||||
#endif
|
||||
if( pLoop->wsFlags & WHERE_IDX_ONLY ){
|
||||
sqlite3ErrorMsg(pParse, "internal query planner error");
|
||||
pParse->rc = SQLITE_INTERNAL;
|
||||
}
|
||||
}
|
||||
}else if( pOp->opcode==OP_Rowid ){
|
||||
pOp->p1 = pLevel->iIdxCur;
|
||||
|
||||
+40
-2
@@ -1337,6 +1337,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 +1436,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 +2105,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;
|
||||
@@ -2474,6 +2497,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** iLoop==3: Code all remaining expressions.
|
||||
**
|
||||
** An effort is made to skip unnecessary iterations of the loop.
|
||||
**
|
||||
** This optimization of causing simple query restrictions to occur before
|
||||
** more complex one is call the "push-down" optimization in MySQL. Here
|
||||
** in SQLite, the name is "MySQL push-down", since there is also another
|
||||
** totally unrelated optimization called "WHERE-clause push-down".
|
||||
** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
|
||||
*/
|
||||
iLoop = (pIdx ? 1 : 2);
|
||||
do{
|
||||
@@ -2724,7 +2753,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 ){
|
||||
|
||||
+6
-3
@@ -1638,6 +1638,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 +1653,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -763,4 +763,27 @@ do_execsql_test 30.2 {
|
||||
)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 31.0 {
|
||||
CREATE TABLE t1(ii INTEGER PRIMARY KEY, tt INTEGER, rr REAL);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
|
||||
)
|
||||
INSERT INTO t1 SELECT NULL, i, 5.0 FROM s;
|
||||
}
|
||||
|
||||
do_test 31.1 {
|
||||
set pg [db one {PRAGMA page_count}]
|
||||
execsql {
|
||||
ALTER TABLE t1 DROP COLUMN tt;
|
||||
}
|
||||
set pg2 [db one {PRAGMA page_count}]
|
||||
expr $pg==$pg2
|
||||
} {1}
|
||||
|
||||
do_execsql_test 31.2 {
|
||||
SELECT rr FROM t1 LIMIT 1
|
||||
} {5.0}
|
||||
|
||||
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,213 @@
|
||||
# 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}}
|
||||
|
||||
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}
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-1
@@ -135,6 +135,10 @@ reset_db
|
||||
do_catchsql_test default-5.1 {
|
||||
CREATE TABLE t1 (a,b DEFAULT(random() NOTNULL IN (RAISE(IGNORE),2,3)));
|
||||
INSERT INTO t1(a) VALUES(1);
|
||||
} {1 {RAISE() may only be used within a trigger-program}}
|
||||
} {1 {default value of column [b] is not constant}}
|
||||
do_catchsql_test default-5.2 {
|
||||
CREATE TABLE Table0 (Col0 DEFAULT (RAISE(IGNORE) ) ) ;
|
||||
INSERT INTO Table0 DEFAULT VALUES ;
|
||||
} {1 {default value of column [Col0] is not constant}}
|
||||
|
||||
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
|
||||
|
||||
+11
-5
@@ -979,7 +979,8 @@ extern int fuzz_invariant(
|
||||
int iRow, /* The row number for pStmt */
|
||||
int nRow, /* Total number of output rows */
|
||||
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
|
||||
int eVerbosity /* How much debugging output */
|
||||
int eVerbosity, /* How much debugging output */
|
||||
unsigned int dbOpt /* Default optimization flags */
|
||||
);
|
||||
|
||||
/* Implementation of sqlite_dbdata and sqlite_dbptr */
|
||||
@@ -1031,7 +1032,12 @@ static int recoverDatabase(sqlite3 *db){
|
||||
/*
|
||||
** Run the SQL text
|
||||
*/
|
||||
static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
|
||||
static int runDbSql(
|
||||
sqlite3 *db, /* Run SQL on this database connection */
|
||||
const char *zSql, /* The SQL to be run */
|
||||
unsigned int *pBtsFlags,
|
||||
unsigned int dbOpt /* Default optimization flags */
|
||||
){
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
int bCorrupt = 0;
|
||||
@@ -1107,7 +1113,7 @@ static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
|
||||
iRow++;
|
||||
for(iCnt=0; iCnt<99999; iCnt++){
|
||||
rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow,
|
||||
&bCorrupt, eVerbosity);
|
||||
&bCorrupt, eVerbosity, dbOpt);
|
||||
if( rc==SQLITE_DONE ) break;
|
||||
if( rc!=SQLITE_ERROR ) g.nInvariant++;
|
||||
if( eVerbosity>0 ){
|
||||
@@ -1330,7 +1336,7 @@ int runCombinedDbSqlInput(
|
||||
char cSaved = zSql[i+1];
|
||||
zSql[i+1] = 0;
|
||||
if( sqlite3_complete(zSql+j) ){
|
||||
rc = runDbSql(cx.db, zSql+j, &btsFlags);
|
||||
rc = runDbSql(cx.db, zSql+j, &btsFlags, dbOpt);
|
||||
j = i+1;
|
||||
}
|
||||
zSql[i+1] = cSaved;
|
||||
@@ -1340,7 +1346,7 @@ int runCombinedDbSqlInput(
|
||||
}
|
||||
}
|
||||
if( j<i ){
|
||||
runDbSql(cx.db, zSql+j, &btsFlags);
|
||||
runDbSql(cx.db, zSql+j, &btsFlags, dbOpt);
|
||||
}
|
||||
}
|
||||
testrun_finished:
|
||||
|
||||
+24
-15
@@ -30,7 +30,13 @@
|
||||
/* Forward references */
|
||||
static char *fuzz_invariant_sql(sqlite3_stmt*, int);
|
||||
static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int,sqlite3_stmt*);
|
||||
static void reportInvariantFailed(sqlite3_stmt*,sqlite3_stmt*,int);
|
||||
static void reportInvariantFailed(
|
||||
sqlite3_stmt *pOrig, /* The original query */
|
||||
sqlite3_stmt *pTest, /* The alternative test query with a missing row */
|
||||
int iRow, /* Row number in pOrig */
|
||||
unsigned int dbOpt, /* Optimization flags on pOrig */
|
||||
int noOpt /* True if opt flags inverted for pTest */
|
||||
);
|
||||
|
||||
/*
|
||||
** Do an invariant check on pStmt. iCnt determines which invariant check to
|
||||
@@ -68,7 +74,8 @@ int fuzz_invariant(
|
||||
int iRow, /* Current row number */
|
||||
int nRow, /* Number of output rows from pStmt */
|
||||
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
|
||||
int eVerbosity /* How much debugging output */
|
||||
int eVerbosity, /* How much debugging output */
|
||||
unsigned int dbOpt /* Default optimization flags */
|
||||
){
|
||||
char *zTest;
|
||||
sqlite3_stmt *pTestStmt = 0;
|
||||
@@ -76,13 +83,20 @@ int fuzz_invariant(
|
||||
int i;
|
||||
int nCol;
|
||||
int nParam;
|
||||
int noOpt = (iCnt%3)==0;
|
||||
|
||||
if( *pbCorrupt ) return SQLITE_DONE;
|
||||
nParam = sqlite3_bind_parameter_count(pStmt);
|
||||
if( nParam>100 ) return SQLITE_DONE;
|
||||
zTest = fuzz_invariant_sql(pStmt, iCnt);
|
||||
if( zTest==0 ) return SQLITE_DONE;
|
||||
if( noOpt ){
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, ~dbOpt);
|
||||
}
|
||||
rc = sqlite3_prepare_v2(db, zTest, -1, &pTestStmt, 0);
|
||||
if( noOpt ){
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, dbOpt);
|
||||
}
|
||||
if( rc ){
|
||||
if( eVerbosity ){
|
||||
printf("invariant compile failed: %s\n%s\n",
|
||||
@@ -212,7 +226,7 @@ int fuzz_invariant(
|
||||
}
|
||||
sqlite3_finalize(pCk);
|
||||
if( rc==SQLITE_DONE ){
|
||||
reportInvariantFailed(pStmt, pTestStmt, iRow);
|
||||
reportInvariantFailed(pStmt, pTestStmt, iRow, dbOpt, noOpt);
|
||||
return SQLITE_INTERNAL;
|
||||
}else if( eVerbosity>0 ){
|
||||
printf("invariant-error ignored due to the use of virtual tables\n");
|
||||
@@ -223,7 +237,6 @@ not_a_fault:
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Generate SQL used to test a statement invariant.
|
||||
**
|
||||
@@ -296,14 +309,6 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
|
||||
** WHERE clause. */
|
||||
continue;
|
||||
}
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( sqlite3_strlike("%rowid%",zColName,0)==0
|
||||
|| sqlite3_strlike("%oid%",zColName,0)==0
|
||||
){
|
||||
/* ROWID values are unreliable if SQLITE_ALLOW_ROWID_IN_VIEW is used */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
for(j=0; j<i; j++){
|
||||
const char *zPrior = sqlite3_column_name(pBase, j);
|
||||
if( sqlite3_stricmp(zPrior, zColName)==0 ) break;
|
||||
@@ -497,13 +502,17 @@ static void printRow(sqlite3_stmt *pStmt, int iRow){
|
||||
static void reportInvariantFailed(
|
||||
sqlite3_stmt *pOrig, /* The original query */
|
||||
sqlite3_stmt *pTest, /* The alternative test query with a missing row */
|
||||
int iRow /* Row number in pOrig */
|
||||
int iRow, /* Row number in pOrig */
|
||||
unsigned int dbOpt, /* Optimization flags on pOrig */
|
||||
int noOpt /* True if opt flags inverted for pTest */
|
||||
){
|
||||
int iTestRow = 0;
|
||||
printf("Invariant check failed on row %d.\n", iRow);
|
||||
printf("Original query --------------------------------------------------\n");
|
||||
printf("Original query (opt-flags: 0x%08x) --------------------------\n",
|
||||
dbOpt);
|
||||
printf("%s\n", sqlite3_expanded_sql(pOrig));
|
||||
printf("Alternative query -----------------------------------------------\n");
|
||||
printf("Alternative query (opt-flags: 0x%08x) -----------------------\n",
|
||||
noOpt ? ~dbOpt : dbOpt);
|
||||
printf("%s\n", sqlite3_expanded_sql(pTest));
|
||||
printf("Result row that is missing from the alternative -----------------\n");
|
||||
printRow(pOrig, iRow);
|
||||
|
||||
+17
-1
@@ -149,7 +149,7 @@ ifcapable icu {
|
||||
# 2020-03-19
|
||||
# The ESCAPE clause on LIKE takes precedence over wildcards
|
||||
#
|
||||
do_execsql_test idu-6.0 {
|
||||
do_execsql_test icu-6.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT);
|
||||
INSERT INTO t1 VALUES
|
||||
@@ -164,4 +164,20 @@ do_execsql_test icu-6.1 {
|
||||
SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_';
|
||||
} {2}
|
||||
|
||||
# 2024-04-02
|
||||
# Optional 3rd argument to icu_load_collation() that specifies
|
||||
# the "strength" of comparison.
|
||||
#
|
||||
reset_db
|
||||
do_catchsql_test icu-7.1 {
|
||||
SELECT icu_load_collation('en_US','error','xyzzy');
|
||||
} {1 {unknown collation strength "xyzzy" - should be one of: PRIMARY SECONDARY TERTIARY DEFAULT QUARTERNARY IDENTICAL}}
|
||||
do_execsql_test icu-7.2 {
|
||||
SELECT icu_load_collation('en_US','prim','PRIMARY'),
|
||||
icu_load_collation('en_US','dflt','DEFAULT');
|
||||
} {{} {}}
|
||||
do_execsql_test icu-7.3 {
|
||||
SELECT char(0x100)=='a', char(0x100)=='a' COLLATE dflt, char(0x100)=='a' COLLATE prim;
|
||||
} {0 0 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
|
||||
#
|
||||
|
||||
@@ -309,4 +309,36 @@ do_execsql_test 12.3 {
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# 2024-04-05 dbsqlfuzz b9e65e2f110df998f1306571fae7af6c01e4d92b
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE TABLE t1(a INT AS (b), b INT);
|
||||
INSERT INTO t1(b) VALUES(123);
|
||||
CREATE TABLE t2(a INT, c INT);
|
||||
SELECT a FROM t2 NATURAL RIGHT JOIN t1;
|
||||
} {123}
|
||||
do_execsql_test 13.2 {
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
SELECT a FROM t2 NATURAL RIGHT JOIN t1;
|
||||
} {123}
|
||||
# Further tests of the same logic (indexes on expressions
|
||||
# used by RIGHT JOIN) from check-in ffe23af73fcb324d and
|
||||
# forum post https://sqlite.org/forum/forumpost/9b491e1debf0b67a.
|
||||
db null NULL
|
||||
do_execsql_test 13.3 {
|
||||
CREATE TABLE t3(a INT, b INT);
|
||||
CREATE UNIQUE INDEX t3x ON t3(a, a+b);
|
||||
INSERT INTO t3(a,b) VALUES(1,2),(4,8),(16,32),(4,80),(1,-300);
|
||||
CREATE TABLE t4(x INT, y INT);
|
||||
INSERT INTO t4(x,y) SELECT a, b FROM t3;
|
||||
INSERT INTO t4(x,y) VALUES(99,99);
|
||||
SELECT a1.a, sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t4 ON a=x
|
||||
GROUP BY a1.a ORDER BY 1;
|
||||
} {NULL NULL 1 -592 4 192 16 48}
|
||||
do_execsql_test 13.4 {
|
||||
SELECT sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t3 ON true
|
||||
GROUP BY a1.a ORDER BY 1;
|
||||
} {-1480 240 480}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -764,4 +764,35 @@ do_execsql_test json102-1720 {
|
||||
SELECT * FROM t1;
|
||||
} {ok 2023-08-03 876 5 {{"x":77,"y":6}}}
|
||||
|
||||
# 2024-05-21 https://sqlite.org/forum/forumpost/9e52cdfe15c3926e
|
||||
# What if the RHS of the -> or ->> operator is a string that looks
|
||||
# like a number? PostgreSQL treats it as a string.
|
||||
#
|
||||
do_execsql_test json102-1800 {
|
||||
SELECT '{"1":"one","2":"two","3":"three"}'->>'2';
|
||||
} two
|
||||
db null NULL
|
||||
do_execsql_test json102-1801 {
|
||||
SELECT '{"1":"one","2":"two","3":"three"}'->>2;
|
||||
} NULL
|
||||
do_execsql_test json102-1810 {
|
||||
SELECT '["zero","one","two"]'->>'1';
|
||||
} NULL
|
||||
do_execsql_test json102-1811 {
|
||||
SELECT '["zero","one","two"]'->>1;
|
||||
} one
|
||||
do_execsql_test json102-1820 {
|
||||
SELECT '{"1":"one","2":"two","3":"three"}'->'2';
|
||||
} {{"two"}}
|
||||
do_execsql_test json102-1821 {
|
||||
SELECT '{"1":"one","2":"two","3":"three"}'->2;
|
||||
} {NULL}
|
||||
do_execsql_test json102-1830 {
|
||||
SELECT '["zero","one","two"]'->'1';
|
||||
} {NULL}
|
||||
do_execsql_test json102-1831 {
|
||||
SELECT '["zero","one","two"]'->1;
|
||||
} {{"one"}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+6
-1
@@ -2,6 +2,11 @@
|
||||
//
|
||||
// lemon lemon-test01.y && gcc -g lemon-test01.c && ./a.out
|
||||
//
|
||||
// This testcase was made obsolete by check-in 7cca80808cef192f on
|
||||
// 2021-08-17 (associated with Forum Thread
|
||||
// https://sqlite.org/forum/forumpost/bd91fd965c9803c4) and no longer
|
||||
// works. It is retained for historical reference only.
|
||||
//
|
||||
%token_prefix TK_
|
||||
%token_type int
|
||||
%default_type int
|
||||
@@ -28,7 +33,7 @@ all ::= error B.
|
||||
#include "lemon-test01.h"
|
||||
static int nTest = 0;
|
||||
static int nErr = 0;
|
||||
static int testCase(int testId, int shouldBe, int actual){
|
||||
static void testCase(int testId, int shouldBe, int actual){
|
||||
nTest++;
|
||||
if( shouldBe==actual ){
|
||||
printf("test %d: ok\n", testId);
|
||||
|
||||
+6
-1
@@ -100,6 +100,11 @@ do_execsql_test misc8-2.1 {
|
||||
|
||||
# 2016-02-26: An assertion fault found by the libFuzzer project
|
||||
#
|
||||
ifcapable allow_rowid_in_view {
|
||||
set nosuch "1 {ambiguous column name: rowid}"
|
||||
} else {
|
||||
set nosuch "1 {no such column: rowid}"
|
||||
}
|
||||
do_catchsql_test misc8-3.0 {
|
||||
SELECT *
|
||||
FROM
|
||||
@@ -110,7 +115,7 @@ do_catchsql_test misc8-3.0 {
|
||||
(SELECT 6 AS j UNION ALL SELECT 7) AS x4
|
||||
WHERE i<rowid
|
||||
ORDER BY 1;
|
||||
} {1 {no such column: rowid}}
|
||||
} $nosuch
|
||||
|
||||
# The SQLITE_DBCONFIG_MAINDBNAME interface
|
||||
#
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user