1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Merge latest trunk changes into this branch.

FossilOrigin-Name: d5b597b52a1213cdf382d96f4df3535727be0852b25bafd12bbef54da946c5f2
This commit is contained in:
dan
2017-12-16 19:16:24 +00:00
43 changed files with 1131 additions and 376 deletions

View File

@@ -2077,6 +2077,24 @@ FTS5_SRC = \
$(TOP)\ext\fts5\fts5_varint.c \ $(TOP)\ext\fts5\fts5_varint.c \
$(TOP)\ext\fts5\fts5_vocab.c $(TOP)\ext\fts5\fts5_vocab.c
LSM1_SRC = \
$(TOP)\ext\lsm1\lsm.h \
$(TOP)\ext\lsm1\lsmInt.h \
$(TOP)\ext\lsm1\lsm_ckpt.c \
$(TOP)\ext\lsm1\lsm_file.c \
$(TOP)\ext\lsm1\lsm_log.c \
$(TOP)\ext\lsm1\lsm_main.c \
$(TOP)\ext\lsm1\lsm_mem.c \
$(TOP)\ext\lsm1\lsm_mutex.c \
$(TOP)\ext\lsm1\lsm_shared.c \
$(TOP)\ext\lsm1\lsm_sorted.c \
$(TOP)\ext\lsm1\lsm_str.c \
$(TOP)\ext\lsm1\lsm_tree.c \
$(TOP)\ext\lsm1\lsm_unix.c \
$(TOP)\ext\lsm1\lsm_varint.c \
$(TOP)\ext\lsm1\lsm_vtab.c \
$(TOP)\ext\lsm1\lsm_win32.c
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
copy $(TOP)\ext\fts5\fts5parse.y . copy $(TOP)\ext\fts5\fts5parse.y .
del /Q fts5parse.h 2>NUL del /Q fts5parse.h 2>NUL
@@ -2088,6 +2106,10 @@ fts5.c: $(FTS5_SRC)
$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl $(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
copy $(TOP)\ext\fts5\fts5.h . copy $(TOP)\ext\fts5\fts5.h .
lsm1.c: $(LSM1_SRC)
$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
copy $(TOP)\ext\lsm1\lsm.h .
fts5.lo: fts5.c $(HDR) $(EXTHDR) fts5.lo: fts5.c $(HDR) $(EXTHDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
@@ -2320,4 +2342,5 @@ clean:
del /Q sqlite-*-output.vsix 2>NUL del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
del /Q fts5.* fts5parse.* 2>NUL del /Q fts5.* fts5parse.* 2>NUL
del /Q lsm.h lsm1.c 2>NUL
# <</mark>> # <</mark>>

View File

@@ -207,8 +207,8 @@ The amalgamation source file is more than 200K lines long. Some symbolic
debuggers (most notably MSVC) are unable to deal with files longer than 64K debuggers (most notably MSVC) are unable to deal with files longer than 64K
lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl, lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl,
can be run on the amalgamation to break it up into a single small C file can be run on the amalgamation to break it up into a single small C file
called **sqlite3-all.c** that does #include on about five other files called **sqlite3-all.c** that does #include on about seven other files
named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-5.c**. In this way, named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-7.c**. In this way,
all of the source code is contained within a single translation unit so all of the source code is contained within a single translation unit so
that the compiler can do extra cross-procedure optimization, but no that the compiler can do extra cross-procedure optimization, but no
individual source file exceeds 32K lines in length. individual source file exceeds 32K lines in length.
@@ -237,7 +237,8 @@ Key files:
trying to understand how the library works internally. trying to understand how the library works internally.
* **sqliteInt.h** - this header file defines many of the data objects * **sqliteInt.h** - this header file defines many of the data objects
used internally by SQLite. used internally by SQLite. In addition to "sqliteInt.h", some
subsystems have their own header files.
* **parse.y** - This file describes the LALR(1) grammar that SQLite uses * **parse.y** - This file describes the LALR(1) grammar that SQLite uses
to parse SQL statements, and the actions that are taken at each step to parse SQL statements, and the actions that are taken at each step
@@ -249,29 +250,44 @@ Key files:
which defines internal data objects. The rest of SQLite interacts which defines internal data objects. The rest of SQLite interacts
with the VDBE through an interface defined by vdbe.h. with the VDBE through an interface defined by vdbe.h.
* **where.c** - This file analyzes the WHERE clause and generates * **where.c** - This file (together with its helper files named
by "where*.c") analyzes the WHERE clause and generates
virtual machine code to run queries efficiently. This file is virtual machine code to run queries efficiently. This file is
sometimes called the "query optimizer". It has its own private sometimes called the "query optimizer". It has its own private
header file, whereInt.h, that defines data objects used internally. header file, whereInt.h, that defines data objects used internally.
* **btree.c** - This file contains the implementation of the B-Tree * **btree.c** - This file contains the implementation of the B-Tree
storage engine used by SQLite. storage engine used by SQLite. The interface to the rest of the system
is defined by "btree.h". The "btreeInt.h" header defines objects
used internally by btree.c and not published to the rest of the system.
* **pager.c** - This file contains the "pager" implementation, the * **pager.c** - This file contains the "pager" implementation, the
module that implements transactions. module that implements transactions. The "pager.h" header file
defines the interface between pager.c and the rest of the system.
* **os_unix.c** and **os_win.c** - These two files implement the interface * **os_unix.c** and **os_win.c** - These two files implement the interface
between SQLite and the underlying operating system using the run-time between SQLite and the underlying operating system using the run-time
pluggable VFS interface. pluggable VFS interface.
* **shell.c** - This file is not part of the core SQLite library. This * **shell.c.in** - This file is not part of the core SQLite library. This
is the file that, when linked against sqlite3.a, generates the is the file that, when linked against sqlite3.a, generates the
"sqlite3.exe" command-line shell. "sqlite3.exe" command-line shell. The "shell.c.in" file is transformed
into "shell.c" as part of the build process.
* **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It * **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It
is not part of the core SQLite library. But as most of the tests in this is not part of the core SQLite library. But as most of the tests in this
repository are written in Tcl, the Tcl language bindings are important. repository are written in Tcl, the Tcl language bindings are important.
* **test*.c** - Files in the src/ folder that begin with "test" go into
building the "testfixture.exe" program. The testfixture.exe program is
an enhanced TCL shell. The testfixture.exe program runs scripts in the
test/ folder to validate the core SQLite code. The testfixture program
(and some other test programs too) is build and run when you type
"make test".
* **ext/misc/json1.c** - This file implements the various JSON functions
that are build into SQLite.
There are many other source files. Each has a succinct header comment that There are many other source files. Each has a succinct header comment that
describes its purpose and role within the larger system. describes its purpose and role within the larger system.

View File

@@ -4909,7 +4909,13 @@ static void fts5MergePrefixLists(
Fts5Buffer out = {0, 0, 0}; Fts5Buffer out = {0, 0, 0};
Fts5Buffer tmp = {0, 0, 0}; Fts5Buffer tmp = {0, 0, 0};
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; /* The maximum size of the output is equal to the sum of the two
** input sizes + 1 varint (9 bytes). The extra varint is because if the
** first rowid in one input is a large negative number, and the first in
** the other a non-negative number, the delta for the non-negative
** number will be larger on disk than the literal integer value
** was. */
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return;
fts5DoclistIterInit(p1, &i1); fts5DoclistIterInit(p1, &i1);
fts5DoclistIterInit(p2, &i2); fts5DoclistIterInit(p2, &i2);
@@ -5003,6 +5009,7 @@ static void fts5MergePrefixLists(
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
} }
assert( out.n<=(p1->n+p2->n+9) );
fts5BufferSet(&p->rc, p1, out.n, out.p); fts5BufferSet(&p->rc, p1, out.n, out.p);
fts5BufferFree(&tmp); fts5BufferFree(&tmp);

View File

@@ -64,7 +64,7 @@ for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
execsql COMMIT execsql COMMIT
} {} } {}
do_execsql_test 1.$tn.2 { do_execsql_test 2.$tn.2 {
INSERT INTO t1(t1) VALUES('integrity-check'); INSERT INTO t1(t1) VALUES('integrity-check');
} }
@@ -77,5 +77,15 @@ for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
} }
} }
reset_db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE x1 USING fts5(a);
INSERT INTO x1(rowid, a) VALUES(-1000000000000, 'toyota');
INSERT INTO x1(rowid, a) VALUES(1, 'tarago');
}
do_execsql_test 3.1 {
SELECT rowid FROM x1('t*');
} {-1000000000000 1}
finish_test finish_test

View File

@@ -28,7 +28,9 @@
** provide case-independent matching. ** provide case-independent matching.
*/ */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) #if !defined(SQLITE_CORE) \
|| defined(SQLITE_ENABLE_ICU) \
|| defined(SQLITE_ENABLE_ICU_COLLATIONS)
/* Include ICU headers */ /* Include ICU headers */
#include <unicode/utypes.h> #include <unicode/utypes.h>
@@ -45,6 +47,26 @@
#include "sqlite3.h" #include "sqlite3.h"
#endif #endif
/*
** This function is called when an ICU function called from within
** the implementation of an SQL scalar function returns an error.
**
** The scalar function context passed as the first argument is
** loaded with an error message based on the following two args.
*/
static void icuFunctionError(
sqlite3_context *pCtx, /* SQLite scalar function context */
const char *zName, /* Name of ICU function that failed */
UErrorCode e /* Error code returned by ICU function */
){
char zBuf[128];
sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e));
zBuf[127] = '\0';
sqlite3_result_error(pCtx, zBuf, -1);
}
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
/* /*
** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** Maximum length (in bytes) of the pattern in a LIKE or GLOB
** operator. ** operator.
@@ -224,24 +246,6 @@ static void icuLikeFunc(
} }
} }
/*
** This function is called when an ICU function called from within
** the implementation of an SQL scalar function returns an error.
**
** The scalar function context passed as the first argument is
** loaded with an error message based on the following two args.
*/
static void icuFunctionError(
sqlite3_context *pCtx, /* SQLite scalar function context */
const char *zName, /* Name of ICU function that failed */
UErrorCode e /* Error code returned by ICU function */
){
char zBuf[128];
sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e));
zBuf[127] = '\0';
sqlite3_result_error(pCtx, zBuf, -1);
}
/* /*
** Function to delete compiled regexp objects. Registered as ** Function to delete compiled regexp objects. Registered as
** a destructor function with sqlite3_set_auxdata(). ** a destructor function with sqlite3_set_auxdata().
@@ -407,6 +411,8 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
assert( 0 ); /* Unreachable */ assert( 0 ); /* Unreachable */
} }
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
/* /*
** Collation sequence destructor function. The pCtx argument points to ** Collation sequence destructor function. The pCtx argument points to
** a UCollator structure previously allocated using ucol_open(). ** a UCollator structure previously allocated using ucol_open().
@@ -501,6 +507,7 @@ int sqlite3IcuInit(sqlite3 *db){
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = { } scalars[] = {
{"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation}, {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc}, {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
@@ -512,10 +519,10 @@ int sqlite3IcuInit(sqlite3 *db){
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
}; };
int rc = SQLITE_OK; int rc = SQLITE_OK;
int i; int i;
for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){ for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
const struct IcuScalar *p = &scalars[i]; const struct IcuScalar *p = &scalars[i];

View File

@@ -110,7 +110,7 @@ typedef unsigned long long int u64;
#endif #endif
/* A page number is a 64-bit integer. */ /* A page number is a 64-bit integer. */
typedef i64 Pgno; typedef i64 LsmPgno;
#ifdef LSM_DEBUG #ifdef LSM_DEBUG
int lsmErrorBkpt(int); int lsmErrorBkpt(int);
@@ -402,9 +402,9 @@ struct lsm_db {
}; };
struct Segment { struct Segment {
Pgno iFirst; /* First page of this run */ LsmPgno iFirst; /* First page of this run */
Pgno iLastPg; /* Last page of this run */ LsmPgno iLastPg; /* Last page of this run */
Pgno iRoot; /* Root page number (if any) */ LsmPgno iRoot; /* Root page number (if any) */
int nSize; /* Size of this run in pages */ int nSize; /* Size of this run in pages */
Redirect *pRedirect; /* Block redirects (or NULL) */ Redirect *pRedirect; /* Block redirects (or NULL) */
@@ -456,7 +456,7 @@ struct Level {
** output segment. ** output segment.
*/ */
struct MergeInput { struct MergeInput {
Pgno iPg; /* Page on which next input is stored */ LsmPgno iPg; /* Page on which next input is stored */
int iCell; /* Cell containing next input to merge */ int iCell; /* Cell containing next input to merge */
}; };
struct Merge { struct Merge {
@@ -465,7 +465,7 @@ struct Merge {
MergeInput splitkey; /* Location in file of current splitkey */ MergeInput splitkey; /* Location in file of current splitkey */
int nSkip; /* Number of separators entries to skip */ int nSkip; /* Number of separators entries to skip */
int iOutputOff; /* Write offset on output page */ int iOutputOff; /* Write offset on output page */
Pgno iCurrentPtr; /* Current pointer value */ LsmPgno iCurrentPtr; /* Current pointer value */
}; };
/* /*
@@ -579,10 +579,10 @@ struct Snapshot {
Redirect redirect; /* Block redirection array */ Redirect redirect; /* Block redirection array */
/* Used by worker snapshots only */ /* Used by worker snapshots only */
int nBlock; /* Number of blocks in database file */ int nBlock; /* Number of blocks in database file */
Pgno aiAppend[LSM_APPLIST_SZ]; /* Append point list */ LsmPgno aiAppend[LSM_APPLIST_SZ]; /* Append point list */
Freelist freelist; /* Free block list */ Freelist freelist; /* Free block list */
u32 nWrite; /* Total number of pages written to disk */ u32 nWrite; /* Total number of pages written to disk */
}; };
#define LSM_INITIAL_SNAPSHOT_ID 11 #define LSM_INITIAL_SNAPSHOT_ID 11
@@ -710,7 +710,7 @@ void lsmFsSetPageSize(FileSystem *, int);
int lsmFsFileid(lsm_db *pDb, void **ppId, int *pnId); int lsmFsFileid(lsm_db *pDb, void **ppId, int *pnId);
/* Creating, populating, gobbling and deleting sorted runs. */ /* Creating, populating, gobbling and deleting sorted runs. */
void lsmFsGobble(lsm_db *, Segment *, Pgno *, int); void lsmFsGobble(lsm_db *, Segment *, LsmPgno *, int);
int lsmFsSortedDelete(FileSystem *, Snapshot *, int, Segment *); int lsmFsSortedDelete(FileSystem *, Snapshot *, int, Segment *);
int lsmFsSortedFinish(FileSystem *, Segment *); int lsmFsSortedFinish(FileSystem *, Segment *);
int lsmFsSortedAppend(FileSystem *, Snapshot *, Level *, int, Page **); int lsmFsSortedAppend(FileSystem *, Snapshot *, Level *, int, Page **);
@@ -727,14 +727,14 @@ void lsmSortedSplitkey(lsm_db *, Level *, int *);
/* Reading sorted run content. */ /* Reading sorted run content. */
int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg); int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg);
int lsmFsDbPageGet(FileSystem *, Segment *, Pgno, Page **); int lsmFsDbPageGet(FileSystem *, Segment *, LsmPgno, Page **);
int lsmFsDbPageNext(Segment *, Page *, int eDir, Page **); int lsmFsDbPageNext(Segment *, Page *, int eDir, Page **);
u8 *lsmFsPageData(Page *, int *); u8 *lsmFsPageData(Page *, int *);
int lsmFsPageRelease(Page *); int lsmFsPageRelease(Page *);
int lsmFsPagePersist(Page *); int lsmFsPagePersist(Page *);
void lsmFsPageRef(Page *); void lsmFsPageRef(Page *);
Pgno lsmFsPageNumber(Page *); LsmPgno lsmFsPageNumber(Page *);
int lsmFsNRead(FileSystem *); int lsmFsNRead(FileSystem *);
int lsmFsNWrite(FileSystem *); int lsmFsNWrite(FileSystem *);
@@ -748,7 +748,7 @@ int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg);
int lsmFsIntegrityCheck(lsm_db *); int lsmFsIntegrityCheck(lsm_db *);
#endif #endif
Pgno lsmFsRedirectPage(FileSystem *, Redirect *, Pgno); LsmPgno lsmFsRedirectPage(FileSystem *, Redirect *, LsmPgno);
int lsmFsPageWritable(Page *); int lsmFsPageWritable(Page *);
@@ -768,8 +768,8 @@ int lsmFsSyncDb(FileSystem *, int);
void lsmFsFlushWaiting(FileSystem *, int *); void lsmFsFlushWaiting(FileSystem *, int *);
/* Used by lsm_info(ARRAY_STRUCTURE) and lsm_config(MMAP) */ /* Used by lsm_info(ARRAY_STRUCTURE) and lsm_config(MMAP) */
int lsmInfoArrayStructure(lsm_db *pDb, int bBlock, Pgno iFirst, char **pzOut); int lsmInfoArrayStructure(lsm_db *pDb, int bBlock, LsmPgno iFirst, char **pz);
int lsmInfoArrayPages(lsm_db *pDb, Pgno iFirst, char **pzOut); int lsmInfoArrayPages(lsm_db *pDb, LsmPgno iFirst, char **pzOut);
int lsmConfigMmap(lsm_db *pDb, int *piParam); int lsmConfigMmap(lsm_db *pDb, int *piParam);
int lsmEnvOpen(lsm_env *, const char *, int, lsm_file **); int lsmEnvOpen(lsm_env *, const char *, int, lsm_file **);
@@ -785,7 +785,7 @@ void lsmEnvSleep(lsm_env *, int);
int lsmFsReadSyncedId(lsm_db *db, int, i64 *piVal); int lsmFsReadSyncedId(lsm_db *db, int, i64 *piVal);
int lsmFsSegmentContainsPg(FileSystem *pFS, Segment *, Pgno, int *); int lsmFsSegmentContainsPg(FileSystem *pFS, Segment *, LsmPgno, int *);
void lsmFsPurgeCache(FileSystem *); void lsmFsPurgeCache(FileSystem *);
@@ -796,7 +796,7 @@ void lsmFsPurgeCache(FileSystem *);
/* /*
** Functions from file "lsm_sorted.c". ** Functions from file "lsm_sorted.c".
*/ */
int lsmInfoPageDump(lsm_db *, Pgno, int, char **); int lsmInfoPageDump(lsm_db *, LsmPgno, int, char **);
void lsmSortedCleanup(lsm_db *); void lsmSortedCleanup(lsm_db *);
int lsmSortedAutoWork(lsm_db *, int nUnit); int lsmSortedAutoWork(lsm_db *, int nUnit);

View File

@@ -389,7 +389,7 @@ static void ckptExportAppendlist(
int *pRc /* IN/OUT: Error code */ int *pRc /* IN/OUT: Error code */
){ ){
int i; int i;
Pgno *aiAppend = db->pWorker->aiAppend; LsmPgno *aiAppend = db->pWorker->aiAppend;
for(i=0; i<LSM_APPLIST_SZ; i++){ for(i=0; i<LSM_APPLIST_SZ; i++){
ckptAppend64(p, piOut, aiAppend[i], pRc); ckptAppend64(p, piOut, aiAppend[i], pRc);

View File

@@ -269,7 +269,7 @@ struct FileSystem {
struct Page { struct Page {
u8 *aData; /* Buffer containing page data */ u8 *aData; /* Buffer containing page data */
int nData; /* Bytes of usable data at aData[] */ int nData; /* Bytes of usable data at aData[] */
Pgno iPg; /* Page number */ LsmPgno iPg; /* Page number */
int nRef; /* Number of outstanding references */ int nRef; /* Number of outstanding references */
int flags; /* Combination of PAGE_XXX flags */ int flags; /* Combination of PAGE_XXX flags */
Page *pHashNext; /* Next page in hash table slot */ Page *pHashNext; /* Next page in hash table slot */
@@ -332,7 +332,7 @@ static int IOERR_WRAPPER(int rc){
#ifdef NDEBUG #ifdef NDEBUG
# define assert_lists_are_ok(x) # define assert_lists_are_ok(x)
#else #else
static Page *fsPageFindInHash(FileSystem *pFS, Pgno iPg, int *piHash); static Page *fsPageFindInHash(FileSystem *pFS, LsmPgno iPg, int *piHash);
static void assert_lists_are_ok(FileSystem *pFS){ static void assert_lists_are_ok(FileSystem *pFS){
#if 0 #if 0
@@ -532,7 +532,7 @@ int lsmFsCloseAndDeleteLog(FileSystem *pFS){
** Return true if page iReal of the database should be accessed using mmap. ** Return true if page iReal of the database should be accessed using mmap.
** False otherwise. ** False otherwise.
*/ */
static int fsMmapPage(FileSystem *pFS, Pgno iReal){ static int fsMmapPage(FileSystem *pFS, LsmPgno iReal){
return ((i64)iReal*pFS->nPagesize <= pFS->nMapLimit); return ((i64)iReal*pFS->nPagesize <= pFS->nMapLimit);
} }
@@ -540,7 +540,7 @@ static int fsMmapPage(FileSystem *pFS, Pgno iReal){
** Given that there are currently nHash slots in the hash table, return ** Given that there are currently nHash slots in the hash table, return
** the hash key for file iFile, page iPg. ** the hash key for file iFile, page iPg.
*/ */
static int fsHashKey(int nHash, Pgno iPg){ static int fsHashKey(int nHash, LsmPgno iPg){
return (iPg % nHash); return (iPg % nHash);
} }
@@ -880,13 +880,13 @@ void lsmFsSetBlockSize(FileSystem *pFS, int nBlocksize){
** page on each block is the byte offset immediately following the 4-byte ** page on each block is the byte offset immediately following the 4-byte
** "previous block" pointer at the start of each block. ** "previous block" pointer at the start of each block.
*/ */
static Pgno fsFirstPageOnBlock(FileSystem *pFS, int iBlock){ static LsmPgno fsFirstPageOnBlock(FileSystem *pFS, int iBlock){
Pgno iPg; LsmPgno iPg;
if( pFS->pCompress ){ if( pFS->pCompress ){
if( iBlock==1 ){ if( iBlock==1 ){
iPg = pFS->nMetasize * 2 + 4; iPg = pFS->nMetasize * 2 + 4;
}else{ }else{
iPg = pFS->nBlocksize * (Pgno)(iBlock-1) + 4; iPg = pFS->nBlocksize * (LsmPgno)(iBlock-1) + 4;
} }
}else{ }else{
const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize); const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
@@ -907,9 +907,9 @@ static Pgno fsFirstPageOnBlock(FileSystem *pFS, int iBlock){
** page on each block is the byte offset of the byte immediately before ** page on each block is the byte offset of the byte immediately before
** the 4-byte "next block" pointer at the end of each block. ** the 4-byte "next block" pointer at the end of each block.
*/ */
static Pgno fsLastPageOnBlock(FileSystem *pFS, int iBlock){ static LsmPgno fsLastPageOnBlock(FileSystem *pFS, int iBlock){
if( pFS->pCompress ){ if( pFS->pCompress ){
return pFS->nBlocksize * (Pgno)iBlock - 1 - 4; return pFS->nBlocksize * (LsmPgno)iBlock - 1 - 4;
}else{ }else{
const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize); const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
return iBlock * nPagePerBlock; return iBlock * nPagePerBlock;
@@ -920,7 +920,7 @@ static Pgno fsLastPageOnBlock(FileSystem *pFS, int iBlock){
** Return the block number of the block that page iPg is located on. ** Return the block number of the block that page iPg is located on.
** Blocks are numbered starting from 1. ** Blocks are numbered starting from 1.
*/ */
static int fsPageToBlock(FileSystem *pFS, Pgno iPg){ static int fsPageToBlock(FileSystem *pFS, LsmPgno iPg){
if( pFS->pCompress ){ if( pFS->pCompress ){
return (int)((iPg / pFS->nBlocksize) + 1); return (int)((iPg / pFS->nBlocksize) + 1);
}else{ }else{
@@ -933,7 +933,7 @@ static int fsPageToBlock(FileSystem *pFS, Pgno iPg){
** **
** This function is only called in non-compressed database mode. ** This function is only called in non-compressed database mode.
*/ */
static int fsIsLast(FileSystem *pFS, Pgno iPg){ static int fsIsLast(FileSystem *pFS, LsmPgno iPg){
const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize); const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
assert( !pFS->pCompress ); assert( !pFS->pCompress );
return ( iPg && (iPg % nPagePerBlock)==0 ); return ( iPg && (iPg % nPagePerBlock)==0 );
@@ -944,7 +944,7 @@ static int fsIsLast(FileSystem *pFS, Pgno iPg){
** **
** This function is only called in non-compressed database mode. ** This function is only called in non-compressed database mode.
*/ */
static int fsIsFirst(FileSystem *pFS, Pgno iPg){ static int fsIsFirst(FileSystem *pFS, LsmPgno iPg){
const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize); const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
assert( !pFS->pCompress ); assert( !pFS->pCompress );
return ( (iPg % nPagePerBlock)==1 return ( (iPg % nPagePerBlock)==1
@@ -967,7 +967,7 @@ u8 *lsmFsPageData(Page *pPage, int *pnData){
/* /*
** Return the page number of a page. ** Return the page number of a page.
*/ */
Pgno lsmFsPageNumber(Page *pPage){ LsmPgno lsmFsPageNumber(Page *pPage){
/* assert( (pPage->flags & PAGE_DIRTY)==0 ); */ /* assert( (pPage->flags & PAGE_DIRTY)==0 ); */
return pPage ? pPage->iPg : 0; return pPage ? pPage->iPg : 0;
} }
@@ -1058,7 +1058,7 @@ void lsmFsPurgeCache(FileSystem *pFS){
** Either way, if argument piHash is not NULL set *piHash to the hash slot ** Either way, if argument piHash is not NULL set *piHash to the hash slot
** number that page iPg would be stored in before returning. ** number that page iPg would be stored in before returning.
*/ */
static Page *fsPageFindInHash(FileSystem *pFS, Pgno iPg, int *piHash){ static Page *fsPageFindInHash(FileSystem *pFS, LsmPgno iPg, int *piHash){
Page *p; /* Return value */ Page *p; /* Return value */
int iHash = fsHashKey(pFS->nHash, iPg); int iHash = fsHashKey(pFS->nHash, iPg);
@@ -1189,8 +1189,8 @@ static int fsRedirectBlock(Redirect *p, int iBlk){
** object passed as the second argument, return the destination page to ** object passed as the second argument, return the destination page to
** which it is redirected. Otherwise, return a copy of iPg. ** which it is redirected. Otherwise, return a copy of iPg.
*/ */
Pgno lsmFsRedirectPage(FileSystem *pFS, Redirect *pRedir, Pgno iPg){ LsmPgno lsmFsRedirectPage(FileSystem *pFS, Redirect *pRedir, LsmPgno iPg){
Pgno iReal = iPg; LsmPgno iReal = iPg;
if( pRedir ){ if( pRedir ){
const int nPagePerBlock = ( const int nPagePerBlock = (
@@ -1203,7 +1203,7 @@ Pgno lsmFsRedirectPage(FileSystem *pFS, Redirect *pRedir, Pgno iPg){
if( iFrom>iBlk ) break; if( iFrom>iBlk ) break;
if( iFrom==iBlk ){ if( iFrom==iBlk ){
int iTo = pRedir->a[i].iTo; int iTo = pRedir->a[i].iTo;
iReal = iPg - (Pgno)(iFrom - iTo) * nPagePerBlock; iReal = iPg - (LsmPgno)(iFrom - iTo) * nPagePerBlock;
if( iTo==1 ){ if( iTo==1 ){
iReal += (fsFirstPageOnBlock(pFS, 1)-1); iReal += (fsFirstPageOnBlock(pFS, 1)-1);
} }
@@ -1217,7 +1217,7 @@ Pgno lsmFsRedirectPage(FileSystem *pFS, Redirect *pRedir, Pgno iPg){
} }
/* Required by the circular fsBlockNext<->fsPageGet dependency. */ /* Required by the circular fsBlockNext<->fsPageGet dependency. */
static int fsPageGet(FileSystem *, Segment *, Pgno, int, Page **, int *); static int fsPageGet(FileSystem *, Segment *, LsmPgno, int, Page **, int *);
/* /*
** Parameter iBlock is a database file block. This function reads the value ** Parameter iBlock is a database file block. This function reads the value
@@ -1269,7 +1269,7 @@ static int fsBlockNext(
/* /*
** Return the page number of the last page on the same block as page iPg. ** Return the page number of the last page on the same block as page iPg.
*/ */
Pgno fsLastPageOnPagesBlock(FileSystem *pFS, Pgno iPg){ LsmPgno fsLastPageOnPagesBlock(FileSystem *pFS, LsmPgno iPg){
return fsLastPageOnBlock(pFS, fsPageToBlock(pFS, iPg)); return fsLastPageOnBlock(pFS, fsPageToBlock(pFS, iPg));
} }
@@ -1537,7 +1537,7 @@ static int fsReadPagedata(
static int fsPageGet( static int fsPageGet(
FileSystem *pFS, /* File-system handle */ FileSystem *pFS, /* File-system handle */
Segment *pSeg, /* Block redirection to use (or NULL) */ Segment *pSeg, /* Block redirection to use (or NULL) */
Pgno iPg, /* Page id */ LsmPgno iPg, /* Page id */
int noContent, /* True to not load content from disk */ int noContent, /* True to not load content from disk */
Page **ppPg, /* OUT: New page handle */ Page **ppPg, /* OUT: New page handle */
int *pnSpace /* OUT: Bytes of free space */ int *pnSpace /* OUT: Bytes of free space */
@@ -1549,7 +1549,7 @@ static int fsPageGet(
/* In most cases iReal is the same as iPg. Except, if pSeg->pRedirect is /* In most cases iReal is the same as iPg. Except, if pSeg->pRedirect is
** not NULL, and the block containing iPg has been redirected, then iReal ** not NULL, and the block containing iPg has been redirected, then iReal
** is the page number after redirection. */ ** is the page number after redirection. */
Pgno iReal = lsmFsRedirectPage(pFS, (pSeg ? pSeg->pRedirect : 0), iPg); LsmPgno iReal = lsmFsRedirectPage(pFS, (pSeg ? pSeg->pRedirect : 0), iPg);
assert_lists_are_ok(pFS); assert_lists_are_ok(pFS);
assert( iPg>=fsFirstPageOnBlock(pFS, 1) ); assert( iPg>=fsFirstPageOnBlock(pFS, 1) );
@@ -1689,8 +1689,8 @@ int lsmFsReadSyncedId(lsm_db *db, int iMeta, i64 *piVal){
static int fsRunEndsBetween( static int fsRunEndsBetween(
Segment *pRun, Segment *pRun,
Segment *pIgnore, Segment *pIgnore,
Pgno iFirst, LsmPgno iFirst,
Pgno iLast LsmPgno iLast
){ ){
return (pRun!=pIgnore && ( return (pRun!=pIgnore && (
(pRun->iFirst>=iFirst && pRun->iFirst<=iLast) (pRun->iFirst>=iFirst && pRun->iFirst<=iLast)
@@ -1705,8 +1705,8 @@ static int fsRunEndsBetween(
static int fsLevelEndsBetween( static int fsLevelEndsBetween(
Level *pLevel, Level *pLevel,
Segment *pIgnore, Segment *pIgnore,
Pgno iFirst, LsmPgno iFirst,
Pgno iLast LsmPgno iLast
){ ){
int i; int i;
@@ -1733,13 +1733,13 @@ static int fsFreeBlock(
int iBlk /* Block number of block to free */ int iBlk /* Block number of block to free */
){ ){
int rc = LSM_OK; /* Return code */ int rc = LSM_OK; /* Return code */
Pgno iFirst; /* First page on block iBlk */ LsmPgno iFirst; /* First page on block iBlk */
Pgno iLast; /* Last page on block iBlk */ LsmPgno iLast; /* Last page on block iBlk */
Level *pLevel; /* Used to iterate through levels */ Level *pLevel; /* Used to iterate through levels */
int iIn; /* Used to iterate through append points */ int iIn; /* Used to iterate through append points */
int iOut = 0; /* Used to output append points */ int iOut = 0; /* Used to output append points */
Pgno *aApp = pSnapshot->aiAppend; LsmPgno *aApp = pSnapshot->aiAppend;
iFirst = fsFirstPageOnBlock(pFS, iBlk); iFirst = fsFirstPageOnBlock(pFS, iBlk);
iLast = fsLastPageOnBlock(pFS, iBlk); iLast = fsLastPageOnBlock(pFS, iBlk);
@@ -1811,11 +1811,16 @@ int lsmFsSortedDelete(
** number from the array that falls on block iBlk. Or, if none of the pages ** number from the array that falls on block iBlk. Or, if none of the pages
** in aPgno[] fall on block iBlk, return 0. ** in aPgno[] fall on block iBlk, return 0.
*/ */
static Pgno firstOnBlock(FileSystem *pFS, int iBlk, Pgno *aPgno, int nPgno){ static LsmPgno firstOnBlock(
Pgno iRet = 0; FileSystem *pFS,
int iBlk,
LsmPgno *aPgno,
int nPgno
){
LsmPgno iRet = 0;
int i; int i;
for(i=0; i<nPgno; i++){ for(i=0; i<nPgno; i++){
Pgno iPg = aPgno[i]; LsmPgno iPg = aPgno[i];
if( fsPageToBlock(pFS, iPg)==iBlk && (iRet==0 || iPg<iRet) ){ if( fsPageToBlock(pFS, iPg)==iBlk && (iRet==0 || iPg<iRet) ){
iRet = iPg; iRet = iPg;
} }
@@ -1828,7 +1833,7 @@ static Pgno firstOnBlock(FileSystem *pFS, int iBlk, Pgno *aPgno, int nPgno){
** Return true if page iPg, which is a part of segment p, lies on ** Return true if page iPg, which is a part of segment p, lies on
** a redirected block. ** a redirected block.
*/ */
static int fsPageRedirects(FileSystem *pFS, Segment *p, Pgno iPg){ static int fsPageRedirects(FileSystem *pFS, Segment *p, LsmPgno iPg){
return (iPg!=0 && iPg!=lsmFsRedirectPage(pFS, p->pRedirect, iPg)); return (iPg!=0 && iPg!=lsmFsRedirectPage(pFS, p->pRedirect, iPg));
} }
@@ -1854,7 +1859,7 @@ static int fsSegmentRedirects(FileSystem *pFS, Segment *p){
void lsmFsGobble( void lsmFsGobble(
lsm_db *pDb, lsm_db *pDb,
Segment *pRun, Segment *pRun,
Pgno *aPgno, LsmPgno *aPgno,
int nPgno int nPgno
){ ){
int rc = LSM_OK; int rc = LSM_OK;
@@ -1871,7 +1876,7 @@ void lsmFsGobble(
while( rc==LSM_OK ){ while( rc==LSM_OK ){
int iNext = 0; int iNext = 0;
Pgno iFirst = firstOnBlock(pFS, iBlk, aPgno, nPgno); LsmPgno iFirst = firstOnBlock(pFS, iBlk, aPgno, nPgno);
if( iFirst ){ if( iFirst ){
pRun->iFirst = iFirst; pRun->iFirst = iFirst;
break; break;
@@ -1905,11 +1910,11 @@ void lsmFsGobble(
static int fsNextPageOffset( static int fsNextPageOffset(
FileSystem *pFS, /* File system object */ FileSystem *pFS, /* File system object */
Segment *pSeg, /* Segment to move within */ Segment *pSeg, /* Segment to move within */
Pgno iPg, /* Offset of current page */ LsmPgno iPg, /* Offset of current page */
int nByte, /* Size of current page including headers */ int nByte, /* Size of current page including headers */
Pgno *piNext /* OUT: Offset of next page. Or zero (EOF) */ LsmPgno *piNext /* OUT: Offset of next page. Or zero (EOF) */
){ ){
Pgno iNext; LsmPgno iNext;
int rc; int rc;
assert( pFS->pCompress ); assert( pFS->pCompress );
@@ -1939,8 +1944,8 @@ static int fsNextPageOffset(
static int fsGetPageBefore( static int fsGetPageBefore(
FileSystem *pFS, FileSystem *pFS,
Segment *pSeg, Segment *pSeg,
Pgno iPg, LsmPgno iPg,
Pgno *piPrev LsmPgno *piPrev
){ ){
u8 aSz[3]; u8 aSz[3];
int rc; int rc;
@@ -1990,7 +1995,7 @@ static int fsGetPageBefore(
int lsmFsDbPageNext(Segment *pRun, Page *pPg, int eDir, Page **ppNext){ int lsmFsDbPageNext(Segment *pRun, Page *pPg, int eDir, Page **ppNext){
int rc = LSM_OK; int rc = LSM_OK;
FileSystem *pFS = pPg->pFS; FileSystem *pFS = pPg->pFS;
Pgno iPg = pPg->iPg; LsmPgno iPg = pPg->iPg;
assert( 0==fsSegmentRedirects(pFS, pRun) ); assert( 0==fsSegmentRedirects(pFS, pRun) );
if( pFS->pCompress ){ if( pFS->pCompress ){
@@ -2062,10 +2067,10 @@ int lsmFsDbPageNext(Segment *pRun, Page *pPg, int eDir, Page **ppNext){
** start the new segment immediately following any segment that is part ** start the new segment immediately following any segment that is part
** of the right-hand-side of pLvl. ** of the right-hand-side of pLvl.
*/ */
static Pgno findAppendPoint(FileSystem *pFS, Level *pLvl){ static LsmPgno findAppendPoint(FileSystem *pFS, Level *pLvl){
int i; int i;
Pgno *aiAppend = pFS->pDb->pWorker->aiAppend; LsmPgno *aiAppend = pFS->pDb->pWorker->aiAppend;
Pgno iRet = 0; LsmPgno iRet = 0;
for(i=LSM_APPLIST_SZ-1; iRet==0 && i>=0; i--){ for(i=LSM_APPLIST_SZ-1; iRet==0 && i>=0; i--){
if( (iRet = aiAppend[i]) ){ if( (iRet = aiAppend[i]) ){
@@ -2098,10 +2103,10 @@ int lsmFsSortedAppend(
){ ){
int rc = LSM_OK; int rc = LSM_OK;
Page *pPg = 0; Page *pPg = 0;
Pgno iApp = 0; LsmPgno iApp = 0;
Pgno iNext = 0; LsmPgno iNext = 0;
Segment *p = &pLvl->lhs; Segment *p = &pLvl->lhs;
Pgno iPrev = p->iLastPg; LsmPgno iPrev = p->iLastPg;
*ppOut = 0; *ppOut = 0;
assert( p->pRedirect==0 ); assert( p->pRedirect==0 );
@@ -2195,7 +2200,7 @@ int lsmFsSortedFinish(FileSystem *pFS, Segment *p){
*/ */
if( fsLastPageOnPagesBlock(pFS, p->iLastPg)!=p->iLastPg ){ if( fsLastPageOnPagesBlock(pFS, p->iLastPg)!=p->iLastPg ){
int i; int i;
Pgno *aiAppend = pFS->pDb->pWorker->aiAppend; LsmPgno *aiAppend = pFS->pDb->pWorker->aiAppend;
for(i=0; i<LSM_APPLIST_SZ; i++){ for(i=0; i<LSM_APPLIST_SZ; i++){
if( aiAppend[i]==0 ){ if( aiAppend[i]==0 ){
aiAppend[i] = p->iLastPg+1; aiAppend[i] = p->iLastPg+1;
@@ -2226,7 +2231,7 @@ int lsmFsSortedFinish(FileSystem *pFS, Segment *p){
** **
** Return LSM_OK if successful, or an lsm error code if an error occurs. ** Return LSM_OK if successful, or an lsm error code if an error occurs.
*/ */
int lsmFsDbPageGet(FileSystem *pFS, Segment *pSeg, Pgno iPg, Page **ppPg){ int lsmFsDbPageGet(FileSystem *pFS, Segment *pSeg, LsmPgno iPg, Page **ppPg){
return fsPageGet(pFS, pSeg, iPg, 0, ppPg, 0); return fsPageGet(pFS, pSeg, iPg, 0, ppPg, 0);
} }
@@ -2238,7 +2243,7 @@ int lsmFsDbPageGet(FileSystem *pFS, Segment *pSeg, Pgno iPg, Page **ppPg){
*/ */
int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg){ int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg){
int rc; int rc;
Pgno iPg = pSeg->iLastPg; LsmPgno iPg = pSeg->iLastPg;
if( pFS->pCompress ){ if( pFS->pCompress ){
int nSpace; int nSpace;
iPg++; iPg++;
@@ -2366,14 +2371,14 @@ static void fsMovePage(
FileSystem *pFS, /* File system object */ FileSystem *pFS, /* File system object */
int iTo, /* Destination block */ int iTo, /* Destination block */
int iFrom, /* Source block */ int iFrom, /* Source block */
Pgno *piPg /* IN/OUT: Page number */ LsmPgno *piPg /* IN/OUT: Page number */
){ ){
Pgno iPg = *piPg; LsmPgno iPg = *piPg;
if( iFrom==fsPageToBlock(pFS, iPg) ){ if( iFrom==fsPageToBlock(pFS, iPg) ){
const int nPagePerBlock = ( const int nPagePerBlock = (
pFS->pCompress ? pFS ->nBlocksize : (pFS->nBlocksize / pFS->nPagesize) pFS->pCompress ? pFS ->nBlocksize : (pFS->nBlocksize / pFS->nPagesize)
); );
*piPg = iPg - (Pgno)(iFrom - iTo) * nPagePerBlock; *piPg = iPg - (LsmPgno)(iFrom - iTo) * nPagePerBlock;
} }
} }
@@ -2457,21 +2462,21 @@ int lsmFsMoveBlock(FileSystem *pFS, Segment *pSeg, int iTo, int iFrom){
** **
** This function is only used in compressed database mode. ** This function is only used in compressed database mode.
*/ */
static Pgno fsAppendData( static LsmPgno fsAppendData(
FileSystem *pFS, /* File-system handle */ FileSystem *pFS, /* File-system handle */
Segment *pSeg, /* Segment to append to */ Segment *pSeg, /* Segment to append to */
const u8 *aData, /* Buffer containing data to write */ const u8 *aData, /* Buffer containing data to write */
int nData, /* Size of buffer aData[] in bytes */ int nData, /* Size of buffer aData[] in bytes */
int *pRc /* IN/OUT: Error code */ int *pRc /* IN/OUT: Error code */
){ ){
Pgno iRet = 0; LsmPgno iRet = 0;
int rc = *pRc; int rc = *pRc;
assert( pFS->pCompress ); assert( pFS->pCompress );
if( rc==LSM_OK ){ if( rc==LSM_OK ){
int nRem = 0; int nRem = 0;
int nWrite = 0; int nWrite = 0;
Pgno iLastOnBlock; LsmPgno iLastOnBlock;
Pgno iApp = pSeg->iLastPg+1; LsmPgno iApp = pSeg->iLastPg+1;
/* If this is the first data written into the segment, find an append-point /* If this is the first data written into the segment, find an append-point
** or allocate a new block. */ ** or allocate a new block. */
@@ -2519,7 +2524,7 @@ static Pgno fsAppendData(
/* Set the "prev" pointer on the new block */ /* Set the "prev" pointer on the new block */
if( rc==LSM_OK ){ if( rc==LSM_OK ){
Pgno iWrite; LsmPgno iWrite;
lsmPutU32(aPtr, fsPageToBlock(pFS, iApp)); lsmPutU32(aPtr, fsPageToBlock(pFS, iApp));
iWrite = fsFirstPageOnBlock(pFS, iBlk); iWrite = fsFirstPageOnBlock(pFS, iBlk);
rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iWrite-4, aPtr, sizeof(aPtr)); rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iWrite-4, aPtr, sizeof(aPtr));
@@ -2588,11 +2593,11 @@ static int fsCompressIntoBuffer(FileSystem *pFS, Page *pPg){
static int fsAppendPage( static int fsAppendPage(
FileSystem *pFS, FileSystem *pFS,
Segment *pSeg, Segment *pSeg,
Pgno *piNew, LsmPgno *piNew,
int *piPrev, int *piPrev,
int *piNext int *piNext
){ ){
Pgno iPrev = pSeg->iLastPg; LsmPgno iPrev = pSeg->iLastPg;
int rc; int rc;
assert( iPrev!=0 ); assert( iPrev!=0 );
@@ -2650,7 +2655,7 @@ void lsmFsFlushWaiting(FileSystem *pFS, int *pRc){
/* /*
** If there exists a hash-table entry associated with page iPg, remove it. ** If there exists a hash-table entry associated with page iPg, remove it.
*/ */
static void fsRemoveHashEntry(FileSystem *pFS, Pgno iPg){ static void fsRemoveHashEntry(FileSystem *pFS, LsmPgno iPg){
Page *p; Page *p;
int iHash = fsHashKey(pFS->nHash, iPg); int iHash = fsHashKey(pFS->nHash, iPg);
@@ -2804,8 +2809,8 @@ int lsmFsSortedPadding(
){ ){
int rc = LSM_OK; int rc = LSM_OK;
if( pFS->pCompress && pSeg->iFirst ){ if( pFS->pCompress && pSeg->iFirst ){
Pgno iLast2; LsmPgno iLast2;
Pgno iLast = pSeg->iLastPg; /* Current last page of segment */ LsmPgno iLast = pSeg->iLastPg; /* Current last page of segment */
int nPad; /* Bytes of padding required */ int nPad; /* Bytes of padding required */
u8 aSz[3]; u8 aSz[3];
@@ -2935,7 +2940,7 @@ int lsmFsSectorSize(FileSystem *pFS){
/* /*
** Helper function for lsmInfoArrayStructure(). ** Helper function for lsmInfoArrayStructure().
*/ */
static Segment *startsWith(Segment *pRun, Pgno iFirst){ static Segment *startsWith(Segment *pRun, LsmPgno iFirst){
return (iFirst==pRun->iFirst) ? pRun : 0; return (iFirst==pRun->iFirst) ? pRun : 0;
} }
@@ -2943,7 +2948,7 @@ static Segment *startsWith(Segment *pRun, Pgno iFirst){
** Return the segment that starts with page iFirst, if any. If no such segment ** Return the segment that starts with page iFirst, if any. If no such segment
** can be found, return NULL. ** can be found, return NULL.
*/ */
static Segment *findSegment(Snapshot *pWorker, Pgno iFirst){ static Segment *findSegment(Snapshot *pWorker, LsmPgno iFirst){
Level *pLvl; /* Used to iterate through db levels */ Level *pLvl; /* Used to iterate through db levels */
Segment *pSeg = 0; /* Pointer to segment to return */ Segment *pSeg = 0; /* Pointer to segment to return */
@@ -2970,7 +2975,7 @@ static Segment *findSegment(Snapshot *pWorker, Pgno iFirst){
int lsmInfoArrayStructure( int lsmInfoArrayStructure(
lsm_db *pDb, lsm_db *pDb,
int bBlock, /* True for block numbers only */ int bBlock, /* True for block numbers only */
Pgno iFirst, LsmPgno iFirst,
char **pzOut char **pzOut
){ ){
int rc = LSM_OK; int rc = LSM_OK;
@@ -3035,7 +3040,7 @@ int lsmInfoArrayStructure(
int lsmFsSegmentContainsPg( int lsmFsSegmentContainsPg(
FileSystem *pFS, FileSystem *pFS,
Segment *pSeg, Segment *pSeg,
Pgno iPg, LsmPgno iPg,
int *pbRes int *pbRes
){ ){
Redirect *pRedir = pSeg->pRedirect; Redirect *pRedir = pSeg->pRedirect;
@@ -3064,7 +3069,7 @@ int lsmFsSegmentContainsPg(
** **
** If an error occurs, *pzOut is set to NULL and an LSM error code returned. ** If an error occurs, *pzOut is set to NULL and an LSM error code returned.
*/ */
int lsmInfoArrayPages(lsm_db *pDb, Pgno iFirst, char **pzOut){ int lsmInfoArrayPages(lsm_db *pDb, LsmPgno iFirst, char **pzOut){
int rc = LSM_OK; int rc = LSM_OK;
Snapshot *pWorker; /* Worker snapshot */ Snapshot *pWorker; /* Worker snapshot */
Segment *pSeg = 0; /* Array to report on */ Segment *pSeg = 0; /* Array to report on */
@@ -3297,7 +3302,7 @@ int lsmFsIntegrityCheck(lsm_db *pDb){
*/ */
int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg){ int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg){
if( pPg->pFS->pCompress ){ if( pPg->pFS->pCompress ){
Pgno iNext = 0; LsmPgno iNext = 0;
int rc; int rc;
rc = fsNextPageOffset(pPg->pFS, pSeg, pPg->iPg, pPg->nCompress+6, &iNext); rc = fsNextPageOffset(pPg->pFS, pSeg, pPg->iPg, pPg->nCompress+6, &iNext);
return (rc!=LSM_OK || iNext==0); return (rc!=LSM_OK || iNext==0);

View File

@@ -583,14 +583,14 @@ int lsm_info(lsm_db *pDb, int eParam, ...){
} }
case LSM_INFO_ARRAY_STRUCTURE: { case LSM_INFO_ARRAY_STRUCTURE: {
Pgno pgno = va_arg(ap, Pgno); LsmPgno pgno = va_arg(ap, LsmPgno);
char **pzVal = va_arg(ap, char **); char **pzVal = va_arg(ap, char **);
rc = lsmInfoArrayStructure(pDb, 0, pgno, pzVal); rc = lsmInfoArrayStructure(pDb, 0, pgno, pzVal);
break; break;
} }
case LSM_INFO_ARRAY_PAGES: { case LSM_INFO_ARRAY_PAGES: {
Pgno pgno = va_arg(ap, Pgno); LsmPgno pgno = va_arg(ap, LsmPgno);
char **pzVal = va_arg(ap, char **); char **pzVal = va_arg(ap, char **);
rc = lsmInfoArrayPages(pDb, pgno, pzVal); rc = lsmInfoArrayPages(pDb, pgno, pzVal);
break; break;
@@ -598,7 +598,7 @@ int lsm_info(lsm_db *pDb, int eParam, ...){
case LSM_INFO_PAGE_HEX_DUMP: case LSM_INFO_PAGE_HEX_DUMP:
case LSM_INFO_PAGE_ASCII_DUMP: { case LSM_INFO_PAGE_ASCII_DUMP: {
Pgno pgno = va_arg(ap, Pgno); LsmPgno pgno = va_arg(ap, LsmPgno);
char **pzVal = va_arg(ap, char **); char **pzVal = va_arg(ap, char **);
int bUnlock = 0; int bUnlock = 0;
rc = infoGetWorker(pDb, 0, &bUnlock); rc = infoGetWorker(pDb, 0, &bUnlock);

View File

@@ -104,9 +104,9 @@
#endif #endif
typedef struct SegmentPtr SegmentPtr; typedef struct SegmentPtr SegmentPtr;
typedef struct Blob Blob; typedef struct LsmBlob LsmBlob;
struct Blob { struct LsmBlob {
lsm_env *pEnv; lsm_env *pEnv;
void *pData; void *pData;
int nData; int nData;
@@ -129,18 +129,18 @@ struct SegmentPtr {
Page *pPg; /* Current page */ Page *pPg; /* Current page */
u16 flags; /* Copy of page flags field */ u16 flags; /* Copy of page flags field */
int nCell; /* Number of cells on pPg */ int nCell; /* Number of cells on pPg */
Pgno iPtr; /* Base cascade pointer */ LsmPgno iPtr; /* Base cascade pointer */
/* Current cell. See segmentPtrLoadCell() */ /* Current cell. See segmentPtrLoadCell() */
int iCell; /* Current record within page pPg */ int iCell; /* Current record within page pPg */
int eType; /* Type of current record */ int eType; /* Type of current record */
Pgno iPgPtr; /* Cascade pointer offset */ LsmPgno iPgPtr; /* Cascade pointer offset */
void *pKey; int nKey; /* Key associated with current record */ void *pKey; int nKey; /* Key associated with current record */
void *pVal; int nVal; /* Current record value (eType==WRITE only) */ void *pVal; int nVal; /* Current record value (eType==WRITE only) */
/* Blobs used to allocate buffers for pKey and pVal as required */ /* Blobs used to allocate buffers for pKey and pVal as required */
Blob blob1; LsmBlob blob1;
Blob blob2; LsmBlob blob2;
}; };
/* /*
@@ -171,10 +171,10 @@ struct BtreeCursor {
void *pKey; void *pKey;
int nKey; int nKey;
int eType; int eType;
Pgno iPtr; LsmPgno iPtr;
/* Storage for key, if not local */ /* Storage for key, if not local */
Blob blob; LsmBlob blob;
}; };
@@ -203,8 +203,8 @@ struct MultiCursor {
int flags; /* Mask of CURSOR_XXX flags */ int flags; /* Mask of CURSOR_XXX flags */
int eType; /* Cache of current key type */ int eType; /* Cache of current key type */
Blob key; /* Cache of current key (or NULL) */ LsmBlob key; /* Cache of current key (or NULL) */
Blob val; /* Cache of current value */ LsmBlob val; /* Cache of current value */
/* All the component cursors: */ /* All the component cursors: */
TreeCursor *apTreeCsr[2]; /* Up to two tree cursors */ TreeCursor *apTreeCsr[2]; /* Up to two tree cursors */
@@ -221,7 +221,7 @@ struct MultiCursor {
void *pSystemVal; /* Pointer to buffer to free */ void *pSystemVal; /* Pointer to buffer to free */
/* Used by worker cursors only */ /* Used by worker cursors only */
Pgno *pPrevMergePtr; LsmPgno *pPrevMergePtr;
}; };
/* /*
@@ -295,11 +295,11 @@ struct MergeWorker {
Hierarchy hier; /* B-tree hierarchy under construction */ Hierarchy hier; /* B-tree hierarchy under construction */
Page *pPage; /* Current output page */ Page *pPage; /* Current output page */
int nWork; /* Number of calls to mergeWorkerNextPage() */ int nWork; /* Number of calls to mergeWorkerNextPage() */
Pgno *aGobble; /* Gobble point for each input segment */ LsmPgno *aGobble; /* Gobble point for each input segment */
Pgno iIndirect; LsmPgno iIndirect;
struct SavedPgno { struct SavedPgno {
Pgno iPgno; LsmPgno iPgno;
int bStore; int bStore;
} aSave[2]; } aSave[2];
}; };
@@ -371,7 +371,7 @@ void lsmPutU64(u8 *aOut, u64 nVal){
aOut[7] = (u8)((nVal ) & 0xFF); aOut[7] = (u8)((nVal ) & 0xFF);
} }
static int sortedBlobGrow(lsm_env *pEnv, Blob *pBlob, int nData){ static int sortedBlobGrow(lsm_env *pEnv, LsmBlob *pBlob, int nData){
assert( pBlob->pEnv==pEnv || (pBlob->pEnv==0 && pBlob->pData==0) ); assert( pBlob->pEnv==pEnv || (pBlob->pEnv==0 && pBlob->pData==0) );
if( pBlob->nAlloc<nData ){ if( pBlob->nAlloc<nData ){
pBlob->pData = lsmReallocOrFree(pEnv, pBlob->pData, nData); pBlob->pData = lsmReallocOrFree(pEnv, pBlob->pData, nData);
@@ -382,7 +382,7 @@ static int sortedBlobGrow(lsm_env *pEnv, Blob *pBlob, int nData){
return LSM_OK; return LSM_OK;
} }
static int sortedBlobSet(lsm_env *pEnv, Blob *pBlob, void *pData, int nData){ static int sortedBlobSet(lsm_env *pEnv, LsmBlob *pBlob, void *pData, int nData){
if( sortedBlobGrow(pEnv, pBlob, nData) ) return LSM_NOMEM; if( sortedBlobGrow(pEnv, pBlob, nData) ) return LSM_NOMEM;
memcpy(pBlob->pData, pData, nData); memcpy(pBlob->pData, pData, nData);
pBlob->nData = nData; pBlob->nData = nData;
@@ -390,15 +390,15 @@ static int sortedBlobSet(lsm_env *pEnv, Blob *pBlob, void *pData, int nData){
} }
#if 0 #if 0
static int sortedBlobCopy(Blob *pDest, Blob *pSrc){ static int sortedBlobCopy(LsmBlob *pDest, LsmBlob *pSrc){
return sortedBlobSet(pDest, pSrc->pData, pSrc->nData); return sortedBlobSet(pDest, pSrc->pData, pSrc->nData);
} }
#endif #endif
static void sortedBlobFree(Blob *pBlob){ static void sortedBlobFree(LsmBlob *pBlob){
assert( pBlob->pEnv || pBlob->pData==0 ); assert( pBlob->pEnv || pBlob->pData==0 );
if( pBlob->pData ) lsmFree(pBlob->pEnv, pBlob->pData); if( pBlob->pData ) lsmFree(pBlob->pEnv, pBlob->pData);
memset(pBlob, 0, sizeof(Blob)); memset(pBlob, 0, sizeof(LsmBlob));
} }
static int sortedReadData( static int sortedReadData(
@@ -407,7 +407,7 @@ static int sortedReadData(
int iOff, int iOff,
int nByte, int nByte,
void **ppData, void **ppData,
Blob *pBlob LsmBlob *pBlob
){ ){
int rc = LSM_OK; int rc = LSM_OK;
int iEnd; int iEnd;
@@ -481,8 +481,8 @@ static int pageGetNRec(u8 *aData, int nData){
return (int)lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]); return (int)lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
} }
static Pgno pageGetPtr(u8 *aData, int nData){ static LsmPgno pageGetPtr(u8 *aData, int nData){
return (Pgno)lsmGetU64(&aData[SEGMENT_POINTER_OFFSET(nData)]); return (LsmPgno)lsmGetU64(&aData[SEGMENT_POINTER_OFFSET(nData)]);
} }
static int pageGetFlags(u8 *aData, int nData){ static int pageGetFlags(u8 *aData, int nData){
@@ -506,8 +506,8 @@ static int pageObjGetNRec(Page *pPg){
** Return the decoded (possibly relative) pointer value stored in cell ** Return the decoded (possibly relative) pointer value stored in cell
** iCell from page aData/nData. ** iCell from page aData/nData.
*/ */
static Pgno pageGetRecordPtr(u8 *aData, int nData, int iCell){ static LsmPgno pageGetRecordPtr(u8 *aData, int nData, int iCell){
Pgno iRet; /* Return value */ LsmPgno iRet; /* Return value */
u8 *aCell; /* Pointer to cell iCell */ u8 *aCell; /* Pointer to cell iCell */
assert( iCell<pageGetNRec(aData, nData) && iCell>=0 ); assert( iCell<pageGetNRec(aData, nData) && iCell>=0 );
@@ -522,7 +522,7 @@ static u8 *pageGetKey(
int iCell, /* Index of cell on page to read */ int iCell, /* Index of cell on page to read */
int *piTopic, /* OUT: Topic associated with this key */ int *piTopic, /* OUT: Topic associated with this key */
int *pnKey, /* OUT: Size of key in bytes */ int *pnKey, /* OUT: Size of key in bytes */
Blob *pBlob /* If required, use this for dynamic memory */ LsmBlob *pBlob /* If required, use this for dynamic memory */
){ ){
u8 *pKey; u8 *pKey;
int nDummy; int nDummy;
@@ -554,7 +554,7 @@ static int pageGetKeyCopy(
Page *pPg, /* Page to read from */ Page *pPg, /* Page to read from */
int iCell, /* Index of cell on page to read */ int iCell, /* Index of cell on page to read */
int *piTopic, /* OUT: Topic associated with this key */ int *piTopic, /* OUT: Topic associated with this key */
Blob *pBlob /* If required, use this for dynamic memory */ LsmBlob *pBlob /* If required, use this for dynamic memory */
){ ){
int rc = LSM_OK; int rc = LSM_OK;
int nKey; int nKey;
@@ -569,8 +569,8 @@ static int pageGetKeyCopy(
return rc; return rc;
} }
static Pgno pageGetBtreeRef(Page *pPg, int iKey){ static LsmPgno pageGetBtreeRef(Page *pPg, int iKey){
Pgno iRef; LsmPgno iRef;
u8 *aData; u8 *aData;
int nData; int nData;
u8 *aCell; u8 *aCell;
@@ -592,11 +592,11 @@ static int pageGetBtreeKey(
Segment *pSeg, /* Segment page pPg belongs to */ Segment *pSeg, /* Segment page pPg belongs to */
Page *pPg, Page *pPg,
int iKey, int iKey,
Pgno *piPtr, LsmPgno *piPtr,
int *piTopic, int *piTopic,
void **ppKey, void **ppKey,
int *pnKey, int *pnKey,
Blob *pBlob LsmBlob *pBlob
){ ){
u8 *aData; u8 *aData;
int nData; int nData;
@@ -613,7 +613,7 @@ static int pageGetBtreeKey(
if( eType==0 ){ if( eType==0 ){
int rc; int rc;
Pgno iRef; /* Page number of referenced page */ LsmPgno iRef; /* Page number of referenced page */
Page *pRef; Page *pRef;
aCell += GETVARINT64(aCell, iRef); aCell += GETVARINT64(aCell, iRef);
rc = lsmFsDbPageGet(lsmPageFS(pPg), pSeg, iRef, &pRef); rc = lsmFsDbPageGet(lsmPageFS(pPg), pSeg, iRef, &pRef);
@@ -638,7 +638,7 @@ static int btreeCursorLoadKey(BtreeCursor *pCsr){
pCsr->nKey = 0; pCsr->nKey = 0;
pCsr->eType = 0; pCsr->eType = 0;
}else{ }else{
Pgno dummy; LsmPgno dummy;
int iPg = pCsr->iPg; int iPg = pCsr->iPg;
int iCell = pCsr->aPg[iPg].iCell; int iCell = pCsr->aPg[iPg].iCell;
while( iCell<0 && (--iPg)>=0 ){ while( iCell<0 && (--iPg)>=0 ){
@@ -683,7 +683,7 @@ static int btreeCursorNext(BtreeCursor *pCsr){
assert( pPg->iCell<=nCell ); assert( pPg->iCell<=nCell );
pPg->iCell++; pPg->iCell++;
if( pPg->iCell==nCell ){ if( pPg->iCell==nCell ){
Pgno iLoad; LsmPgno iLoad;
/* Up to parent. */ /* Up to parent. */
lsmFsPageRelease(pPg->pPage); lsmFsPageRelease(pPg->pPage);
@@ -842,7 +842,7 @@ static int btreeCursorRestore(
if( p->iPg ){ if( p->iPg ){
lsm_env *pEnv = lsmFsEnv(pCsr->pFS); lsm_env *pEnv = lsmFsEnv(pCsr->pFS);
int iCell; /* Current cell number on leaf page */ int iCell; /* Current cell number on leaf page */
Pgno iLeaf; /* Page number of current leaf page */ LsmPgno iLeaf; /* Page number of current leaf page */
int nDepth; /* Depth of b-tree structure */ int nDepth; /* Depth of b-tree structure */
Segment *pSeg = pCsr->pSeg; Segment *pSeg = pCsr->pSeg;
@@ -866,7 +866,7 @@ static int btreeCursorRestore(
/* Populate any other aPg[] array entries */ /* Populate any other aPg[] array entries */
if( rc==LSM_OK && nDepth>1 ){ if( rc==LSM_OK && nDepth>1 ){
Blob blob = {0,0,0}; LsmBlob blob = {0,0,0};
void *pSeek; void *pSeek;
int nSeek; int nSeek;
int iTopicSeek; int iTopicSeek;
@@ -883,7 +883,7 @@ static int btreeCursorRestore(
pSeek = 0; pSeek = 0;
nSeek = 0; nSeek = 0;
}else{ }else{
Pgno dummy; LsmPgno dummy;
rc = pageGetBtreeKey(pSeg, pPg, rc = pageGetBtreeKey(pSeg, pPg,
0, &dummy, &iTopicSeek, &pSeek, &nSeek, &pCsr->blob 0, &dummy, &iTopicSeek, &pSeek, &nSeek, &pCsr->blob
); );
@@ -912,7 +912,7 @@ static int btreeCursorRestore(
int iTry = (iMin+iMax)/2; int iTry = (iMin+iMax)/2;
void *pKey; int nKey; /* Key for cell iTry */ void *pKey; int nKey; /* Key for cell iTry */
int iTopic; /* Topic for key pKeyT/nKeyT */ int iTopic; /* Topic for key pKeyT/nKeyT */
Pgno iPtr; /* Pointer for cell iTry */ LsmPgno iPtr; /* Pointer for cell iTry */
int res; /* (pSeek - pKeyT) */ int res; /* (pSeek - pKeyT) */
rc = pageGetBtreeKey( rc = pageGetBtreeKey(
@@ -955,7 +955,7 @@ static int btreeCursorRestore(
aData = fsPageData(pBtreePg->pPage, &nData); aData = fsPageData(pBtreePg->pPage, &nData);
pCsr->iPtr = btreeCursorPtr(aData, nData, pBtreePg->iCell+1); pCsr->iPtr = btreeCursorPtr(aData, nData, pBtreePg->iCell+1);
if( pBtreePg->iCell<0 ){ if( pBtreePg->iCell<0 ){
Pgno dummy; LsmPgno dummy;
int i; int i;
for(i=pCsr->iPg-1; i>=0; i--){ for(i=pCsr->iPg-1; i>=0; i--){
if( pCsr->aPg[i].iCell>0 ) break; if( pCsr->aPg[i].iCell>0 ) break;
@@ -1030,7 +1030,7 @@ static int segmentPtrReadData(
int iOff, int iOff,
int nByte, int nByte,
void **ppData, void **ppData,
Blob *pBlob LsmBlob *pBlob
){ ){
return sortedReadData(pPtr->pSeg, pPtr->pPg, iOff, nByte, ppData, pBlob); return sortedReadData(pPtr->pSeg, pPtr->pPg, iOff, nByte, ppData, pBlob);
} }
@@ -1123,7 +1123,7 @@ static void sortedSplitkey(lsm_db *pDb, Level *pLevel, int *pRc){
} }
if( rc==LSM_OK ){ if( rc==LSM_OK ){
int iTopic; int iTopic;
Blob blob = {0, 0, 0, 0}; LsmBlob blob = {0, 0, 0, 0};
u8 *aData; u8 *aData;
int nData; int nData;
@@ -1131,7 +1131,7 @@ static void sortedSplitkey(lsm_db *pDb, Level *pLevel, int *pRc){
if( pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG ){ if( pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG ){
void *pKey; void *pKey;
int nKey; int nKey;
Pgno dummy; LsmPgno dummy;
rc = pageGetBtreeKey(pSeg, rc = pageGetBtreeKey(pSeg,
pPg, pMerge->splitkey.iCell, &dummy, &iTopic, &pKey, &nKey, &blob pPg, pMerge->splitkey.iCell, &dummy, &iTopic, &pKey, &nKey, &blob
); );
@@ -1342,7 +1342,7 @@ static int assertKeyLocation(
void *pKey, int nKey void *pKey, int nKey
){ ){
lsm_env *pEnv = lsmFsEnv(pCsr->pDb->pFS); lsm_env *pEnv = lsmFsEnv(pCsr->pDb->pFS);
Blob blob = {0, 0, 0}; LsmBlob blob = {0, 0, 0};
int eDir; int eDir;
int iTopic = 0; /* TODO: Fix me */ int iTopic = 0; /* TODO: Fix me */
@@ -1488,7 +1488,7 @@ static int ptrFwdPointer(
Page *pPage, Page *pPage,
int iCell, int iCell,
Segment *pSeg, Segment *pSeg,
Pgno *piPtr, LsmPgno *piPtr,
int *pbFound int *pbFound
){ ){
Page *pPg = pPage; Page *pPg = pPage;
@@ -1573,14 +1573,14 @@ static int sortedRhsFirst(MultiCursor *pCsr, Level *pLvl, SegmentPtr *pPtr){
static int segmentPtrFwdPointer( static int segmentPtrFwdPointer(
MultiCursor *pCsr, /* Multi-cursor pPtr belongs to */ MultiCursor *pCsr, /* Multi-cursor pPtr belongs to */
SegmentPtr *pPtr, /* Segment-pointer to extract FC ptr from */ SegmentPtr *pPtr, /* Segment-pointer to extract FC ptr from */
Pgno *piPtr /* OUT: FC pointer value */ LsmPgno *piPtr /* OUT: FC pointer value */
){ ){
Level *pLvl = pPtr->pLevel; Level *pLvl = pPtr->pLevel;
Level *pNext = pLvl->pNext; Level *pNext = pLvl->pNext;
Page *pPg = pPtr->pPg; Page *pPg = pPtr->pPg;
int rc; int rc;
int bFound; int bFound;
Pgno iOut = 0; LsmPgno iOut = 0;
if( pPtr->pSeg==&pLvl->lhs || pPtr->pSeg==&pLvl->aRhs[pLvl->nRight-1] ){ if( pPtr->pSeg==&pLvl->lhs || pPtr->pSeg==&pLvl->aRhs[pLvl->nRight-1] ){
if( pNext==0 if( pNext==0
@@ -1641,7 +1641,7 @@ static int segmentPtrSeek(
int rc = LSM_OK; int rc = LSM_OK;
int iMin; int iMin;
int iMax; int iMax;
Pgno iPtrOut = 0; LsmPgno iPtrOut = 0;
/* If the current page contains an oversized entry, then there are no /* If the current page contains an oversized entry, then there are no
** pointers to one or more of the subsequent pages in the sorted run. ** pointers to one or more of the subsequent pages in the sorted run.
@@ -1768,18 +1768,18 @@ static int seekInBtree(
Segment *pSeg, /* Seek within this segment */ Segment *pSeg, /* Seek within this segment */
int iTopic, int iTopic,
void *pKey, int nKey, /* Key to seek to */ void *pKey, int nKey, /* Key to seek to */
Pgno *aPg, /* OUT: Page numbers */ LsmPgno *aPg, /* OUT: Page numbers */
Page **ppPg /* OUT: Leaf (sorted-run) page reference */ Page **ppPg /* OUT: Leaf (sorted-run) page reference */
){ ){
int i = 0; int i = 0;
int rc; int rc;
int iPg; int iPg;
Page *pPg = 0; Page *pPg = 0;
Blob blob = {0, 0, 0}; LsmBlob blob = {0, 0, 0};
iPg = (int)pSeg->iRoot; iPg = (int)pSeg->iRoot;
do { do {
Pgno *piFirst = 0; LsmPgno *piFirst = 0;
if( aPg ){ if( aPg ){
aPg[i++] = iPg; aPg[i++] = iPg;
piFirst = &aPg[i]; piFirst = &aPg[i];
@@ -1808,7 +1808,7 @@ static int seekInBtree(
int iTry = (iMin+iMax)/2; int iTry = (iMin+iMax)/2;
void *pKeyT; int nKeyT; /* Key for cell iTry */ void *pKeyT; int nKeyT; /* Key for cell iTry */
int iTopicT; /* Topic for key pKeyT/nKeyT */ int iTopicT; /* Topic for key pKeyT/nKeyT */
Pgno iPtr; /* Pointer associated with cell iTry */ LsmPgno iPtr; /* Pointer associated with cell iTry */
int res; /* (pKey - pKeyT) */ int res; /* (pKey - pKeyT) */
rc = pageGetBtreeKey( rc = pageGetBtreeKey(
@@ -1899,7 +1899,7 @@ static int seekInLevel(
int eSeek, /* Search bias - see above */ int eSeek, /* Search bias - see above */
int iTopic, /* Key topic to search for */ int iTopic, /* Key topic to search for */
void *pKey, int nKey, /* Key to search for */ void *pKey, int nKey, /* Key to search for */
Pgno *piPgno, /* IN/OUT: fraction cascade pointer (or 0) */ LsmPgno *piPgno, /* IN/OUT: fraction cascade pointer (or 0) */
int *pbStop /* OUT: See above */ int *pbStop /* OUT: See above */
){ ){
Level *pLvl = aPtr[0].pLevel; /* Level to seek within */ Level *pLvl = aPtr[0].pLevel; /* Level to seek within */
@@ -3055,7 +3055,7 @@ int lsmMCursorSeek(
int bStop = 0; /* Set to true to halt search operation */ int bStop = 0; /* Set to true to halt search operation */
int rc = LSM_OK; /* Return code */ int rc = LSM_OK; /* Return code */
int iPtr = 0; /* Used to iterate through pCsr->aPtr[] */ int iPtr = 0; /* Used to iterate through pCsr->aPtr[] */
Pgno iPgno = 0; /* FC pointer value */ LsmPgno iPgno = 0; /* FC pointer value */
assert( pCsr->apTreeCsr[0]==0 || iTopic==0 ); assert( pCsr->apTreeCsr[0]==0 || iTopic==0 );
assert( pCsr->apTreeCsr[1]==0 || iTopic==0 ); assert( pCsr->apTreeCsr[1]==0 || iTopic==0 );
@@ -3537,7 +3537,7 @@ static int mergeWorkerLoadHierarchy(MergeWorker *pMW){
** + Type byte (always SORTED_SEPARATOR or SORTED_SYSTEM_SEPARATOR), ** + Type byte (always SORTED_SEPARATOR or SORTED_SYSTEM_SEPARATOR),
** + Absolute pointer value (varint), ** + Absolute pointer value (varint),
** + Number of bytes in key (varint), ** + Number of bytes in key (varint),
** + Blob containing key data. ** + LsmBlob containing key data.
** **
** 2. All pointer values are stored as absolute values (not offsets ** 2. All pointer values are stored as absolute values (not offsets
** relative to the footer pointer value). ** relative to the footer pointer value).
@@ -3571,8 +3571,8 @@ static int mergeWorkerLoadHierarchy(MergeWorker *pMW){
static int mergeWorkerBtreeWrite( static int mergeWorkerBtreeWrite(
MergeWorker *pMW, MergeWorker *pMW,
u8 eType, u8 eType,
Pgno iPtr, LsmPgno iPtr,
Pgno iKeyPg, LsmPgno iKeyPg,
void *pKey, void *pKey,
int nKey int nKey
){ ){
@@ -3682,7 +3682,7 @@ static int mergeWorkerBtreeWrite(
static int mergeWorkerBtreeIndirect(MergeWorker *pMW){ static int mergeWorkerBtreeIndirect(MergeWorker *pMW){
int rc = LSM_OK; int rc = LSM_OK;
if( pMW->iIndirect ){ if( pMW->iIndirect ){
Pgno iKeyPg = pMW->aSave[1].iPgno; LsmPgno iKeyPg = pMW->aSave[1].iPgno;
rc = mergeWorkerBtreeWrite(pMW, 0, pMW->iIndirect, iKeyPg, 0, 0); rc = mergeWorkerBtreeWrite(pMW, 0, pMW->iIndirect, iKeyPg, 0, 0);
pMW->iIndirect = 0; pMW->iIndirect = 0;
} }
@@ -3703,7 +3703,7 @@ static int mergeWorkerPushHierarchy(
int nKey /* Size of pKey buffer in bytes */ int nKey /* Size of pKey buffer in bytes */
){ ){
int rc = LSM_OK; /* Return Code */ int rc = LSM_OK; /* Return Code */
Pgno iPtr; /* Pointer value to accompany pKey/nKey */ LsmPgno iPtr; /* Pointer value to accompany pKey/nKey */
assert( pMW->aSave[0].bStore==0 ); assert( pMW->aSave[0].bStore==0 );
assert( pMW->aSave[1].bStore==0 ); assert( pMW->aSave[1].bStore==0 );
@@ -3734,7 +3734,7 @@ static int mergeWorkerFinishHierarchy(
){ ){
int i; /* Used to loop through apHier[] */ int i; /* Used to loop through apHier[] */
int rc = LSM_OK; /* Return code */ int rc = LSM_OK; /* Return code */
Pgno iPtr; /* New right-hand-child pointer value */ LsmPgno iPtr; /* New right-hand-child pointer value */
iPtr = pMW->aSave[0].iPgno; iPtr = pMW->aSave[0].iPgno;
for(i=0; i<pMW->hier.nHier && rc==LSM_OK; i++){ for(i=0; i<pMW->hier.nHier && rc==LSM_OK; i++){
@@ -3830,7 +3830,7 @@ static int mergeWorkerPersistAndRelease(MergeWorker *pMW){
*/ */
static int mergeWorkerNextPage( static int mergeWorkerNextPage(
MergeWorker *pMW, /* Merge worker object to append page to */ MergeWorker *pMW, /* Merge worker object to append page to */
Pgno iFPtr /* Pointer value for footer of new page */ LsmPgno iFPtr /* Pointer value for footer of new page */
){ ){
int rc = LSM_OK; /* Return code */ int rc = LSM_OK; /* Return code */
Page *pNext = 0; /* New page appended to run */ Page *pNext = 0; /* New page appended to run */
@@ -4218,7 +4218,7 @@ static int mergeWorkerStep(MergeWorker *pMW){
int rc = LSM_OK; /* Return code */ int rc = LSM_OK; /* Return code */
int eType; /* SORTED_SEPARATOR, WRITE or DELETE */ int eType; /* SORTED_SEPARATOR, WRITE or DELETE */
void *pKey; int nKey; /* Key */ void *pKey; int nKey; /* Key */
Pgno iPtr; LsmPgno iPtr;
int iVal; int iVal;
pCsr = pMW->pCsr; pCsr = pMW->pCsr;
@@ -4371,7 +4371,7 @@ static int sortedNewToplevel(
if( rc!=LSM_OK ){ if( rc!=LSM_OK ){
lsmMCursorClose(pCsr, 0); lsmMCursorClose(pCsr, 0);
}else{ }else{
Pgno iLeftPtr = 0; LsmPgno iLeftPtr = 0;
Merge merge; /* Merge object used to create new level */ Merge merge; /* Merge object used to create new level */
MergeWorker mergeworker; /* MergeWorker object for the same purpose */ MergeWorker mergeworker; /* MergeWorker object for the same purpose */
@@ -4548,7 +4548,7 @@ static int mergeWorkerInit(
memset(pMW, 0, sizeof(MergeWorker)); memset(pMW, 0, sizeof(MergeWorker));
pMW->pDb = pDb; pMW->pDb = pDb;
pMW->pLevel = pLevel; pMW->pLevel = pLevel;
pMW->aGobble = lsmMallocZeroRc(pDb->pEnv, sizeof(Pgno) * pLevel->nRight, &rc); pMW->aGobble = lsmMallocZeroRc(pDb->pEnv, sizeof(LsmPgno)*pLevel->nRight,&rc);
/* Create a multi-cursor to read the data to write to the new /* Create a multi-cursor to read the data to write to the new
** segment. The new segment contains: ** segment. The new segment contains:
@@ -4630,7 +4630,7 @@ static int sortedBtreeGobble(
int rc = LSM_OK; int rc = LSM_OK;
if( rtTopic(pCsr->eType)==0 ){ if( rtTopic(pCsr->eType)==0 ){
Segment *pSeg = pCsr->aPtr[iGobble].pSeg; Segment *pSeg = pCsr->aPtr[iGobble].pSeg;
Pgno *aPg; LsmPgno *aPg;
int nPg; int nPg;
/* Seek from the root of the b-tree to the segment leaf that may contain /* Seek from the root of the b-tree to the segment leaf that may contain
@@ -4639,7 +4639,7 @@ static int sortedBtreeGobble(
** gobbled up to (but not including) the first of these page numbers. ** gobbled up to (but not including) the first of these page numbers.
*/ */
assert( pSeg->iRoot>0 ); assert( pSeg->iRoot>0 );
aPg = lsmMallocZeroRc(pDb->pEnv, sizeof(Pgno)*32, &rc); aPg = lsmMallocZeroRc(pDb->pEnv, sizeof(LsmPgno)*32, &rc);
if( rc==LSM_OK ){ if( rc==LSM_OK ){
rc = seekInBtree(pCsr, pSeg, rc = seekInBtree(pCsr, pSeg,
rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData, aPg, 0 rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData, aPg, 0
@@ -5466,9 +5466,9 @@ int lsmFlushTreeToDisk(lsm_db *pDb){
*/ */
static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){ static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){
int nSize = pSeg->nSize; int nSize = pSeg->nSize;
Pgno iRoot = pSeg->iRoot; LsmPgno iRoot = pSeg->iRoot;
Pgno iFirst = pSeg->iFirst; LsmPgno iFirst = pSeg->iFirst;
Pgno iLast = pSeg->iLastPg; LsmPgno iLast = pSeg->iLastPg;
char *z; char *z;
char *z1; char *z1;
@@ -5527,7 +5527,7 @@ static int fileToString(
} }
void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){ void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
Blob blob = {0, 0, 0}; /* Blob used for keys */ LsmBlob blob = {0, 0, 0}; /* LsmBlob used for keys */
LsmString s; LsmString s;
int i; int i;
@@ -5563,7 +5563,7 @@ void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
aCell += lsmVarintGet32(aCell, &iPgPtr); aCell += lsmVarintGet32(aCell, &iPgPtr);
if( eType==0 ){ if( eType==0 ){
Pgno iRef; /* Page number of referenced page */ LsmPgno iRef; /* Page number of referenced page */
aCell += lsmVarintGet64(aCell, &iRef); aCell += lsmVarintGet64(aCell, &iRef);
lsmFsDbPageGet(pDb->pFS, pRun, iRef, &pRef); lsmFsDbPageGet(pDb->pFS, pRun, iRef, &pRef);
aKey = pageGetKey(pRun, pRef, 0, &iTopic, &nKey, &blob); aKey = pageGetKey(pRun, pRef, 0, &iTopic, &nKey, &blob);
@@ -5607,7 +5607,7 @@ static void infoCellDump(
int *piPgPtr, int *piPgPtr,
u8 **paKey, int *pnKey, u8 **paKey, int *pnKey,
u8 **paVal, int *pnVal, u8 **paVal, int *pnVal,
Blob *pBlob LsmBlob *pBlob
){ ){
u8 *aData; int nData; /* Page data */ u8 *aData; int nData; /* Page data */
u8 *aKey; int nKey = 0; /* Key */ u8 *aKey; int nKey = 0; /* Key */
@@ -5625,7 +5625,7 @@ static void infoCellDump(
if( eType==0 ){ if( eType==0 ){
int dummy; int dummy;
Pgno iRef; /* Page number of referenced page */ LsmPgno iRef; /* Page number of referenced page */
aCell += lsmVarintGet64(aCell, &iRef); aCell += lsmVarintGet64(aCell, &iRef);
if( bIndirect ){ if( bIndirect ){
lsmFsDbPageGet(pDb->pFS, pSeg, iRef, &pRef); lsmFsDbPageGet(pDb->pFS, pSeg, iRef, &pRef);
@@ -5671,7 +5671,7 @@ static int infoAppendBlob(LsmString *pStr, int bHex, u8 *z, int n){
static int infoPageDump( static int infoPageDump(
lsm_db *pDb, /* Database handle */ lsm_db *pDb, /* Database handle */
Pgno iPg, /* Page number of page to dump */ LsmPgno iPg, /* Page number of page to dump */
int flags, int flags,
char **pzOut /* OUT: lsmMalloc'd string */ char **pzOut /* OUT: lsmMalloc'd string */
){ ){
@@ -5712,7 +5712,7 @@ static int infoPageDump(
} }
if( rc==LSM_OK ){ if( rc==LSM_OK ){
Blob blob = {0, 0, 0, 0}; LsmBlob blob = {0, 0, 0, 0};
int nKeyWidth = 0; int nKeyWidth = 0;
LsmString str; LsmString str;
int nRec; int nRec;
@@ -5747,7 +5747,7 @@ static int infoPageDump(
u8 *aVal; int nVal = 0; /* Value */ u8 *aVal; int nVal = 0; /* Value */
int iPgPtr; int iPgPtr;
int eType; int eType;
Pgno iAbsPtr; LsmPgno iAbsPtr;
char zFlags[8]; char zFlags[8];
infoCellDump(pDb, pSeg, bIndirect, pPg, iCell, &eType, &iPgPtr, infoCellDump(pDb, pSeg, bIndirect, pPg, iCell, &eType, &iPgPtr,
@@ -5813,7 +5813,7 @@ static int infoPageDump(
int lsmInfoPageDump( int lsmInfoPageDump(
lsm_db *pDb, /* Database handle */ lsm_db *pDb, /* Database handle */
Pgno iPg, /* Page number of page to dump */ LsmPgno iPg, /* Page number of page to dump */
int bHex, /* True to output key/value in hex form */ int bHex, /* True to output key/value in hex form */
char **pzOut /* OUT: lsmMalloc'd string */ char **pzOut /* OUT: lsmMalloc'd string */
){ ){
@@ -5989,8 +5989,8 @@ void lsmSortedExpandBtreePage(Page *pPg, int nOrig){
#ifdef LSM_DEBUG_EXPENSIVE #ifdef LSM_DEBUG_EXPENSIVE
static void assertRunInOrder(lsm_db *pDb, Segment *pSeg){ static void assertRunInOrder(lsm_db *pDb, Segment *pSeg){
Page *pPg = 0; Page *pPg = 0;
Blob blob1 = {0, 0, 0, 0}; LsmBlob blob1 = {0, 0, 0, 0};
Blob blob2 = {0, 0, 0, 0}; LsmBlob blob2 = {0, 0, 0, 0};
lsmFsDbPageGet(pDb->pFS, pSeg, pSeg->iFirst, &pPg); lsmFsDbPageGet(pDb->pFS, pSeg, pSeg->iFirst, &pPg);
while( pPg ){ while( pPg ){
@@ -6052,7 +6052,7 @@ static int assertPointersOk(
int rc = LSM_OK; /* Error code */ int rc = LSM_OK; /* Error code */
SegmentPtr ptr1; /* Iterates through pOne */ SegmentPtr ptr1; /* Iterates through pOne */
SegmentPtr ptr2; /* Iterates through pTwo */ SegmentPtr ptr2; /* Iterates through pTwo */
Pgno iPrev; LsmPgno iPrev;
assert( pOne && pTwo ); assert( pOne && pTwo );
@@ -6075,7 +6075,7 @@ static int assertPointersOk(
} }
while( rc==LSM_OK && ptr2.pPg ){ while( rc==LSM_OK && ptr2.pPg ){
Pgno iThis; LsmPgno iThis;
/* Advance to the next page of segment pTwo that contains at least /* Advance to the next page of segment pTwo that contains at least
** one cell. Break out of the loop if the iterator reaches EOF. */ ** one cell. Break out of the loop if the iterator reaches EOF. */
@@ -6137,7 +6137,7 @@ static int assertBtreeOk(
){ ){
int rc = LSM_OK; /* Return code */ int rc = LSM_OK; /* Return code */
if( pSeg->iRoot ){ if( pSeg->iRoot ){
Blob blob = {0, 0, 0}; /* Buffer used to cache overflow keys */ LsmBlob blob = {0, 0, 0}; /* Buffer used to cache overflow keys */
FileSystem *pFS = pDb->pFS; /* File system to read from */ FileSystem *pFS = pDb->pFS; /* File system to read from */
Page *pPg = 0; /* Main run page */ Page *pPg = 0; /* Main run page */
BtreeCursor *pCsr = 0; /* Btree cursor */ BtreeCursor *pCsr = 0; /* Btree cursor */

88
ext/lsm1/tool/mklsm1c.tcl Normal file
View File

@@ -0,0 +1,88 @@
#!/bin/sh
# restart with tclsh \
exec tclsh "$0" "$@"
set srcdir [file dirname [file dirname [info script]]]
set G(src) [string map [list %dir% $srcdir] {
%dir%/lsm.h
%dir%/lsmInt.h
%dir%/lsm_vtab.c
%dir%/lsm_ckpt.c
%dir%/lsm_file.c
%dir%/lsm_log.c
%dir%/lsm_main.c
%dir%/lsm_mem.c
%dir%/lsm_mutex.c
%dir%/lsm_shared.c
%dir%/lsm_sorted.c
%dir%/lsm_str.c
%dir%/lsm_tree.c
%dir%/lsm_unix.c
%dir%/lsm_varint.c
%dir%/lsm_win32.c
}]
set G(hdr) {
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_LSM1)
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
# undef NDEBUG
#endif
}
set G(footer) {
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_LSM1) */
}
#-------------------------------------------------------------------------
# Read and return the entire contents of text file $zFile from disk.
#
proc readfile {zFile} {
set fd [open $zFile]
set data [read $fd]
close $fd
return $data
}
proc lsm1c_init {zOut} {
global G
set G(fd) stdout
set G(fd) [open $zOut w]
puts -nonewline $G(fd) $G(hdr)
}
proc lsm1c_printfile {zIn} {
global G
set data [readfile $zIn]
set zTail [file tail $zIn]
puts $G(fd) "#line 1 \"$zTail\""
foreach line [split $data "\n"] {
if {[regexp {^# *include.*lsm} $line]} {
set line "/* $line */"
} elseif { [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?lsm[^_]} $line] } {
set line "static $line"
}
puts $G(fd) $line
}
}
proc lsm1c_close {} {
global G
puts -nonewline $G(fd) $G(footer)
if {$G(fd)!="stdout"} {
close $G(fd)
}
}
lsm1c_init lsm1.c
foreach f $G(src) { lsm1c_printfile $f }
lsm1c_close

View File

@@ -47,9 +47,9 @@ static void rot13func(
const unsigned char *zIn; const unsigned char *zIn;
int nIn; int nIn;
unsigned char *zOut; unsigned char *zOut;
char *zToFree = 0; unsigned char *zToFree = 0;
int i; int i;
char zTemp[100]; unsigned char zTemp[100];
assert( argc==1 ); assert( argc==1 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
zIn = (const unsigned char*)sqlite3_value_text(argv[0]); zIn = (const unsigned char*)sqlite3_value_text(argv[0]);
@@ -57,7 +57,7 @@ static void rot13func(
if( nIn<sizeof(zTemp)-1 ){ if( nIn<sizeof(zTemp)-1 ){
zOut = zTemp; zOut = zTemp;
}else{ }else{
zOut = zToFree = sqlite3_malloc( nIn+1 ); zOut = zToFree = (unsigned char*)sqlite3_malloc64( nIn+1 );
if( zOut==0 ){ if( zOut==0 ){
sqlite3_result_error_nomem(context); sqlite3_result_error_nomem(context);
return; return;

View File

@@ -56,6 +56,8 @@
** **
** SWARMVTAB ** SWARMVTAB
** **
** LEGACY SYNTAX:
**
** A "swarmvtab" virtual table is created similarly to a unionvtab table: ** A "swarmvtab" virtual table is created similarly to a unionvtab table:
** **
** CREATE VIRTUAL TABLE <name> ** CREATE VIRTUAL TABLE <name>
@@ -66,13 +68,78 @@
** the database file containing the source table. The <callback> option ** the database file containing the source table. The <callback> option
** is optional. If included, it is the name of an application-defined ** is optional. If included, it is the name of an application-defined
** SQL function that is invoked with the URI of the file, if the file ** SQL function that is invoked with the URI of the file, if the file
** does not already exist on disk. ** does not already exist on disk when required by swarmvtab.
**
** NEW SYNTAX:
**
** Using the new syntax, a swarmvtab table is created with:
**
** CREATE VIRTUAL TABLE <name> USING swarmvtab(
** <sql-statement> [, <options>]
** );
**
** where valid <options> are:
**
** missing=<udf-function-name>
** openclose=<udf-function-name>
** maxopen=<integer>
** <sql-parameter>=<text-value>
**
** The <sql-statement> must return the same 4 columns as for a swarmvtab
** table in legacy mode. However, it may also return a 5th column - the
** "context" column. The text value returned in this column is not used
** at all by the swarmvtab implementation, except that it is passed as
** an additional argument to the two UDF functions that may be invoked
** (see below).
**
** The "missing" option, if present, specifies the name of an SQL UDF
** function to be invoked if a database file is not already present on
** disk when required by swarmvtab. If the <sql-statement> did not provide
** a context column, it is invoked as:
**
** SELECT <missing-udf>(<database filename/uri>);
**
** Or, if there was a context column:
**
** SELECT <missing-udf>(<database filename/uri>, <context>);
**
** The "openclose" option may also specify a UDF function. This function
** is invoked right before swarmvtab opens a database, and right after
** it closes one. The first argument - or first two arguments, if
** <sql-statement> supplied the context column - is the same as for
** the "missing" UDF. Following this, the UDF is passed integer value
** 0 before a db is opened, and 1 right after it is closed. If both
** a missing and openclose UDF is supplied, the application should expect
** the following sequence of calls (for a single database):
**
** SELECT <openclose-udf>(<db filename>, <context>, 0);
** if( db not already on disk ){
** SELECT <missing-udf>(<db filename>, <context>);
** }
** ... swarmvtab uses database ...
** SELECT <openclose-udf>(<db filename>, <context>, 1);
**
** The "maxopen" option is used to configure the maximum number of
** database files swarmvtab will hold open simultaneously (default 9).
**
** If an option name begins with a ":" character, then it is assumed
** to be an SQL parameter. In this case, the specified text value is
** bound to the same variable of the <sql-statement> before it is
** executed. It is an error of the named SQL parameter does not exist.
** For example:
**
** CREATE VIRTUAL TABLE swarm USING swarmvtab(
** 'SELECT :path || localfile, tbl, min, max FROM swarmdir',
** :path='/home/user/databases/'
** missing='missing_func'
** );
*/ */
#include "sqlite3ext.h" #include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1 SQLITE_EXTENSION_INIT1
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -128,6 +195,7 @@ struct UnionSrc {
/* Fields used by swarmvtab only */ /* Fields used by swarmvtab only */
char *zFile; /* Database file containing table zTab */ char *zFile; /* Database file containing table zTab */
char *zContext; /* Context string, if any */
int nUser; /* Current number of users */ int nUser; /* Current number of users */
sqlite3 *db; /* Database handle */ sqlite3 *db; /* Database handle */
UnionSrc *pNextClosable; /* Next in list of closable sources */ UnionSrc *pNextClosable; /* Next in list of closable sources */
@@ -145,8 +213,11 @@ struct UnionTab {
UnionSrc *aSrc; /* Array of source tables, sorted by rowid */ UnionSrc *aSrc; /* Array of source tables, sorted by rowid */
/* Used by swarmvtab only */ /* Used by swarmvtab only */
int bHasContext; /* Has context strings */
char *zSourceStr; /* Expected unionSourceToStr() value */ char *zSourceStr; /* Expected unionSourceToStr() value */
char *zNotFoundCallback; /* UDF to invoke if file not found on open */ sqlite3_stmt *pNotFound; /* UDF to invoke if file not found on open */
sqlite3_stmt *pOpenClose; /* UDF to invoke on open and close */
UnionSrc *pClosable; /* First in list of closable sources */ UnionSrc *pClosable; /* First in list of closable sources */
int nOpen; /* Current number of open sources */ int nOpen; /* Current number of open sources */
int nMaxOpen; /* Maximum number of open sources */ int nMaxOpen; /* Maximum number of open sources */
@@ -351,6 +422,39 @@ static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
} }
} }
/*
** If an "openclose" UDF was supplied when this virtual table was created,
** invoke it now. The first argument passed is the name of the database
** file for source pSrc. The second is integer value bClose.
**
** If successful, return SQLITE_OK. Otherwise an SQLite error code. In this
** case if argument pzErr is not NULL, also set (*pzErr) to an English
** language error message. The caller is responsible for eventually freeing
** any error message using sqlite3_free().
*/
static int unionInvokeOpenClose(
UnionTab *pTab,
UnionSrc *pSrc,
int bClose,
char **pzErr
){
int rc = SQLITE_OK;
if( pTab->pOpenClose ){
sqlite3_bind_text(pTab->pOpenClose, 1, pSrc->zFile, -1, SQLITE_STATIC);
if( pTab->bHasContext ){
sqlite3_bind_text(pTab->pOpenClose, 2, pSrc->zContext, -1, SQLITE_STATIC);
}
sqlite3_bind_int(pTab->pOpenClose, 2+pTab->bHasContext, bClose);
sqlite3_step(pTab->pOpenClose);
if( SQLITE_OK!=(rc = sqlite3_reset(pTab->pOpenClose)) ){
if( pzErr ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
}
}
}
return rc;
}
/* /*
** This function is a no-op for unionvtab. For swarmvtab, it attempts to ** This function is a no-op for unionvtab. For swarmvtab, it attempts to
** close open database files until at most nMax are open. An SQLite error ** close open database files until at most nMax are open. An SQLite error
@@ -358,13 +462,16 @@ static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
*/ */
static void unionCloseSources(UnionTab *pTab, int nMax){ static void unionCloseSources(UnionTab *pTab, int nMax){
while( pTab->pClosable && pTab->nOpen>nMax ){ while( pTab->pClosable && pTab->nOpen>nMax ){
UnionSrc *p;
UnionSrc **pp; UnionSrc **pp;
for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable); for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable);
assert( (*pp)->db ); p = *pp;
sqlite3_close((*pp)->db); assert( p->db );
(*pp)->db = 0; sqlite3_close(p->db);
p->db = 0;
*pp = 0; *pp = 0;
pTab->nOpen--; pTab->nOpen--;
unionInvokeOpenClose(pTab, p, 1, 0);
} }
} }
@@ -377,13 +484,18 @@ static int unionDisconnect(sqlite3_vtab *pVtab){
int i; int i;
for(i=0; i<pTab->nSrc; i++){ for(i=0; i<pTab->nSrc; i++){
UnionSrc *pSrc = &pTab->aSrc[i]; UnionSrc *pSrc = &pTab->aSrc[i];
if( pSrc->db ){
unionInvokeOpenClose(pTab, pSrc, 1, 0);
}
sqlite3_free(pSrc->zDb); sqlite3_free(pSrc->zDb);
sqlite3_free(pSrc->zTab); sqlite3_free(pSrc->zTab);
sqlite3_free(pSrc->zFile); sqlite3_free(pSrc->zFile);
sqlite3_free(pSrc->zContext);
sqlite3_close(pSrc->db); sqlite3_close(pSrc->db);
} }
sqlite3_finalize(pTab->pNotFound);
sqlite3_finalize(pTab->pOpenClose);
sqlite3_free(pTab->zSourceStr); sqlite3_free(pTab->zSourceStr);
sqlite3_free(pTab->zNotFoundCallback);
sqlite3_free(pTab->aSrc); sqlite3_free(pTab->aSrc);
sqlite3_free(pTab); sqlite3_free(pTab);
} }
@@ -496,29 +608,31 @@ static int unionSourceCheck(UnionTab *pTab, char **pzErr){
return rc; return rc;
} }
/* /*
** Try to open the swarmvtab database. If initially unable, invoke the ** Try to open the swarmvtab database. If initially unable, invoke the
** not-found callback UDF and then try again. ** not-found callback UDF and then try again.
*/ */
static int unionOpenDatabaseInner(UnionTab *pTab, UnionSrc *pSrc, char **pzErr){ static int unionOpenDatabaseInner(UnionTab *pTab, UnionSrc *pSrc, char **pzErr){
int rc = SQLITE_OK; static const int openFlags = SQLITE_OPEN_READONLY | SQLITE_OPEN_URI;
static const int openFlags = int rc;
SQLITE_OPEN_READONLY | SQLITE_OPEN_URI;
rc = unionInvokeOpenClose(pTab, pSrc, 0, pzErr);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0); rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
if( rc==SQLITE_OK ) return rc; if( rc==SQLITE_OK ) return rc;
if( pTab->zNotFoundCallback ){ if( pTab->pNotFound ){
char *zSql = sqlite3_mprintf("SELECT \"%w\"(%Q);",
pTab->zNotFoundCallback, pSrc->zFile);
sqlite3_close(pSrc->db); sqlite3_close(pSrc->db);
pSrc->db = 0; pSrc->db = 0;
if( zSql==0 ){ sqlite3_bind_text(pTab->pNotFound, 1, pSrc->zFile, -1, SQLITE_STATIC);
*pzErr = sqlite3_mprintf("out of memory"); if( pTab->bHasContext ){
return SQLITE_NOMEM; sqlite3_bind_text(pTab->pNotFound, 2, pSrc->zContext, -1, SQLITE_STATIC);
}
sqlite3_step(pTab->pNotFound);
if( SQLITE_OK!=(rc = sqlite3_reset(pTab->pNotFound)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
return rc;
} }
rc = sqlite3_exec(pTab->db, zSql, 0, 0, pzErr);
sqlite3_free(zSql);
if( rc ) return rc;
rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0); rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
} }
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
@@ -572,6 +686,7 @@ static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){
}else{ }else{
sqlite3_close(pSrc->db); sqlite3_close(pSrc->db);
pSrc->db = 0; pSrc->db = 0;
unionInvokeOpenClose(pTab, pSrc, 1, 0);
} }
} }
@@ -627,6 +742,132 @@ static int unionFinalizeCsrStmt(UnionCsr *pCsr){
return rc; return rc;
} }
/*
** Return true if the argument is a space, tab, CR or LF character.
*/
static int union_isspace(char c){
return (c==' ' || c=='\n' || c=='\r' || c=='\t');
}
/*
** Return true if the argument is an alphanumeric character in the
** ASCII range.
*/
static int union_isidchar(char c){
return ((c>='a' && c<='z') || (c>='A' && c<'Z') || (c>='0' && c<='9'));
}
/*
** This function is called to handle all arguments following the first
** (the SQL statement) passed to a swarmvtab (not unionvtab) CREATE
** VIRTUAL TABLE statement. It may bind parameters to the SQL statement
** or configure members of the UnionTab object passed as the second
** argument.
**
** Refer to header comments at the top of this file for a description
** of the arguments parsed.
**
** This function is a no-op if *pRc is other than SQLITE_OK when it is
** called. Otherwise, if an error occurs, *pRc is set to an SQLite error
** code. In this case *pzErr may be set to point to a buffer containing
** an English language error message. It is the responsibility of the
** caller to eventually free the buffer using sqlite3_free().
*/
static void unionConfigureVtab(
int *pRc, /* IN/OUT: Error code */
UnionTab *pTab, /* Table to configure */
sqlite3_stmt *pStmt, /* SQL statement to find sources */
int nArg, /* Number of entries in azArg[] array */
const char * const *azArg, /* Array of arguments to consider */
char **pzErr /* OUT: Error message */
){
int rc = *pRc;
int i;
if( rc==SQLITE_OK ){
pTab->bHasContext = (sqlite3_column_count(pStmt)>4);
}
for(i=0; rc==SQLITE_OK && i<nArg; i++){
char *zArg = unionStrdup(&rc, azArg[i]);
if( zArg ){
int nOpt = 0; /* Size of option name in bytes */
char *zOpt; /* Pointer to option name */
char *zVal; /* Pointer to value */
unionDequote(zArg);
zOpt = zArg;
while( union_isspace(*zOpt) ) zOpt++;
zVal = zOpt;
if( *zVal==':' ) zVal++;
while( union_isidchar(*zVal) ) zVal++;
nOpt = zVal-zOpt;
while( union_isspace(*zVal) ) zVal++;
if( *zVal=='=' ){
zOpt[nOpt] = '\0';
zVal++;
while( union_isspace(*zVal) ) zVal++;
zVal = unionStrdup(&rc, zVal);
if( zVal ){
unionDequote(zVal);
if( zOpt[0]==':' ){
/* A value to bind to the SQL statement */
int iParam = sqlite3_bind_parameter_index(pStmt, zOpt);
if( iParam==0 ){
*pzErr = sqlite3_mprintf(
"swarmvtab: no such SQL parameter: %s", zOpt
);
rc = SQLITE_ERROR;
}else{
rc = sqlite3_bind_text(pStmt, iParam, zVal, -1, SQLITE_TRANSIENT);
}
}else if( nOpt==7 && 0==sqlite3_strnicmp(zOpt, "maxopen", 7) ){
pTab->nMaxOpen = atoi(zVal);
if( pTab->nMaxOpen<=0 ){
*pzErr = sqlite3_mprintf("swarmvtab: illegal maxopen value");
rc = SQLITE_ERROR;
}
}else if( nOpt==7 && 0==sqlite3_strnicmp(zOpt, "missing", 7) ){
if( pTab->pNotFound ){
*pzErr = sqlite3_mprintf(
"swarmvtab: duplicate \"missing\" option");
rc = SQLITE_ERROR;
}else{
pTab->pNotFound = unionPreparePrintf(&rc, pzErr, pTab->db,
"SELECT \"%w\"(?%s)", zVal, pTab->bHasContext ? ",?" : ""
);
}
}else if( nOpt==9 && 0==sqlite3_strnicmp(zOpt, "openclose", 9) ){
if( pTab->pOpenClose ){
*pzErr = sqlite3_mprintf(
"swarmvtab: duplicate \"openclose\" option");
rc = SQLITE_ERROR;
}else{
pTab->pOpenClose = unionPreparePrintf(&rc, pzErr, pTab->db,
"SELECT \"%w\"(?,?%s)", zVal, pTab->bHasContext ? ",?" : ""
);
}
}else{
*pzErr = sqlite3_mprintf("swarmvtab: unrecognized option: %s",zOpt);
rc = SQLITE_ERROR;
}
sqlite3_free(zVal);
}
}else{
if( i==0 && nArg==1 ){
pTab->pNotFound = unionPreparePrintf(&rc, pzErr, pTab->db,
"SELECT \"%w\"(?)", zArg
);
}else{
*pzErr = sqlite3_mprintf( "swarmvtab: parse error: %s", azArg[i]);
rc = SQLITE_ERROR;
}
}
sqlite3_free(zArg);
}
}
*pRc = rc;
}
/* /*
** xConnect/xCreate method. ** xConnect/xCreate method.
** **
@@ -654,7 +895,7 @@ static int unionConnect(
/* unionvtab tables may only be created in the temp schema */ /* unionvtab tables may only be created in the temp schema */
*pzErr = sqlite3_mprintf("%s tables must be created in TEMP schema", zVtab); *pzErr = sqlite3_mprintf("%s tables must be created in TEMP schema", zVtab);
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
}else if( argc!=4 && argc!=5 ){ }else if( argc<4 || (argc>4 && bSwarm==0) ){
*pzErr = sqlite3_mprintf("wrong number of arguments for %s", zVtab); *pzErr = sqlite3_mprintf("wrong number of arguments for %s", zVtab);
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
}else{ }else{
@@ -673,6 +914,17 @@ static int unionConnect(
/* Allocate the UnionTab structure */ /* Allocate the UnionTab structure */
pTab = unionMalloc(&rc, sizeof(UnionTab)); pTab = unionMalloc(&rc, sizeof(UnionTab));
if( pTab ){
assert( rc==SQLITE_OK );
pTab->db = db;
pTab->bSwarm = bSwarm;
pTab->nMaxOpen = SWARMVTAB_MAX_OPEN;
}
/* Parse other CVT arguments, if any */
if( bSwarm ){
unionConfigureVtab(&rc, pTab, pStmt, argc-4, &argv[4], pzErr);
}
/* Iterate through the rows returned by the SQL statement specified /* Iterate through the rows returned by the SQL statement specified
** as an argument to the CREATE VIRTUAL TABLE statement. */ ** as an argument to the CREATE VIRTUAL TABLE statement. */
@@ -715,17 +967,15 @@ static int unionConnect(
}else{ }else{
pSrc->zDb = unionStrdup(&rc, zDb); pSrc->zDb = unionStrdup(&rc, zDb);
} }
if( pTab->bHasContext ){
const char *zContext = (const char*)sqlite3_column_text(pStmt, 4);
pSrc->zContext = unionStrdup(&rc, zContext);
}
} }
} }
unionFinalize(&rc, pStmt, pzErr); unionFinalize(&rc, pStmt, pzErr);
pStmt = 0; pStmt = 0;
/* Capture the not-found callback UDF name */
if( rc==SQLITE_OK && argc>=5 ){
pTab->zNotFoundCallback = unionStrdup(&rc, argv[4]);
unionDequote(pTab->zNotFoundCallback);
}
/* It is an error if the SELECT statement returned zero rows. If only /* It is an error if the SELECT statement returned zero rows. If only
** because there is no way to determine the schema of the virtual ** because there is no way to determine the schema of the virtual
** table in this case. */ ** table in this case. */
@@ -738,9 +988,6 @@ static int unionConnect(
** compatible schemas. For swarmvtab, attach the first database and ** compatible schemas. For swarmvtab, attach the first database and
** check that the first table is a rowid table only. */ ** check that the first table is a rowid table only. */
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pTab->db = db;
pTab->bSwarm = bSwarm;
pTab->nMaxOpen = SWARMVTAB_MAX_OPEN;
if( bSwarm ){ if( bSwarm ){
rc = unionOpenDatabase(pTab, 0, pzErr); rc = unionOpenDatabase(pTab, 0, pzErr);
}else{ }else{

View File

@@ -2021,7 +2021,7 @@ static int ChooseLeaf(
){ ){
int rc; int rc;
int ii; int ii;
RtreeNode *pNode; RtreeNode *pNode = 0;
rc = nodeAcquire(pRtree, 1, 0, &pNode); rc = nodeAcquire(pRtree, 1, 0, &pNode);
for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
@@ -2896,7 +2896,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
*/ */
if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
int rc2; int rc2;
RtreeNode *pChild; RtreeNode *pChild = 0;
i64 iChild = nodeGetRowid(pRtree, pRoot, 0); i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){

23
main.mk
View File

@@ -263,6 +263,24 @@ FTS5_SRC = \
$(TOP)/ext/fts5/fts5_varint.c \ $(TOP)/ext/fts5/fts5_varint.c \
$(TOP)/ext/fts5/fts5_vocab.c \ $(TOP)/ext/fts5/fts5_vocab.c \
LSM1_SRC = \
$(TOP)/ext/lsm1/lsm.h \
$(TOP)/ext/lsm1/lsmInt.h \
$(TOP)/ext/lsm1/lsm_ckpt.c \
$(TOP)/ext/lsm1/lsm_file.c \
$(TOP)/ext/lsm1/lsm_log.c \
$(TOP)/ext/lsm1/lsm_main.c \
$(TOP)/ext/lsm1/lsm_mem.c \
$(TOP)/ext/lsm1/lsm_mutex.c \
$(TOP)/ext/lsm1/lsm_shared.c \
$(TOP)/ext/lsm1/lsm_sorted.c \
$(TOP)/ext/lsm1/lsm_str.c \
$(TOP)/ext/lsm1/lsm_tree.c \
$(TOP)/ext/lsm1/lsm_unix.c \
$(TOP)/ext/lsm1/lsm_varint.c \
$(TOP)/ext/lsm1/lsm_vtab.c \
$(TOP)/ext/lsm1/lsm_win32.c
# Generated source code files # Generated source code files
# #
@@ -768,6 +786,10 @@ fts5.c: $(FTS5_SRC) $(FTS5_HDR)
tclsh $(TOP)/ext/fts5/tool/mkfts5c.tcl tclsh $(TOP)/ext/fts5/tool/mkfts5c.tcl
cp $(TOP)/ext/fts5/fts5.h . cp $(TOP)/ext/fts5/fts5.h .
lsm1.c: $(LSM1_SRC)
tclsh $(TOP)/ext/lsm1/tool/mklsm1c.tcl
cp $(TOP)/ext/lsm1/lsm.h .
userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR) userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
@@ -1025,3 +1047,4 @@ clean:
rm -f fuzzcheck fuzzcheck.exe rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe rm -f sqldiff sqldiff.exe
rm -f fts5.* fts5parse.* rm -f fts5.* fts5parse.*
rm -f lsm.h lsm1.c

View File

@@ -1,9 +1,9 @@
C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
D 2017-11-29T16:16:29.774 D 2017-12-16T19:16:24.821
F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc f1aae0644cac286c1fcf5d7acbf6451c1e1d02e31131aa7c7c4536472771351f F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69
F README.md f5c87359573c4d255425e588a56554b50fdcc2afba4e017a2e02a43701456afd F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681
F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
@@ -111,7 +111,7 @@ F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bf
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c 01048018d21524e2c302b063ff5c3cdcf546e03297215e577205d85b47499deb F ext/fts5/fts5_expr.c 01048018d21524e2c302b063ff5c3cdcf546e03297215e577205d85b47499deb
F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55 F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
F ext/fts5/fts5_index.c 2ce9d50ec5508b8205615aad69e1c9b2c77f017f21d4479e1fb2079c01fdd017 F ext/fts5/fts5_index.c 5fe14375a29e8a7aa8f3e863babe180a19269206c254c8f47b216821d4ac1e15
F ext/fts5/fts5_main.c 24868f88ab2a865defbba7a92eebeb726cc991eb092b71b5f5508f180c72605b F ext/fts5/fts5_main.c 24868f88ab2a865defbba7a92eebeb726cc991eb092b71b5f5508f180c72605b
F ext/fts5/fts5_storage.c fb5ef3c27073f67ade2e1bea08405f9e43f68f5f3676ed0ab7013bce5ba10be6 F ext/fts5/fts5_storage.c fb5ef3c27073f67ade2e1bea08405f9e43f68f5f3676ed0ab7013bce5ba10be6
F ext/fts5/fts5_tcl.c a7df39442ae674dde877cf06fe02ebb7658e69c179a4d223241c90df4f14b54e F ext/fts5/fts5_tcl.c a7df39442ae674dde877cf06fe02ebb7658e69c179a4d223241c90df4f14b54e
@@ -189,7 +189,7 @@ F ext/fts5/test/fts5plan.test e30e8378441114ef6977a3dc24ecd203caa670d782124dfc9a
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15 F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457 F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056 F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
F ext/fts5/test/fts5query.test bdb6fd9e73268cfc07f789f1448cd71ea78acb02e481c619f286289ea18ca518 F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
F ext/fts5/test/fts5rank.test 6e149da77a269923a8439aaa52366e49b85be4721902662da39a5ded16ed85d9 F ext/fts5/test/fts5rank.test 6e149da77a269923a8439aaa52366e49b85be4721902662da39a5ded16ed85d9
F ext/fts5/test/fts5rebuild.test 6d09fd54b1170a1e54fe17b808bbf17fba3154956cc2f065dd94bf1e3d254f63 F ext/fts5/test/fts5rebuild.test 6d09fd54b1170a1e54fe17b808bbf17fba3154956cc2f065dd94bf1e3d254f63
F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415 F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
@@ -216,7 +216,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 635775226d07c743c770888a9dd5175afc6e67d3e28a4032b7fedc3bcaa92e65 F ext/icu/icu.c c2c7592574c08cd1270d909b8fb8797f6ea1f49e931e71dbcc25506b9b224580
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013 F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
@@ -245,15 +245,15 @@ F ext/lsm1/lsm-test/lsmtest_tdb4.c 47e8bb5eba266472d690fb8264f1855ebdba0ae5a0e54
F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806 F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806
F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d
F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001 F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001
F ext/lsm1/lsmInt.h e9e5c5f08e35a104086102b3def94ee69cbc0d39002f6596f5c80a640439628e F ext/lsm1/lsmInt.h 5983690e05e83653cc01ba9d8fbf8455e534ddf8349ed9adedbf46a7549760b0
F ext/lsm1/lsm_ckpt.c ac6fb4581983291c2e0be6fbb68f12b26f0c08d606835c05417be1323d0fdd03 F ext/lsm1/lsm_ckpt.c 0eabfaf812ddb4ea43add38f05e430694cd054eb622c3e35af4c43118a2d5321
F ext/lsm1/lsm_file.c 4b3fb56336fbc9d941e1b2042e809d986feebdc41e73dc7fc4fdc0dd1bd4274d F ext/lsm1/lsm_file.c 3c51841d5b3e7da162693cbac9a9f47eeedf6bcbbe2969a4d25e30c428c9fe36
F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709d9a7c F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709d9a7c
F ext/lsm1/lsm_main.c 15e73ccdafdd44ddeefc29e332079d88ba8f00c12c797b3c2b63d3171b5afce8 F ext/lsm1/lsm_main.c 801295038b548ae2e5fae93f08c3f945154f40848a03ff26b16eab5d04ba573a
F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a
F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea
F ext/lsm1/lsm_shared.c 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2aadf1c525 F ext/lsm1/lsm_shared.c 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2aadf1c525
F ext/lsm1/lsm_sorted.c 8f899fb64a4c736ff3c27d5126c7ce181129ddffde947fe5fb657a7a413f470b F ext/lsm1/lsm_sorted.c d07ff7c28758542b8b4da4b5a1fb67b22a4d33e50e7f684cffe1f6c45cf5182c
F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82 F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b
@@ -262,6 +262,7 @@ F ext/lsm1/lsm_vtab.c 529255dc704289001b225d97e57e0cfa14b29c3f281c7349cfa8fdb655
F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c
F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82 F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82
F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422 F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422
F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2 F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87 F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
@@ -283,7 +284,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4 F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
F ext/misc/series.c f3c0dba5c5c749ce1782b53076108f87cf0b71041eb6023f727a9c50681da564 F ext/misc/series.c f3c0dba5c5c749ce1782b53076108f87cf0b71041eb6023f727a9c50681da564
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56 F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
@@ -292,7 +293,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 41cf26c6b89fcaa8798ae10ae64d39c1f1d9d6995152e545bd491c13058b8fac F ext/misc/spellfix.c 41cf26c6b89fcaa8798ae10ae64d39c1f1d9d6995152e545bd491c13058b8fac
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11 F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/unionvtab.c 1e0ebc5078e1a916db191bcd88f87e94ea7ba4aa563ee30ff706261cb4b39461 F ext/misc/unionvtab.c de36c2c45583d68f99e45b392311967066b02e2651d05697da783698b245b387
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178 F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9 F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
@@ -343,7 +344,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c cc91b6905bf55512c6ebc7dfdd37ac81c86f1753db8cfa6d62f0ee864464044f F ext/rtree/rtree.c 2111f685ae07988622c241f819b56fea60782f56e32f97e334473c59f6083481
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 82a353747fcab1083d114b2ac84723dfefdbf86c1a6e1df57bf588c7d4285436 F ext/rtree/rtree1.test 82a353747fcab1083d114b2ac84723dfefdbf86c1a6e1df57bf588c7d4285436
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
@@ -400,7 +401,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 8e24a3cae9a58e1620a21b492b7272c92ec0ab00e388088df77de2223c002169 F main.mk 6ef9e2b1c3f1e46c9e3c2b362531cbc277f7bea1a66fe610a3a7c4173b091ba4
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -422,14 +423,14 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7
F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09
F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc
F src/build.c 514db9d494ed29155e552f2ec2fa7c55c0241f847c683156b7c017f4b0bad9fa F src/build.c 87b68e3b45559ec404b12f095f0ba5f06f91a6dd2d21bd8443e41d8ac2e67196
F src/callback.c 28a8ede982fde4129b828350f78f2c01fe7d12c74d1a0a05d7108ab36f308688 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0 F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
F src/delete.c e6a70fb58f6628f0ffc6d7221a6702c0d7b342c82520385b3996b364c22e0cb3 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb
F src/expr.c fe11b91bb65b869143bd42023427c4429778ae42c0a0db7762f68f75b347a958 F src/expr.c fe11b91bb65b869143bd42023427c4429778ae42c0a0db7762f68f75b347a958
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
@@ -442,7 +443,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722 F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2 F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
F src/main.c d156d8fd43d268dea567298172a9c490b3a6a097e0b063e9b977f5e5ad78dc8c F src/main.c 903c4e3eb189d4ce94748dc7f442f9136177cb2eedb27185f83a525edb0c4530
F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6 F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -451,7 +452,7 @@ F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
F src/mutex.c 20172f2cc43c4542f7860ab6bafdd16965822c4e56650d62628059a48c7f43c4 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23 F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
@@ -461,8 +462,8 @@ F src/os.c 22d31db3ca5a96a408fbf1ceeaaebcaf64c87024d2ff9fe1cf2ddbec3e75c104
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c e87cef0bb894b94d96ee3af210be669549d111c580817d14818101b992640767 F src/os_unix.c 7fc2735390a7809d5d893ed735d994ff12521224b89738226fff6f1a0aa1c932
F src/os_win.c 7f36120492e4a23c48d1dd685edf29ae459c6d555660c61f1323cea3e5a1191d F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903 F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
@@ -472,17 +473,17 @@ F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69 F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
F src/prepare.c 7cf451f903ad92a14e22de415a13e7a7d30f1bd23b3d21eeb0dc7264723244c5 F src/prepare.c 259f4e7960c47082c9653f3d5f0c294abd68bb9c3aab86de7630700cba1c20fb
F src/printf.c 9506b4b96e59c0467047155f09015750cb2878aeda3d39e5610c1192ddc3c41c F src/printf.c 9506b4b96e59c0467047155f09015750cb2878aeda3d39e5610c1192ddc3c41c
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 17e220191860a64a18c084141e1a8b7309e166a6f2d42c02021af27ea080d157 F src/select.c 17e220191860a64a18c084141e1a8b7309e166a6f2d42c02021af27ea080d157
F src/shell.c.in c441d7ddfbb8120cd8a7cde838ca5c9167311a7e400b1077c3ae6090aa420be8 F src/shell.c.in 6ffed0c589f5aff180789a8c8abf5b2d3e2eea7470c86b30e797887cb0c9d0e5
F src/sqlite.h.in e9e275be6c05a3d5a3e6107c72c4fd8b0aaa6573b65e414373964ecd047fb19f F src/sqlite.h.in 95afbec6e623843d702e727765efc833586fecc688867f41f87be7db3ff1fa62
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
F src/sqliteInt.h b7eee7a14dc4cd8e8d073bd24d43c894880fd94ff39ad6e9ac87f88a85a7888d F src/sqliteInt.h 4d6580ab911e9bc36447ef05bf4d2aab929dde161ac117c7de6220eef06d6175
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -502,7 +503,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 2dad654eb81e90160f764f485bf7248e87b6d251e484c959de1aa04935acae8e F src/test_config.c 3904a8682aac58b77d20ca236face2b11e50781be4116004ba1ba79f69896ec9
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
@@ -552,7 +553,7 @@ F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1
F src/vdbeaux.c cf474d29372a30d0db84b0a9a74ab07117c9b831e1585a0fa335e2b445f4a95f F src/vdbeaux.c cf474d29372a30d0db84b0a9a74ab07117c9b831e1585a0fa335e2b445f4a95f
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 6e6082377183b8fd8d6f2bce45250b4c2e89bfeb534a094cd8612dae8aaa2fda F src/vdbemem.c 8478f7fb1948bf8fdeec7c2cb59ea58155c31258b9cd43c56d485e03ed40bd07
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
@@ -560,9 +561,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
F src/where.c a338038b90028c60901ef4115080220eec431fbdbd17a12c1f1b50b71146301e F src/where.c 1617e7e42daf0ace7799204e3e9b7c9e75069aa2a0c8ddd24d1b9569b2a0b7e4
F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
F src/wherecode.c 611fcabd05592ed2febd7d182f9621425b0466c5232d70e0981c842d429356d5 F src/wherecode.c ff2f079097a3bdce6ebabfde1419fba448c9ce5feb7cb964e8bfa2a4e27274ef
F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46 F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -938,7 +939,7 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711 F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test dbc0b87756e1e20e7497b56889c9e9cd2f8cc2b5 F test/hook.test dbc0b87756e1e20e7497b56889c9e9cd2f8cc2b5
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8 F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 73956798bace8982909c00476b216714a6d0559a F test/icu.test 7fb00edc09e05d51e36be12b33e0af04e3394e3b02dbdcb2eefcb901203e28c4
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test 2fa2dfba1afe30eb830f327e7131dfadaa7a701d677de0eb65f9303d99e18fe0 F test/in.test 2fa2dfba1afe30eb830f327e7131dfadaa7a701d677de0eb65f9303d99e18fe0
@@ -1013,7 +1014,7 @@ F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4 F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
F test/limit2.test e35f57bd3a62d7c5dcb5ac4306e675c75f974809 F test/limit2.test 360982809e03211636d2b18ddbc97d5da06826941370607e4b00e113f827cb5a
F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9 F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7 F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
@@ -1069,7 +1070,7 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2 F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
F test/misc8.test ba03aaa08f02d62fbb8d3b2f5595c1b33aa9bbc5 F test/misc8.test ba03aaa08f02d62fbb8d3b2f5595c1b33aa9bbc5
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7 F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 946d7161cabbc45ecc818d7fa38c1925bbf36e5534a08a81fa0203ee7ced7d54 F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
@@ -1216,7 +1217,7 @@ F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1 F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458 F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
F test/shell6.test ab1592ebe881371f651f18ee6a0df21cbfb5310f88cb832ab642d4038f679772 F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1265,8 +1266,9 @@ F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12 F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/swarmvtab.test c2279311b44de032f86a8295a9b06818d864856f9428b4c99eee91a0d419cf25 F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf
F test/swarmvtab2.test 9a3a68a1e58d00f4ed6c68d12d52f2df971b9e22a80a41f6f8c1409abba8e5b4 F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
F test/swarmvtab3.test c4c8d09e56ae99b90187ac225458f13f373873ea296fc442c7ad7511f25e7314
F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42 F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529 F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
@@ -1539,9 +1541,9 @@ F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03 F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
F test/walprotocol.test 0b92feb132ccebd855494d917d3f6c2d717ace20 F test/walprotocol.test a112aba0b79e3adeaa485fed09484b32c654e97df58e454aa8489ac2cd57bf84
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
F test/walro2.test 8812e514c968bf4ee317571fafedac43443360ae23edd7d0f4ef1eae0c13e8e8 F test/walro2.test 5cd57d192ee334c3894330303b5f8cb6789fef49b2c83ad1b50b9b132d0f7ae1
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
@@ -1607,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c e6056373044d55296d21f81467dba7632bbb81dc49af072b3f0e76338771497e F tool/lemon.c e6056373044d55296d21f81467dba7632bbb81dc49af072b3f0e76338771497e
F tool/lempar.c 105d0d9cbe5a25d24d4769241ffbfc63ac7c09e6ccee0dc43dcc8a4c4ae4e426 F tool/lempar.c 967ebf585cd09b11b89d255d213865109a9c4ff075680d22580a2826de288c89
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1685,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P e38571d518ff399d1033b33843dae60bc61181cdf692dcd8e2e14746bf0d1e61 75d699877fa7d06d30285ecf008fbedfdf68cc7965bb328c96f5a931d1f13f04 P 373fa21bffd37053bb1a741d3ace2f003a5639bf373c20ea7bb24a31080888b3 64487d658cb3b6c8c67f1e198c70813c963de52599f3ea974bdc2aa432e74de9
R 26cc16e97094ad5748375397be24ecfc R 864c298149f75794a8b0c88eee2c8573
U dan U dan
Z 08144a4a155e0a56cb23cd6a4ba9351b Z b67f6466a953a4099311404f5788e02e

View File

@@ -1 +1 @@
373fa21bffd37053bb1a741d3ace2f003a5639bf373c20ea7bb24a31080888b3 d5b597b52a1213cdf382d96f4df3535727be0852b25bafd12bbef54da946c5f2

View File

@@ -4364,6 +4364,18 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
pKey->aSortOrder[i] = pIdx->aSortOrder[i]; pKey->aSortOrder[i] = pIdx->aSortOrder[i];
} }
if( pParse->nErr ){ if( pParse->nErr ){
assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
if( pIdx->bNoQuery==0 ){
/* Deactivate the index because it contains an unknown collating
** sequence. The only way to reactive the index is to reload the
** schema. Adding the missing collating sequence later does not
** reactive the index. The application had the chance to register
** the missing index using the collation-needed callback. For
** simplicity, SQLite will not give the application a second chance.
*/
pIdx->bNoQuery = 1;
pParse->rc = SQLITE_ERROR_RETRY;
}
sqlite3KeyInfoUnref(pKey); sqlite3KeyInfoUnref(pKey);
pKey = 0; pKey = 0;
} }

View File

@@ -105,6 +105,7 @@ CollSeq *sqlite3GetCollSeq(
assert( !p || p->xCmp ); assert( !p || p->xCmp );
if( p==0 ){ if( p==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
} }
return p; return p;
} }

View File

@@ -39,7 +39,7 @@
** **
** Jean Meeus ** Jean Meeus
** Astronomical Algorithms, 2nd Edition, 1998 ** Astronomical Algorithms, 2nd Edition, 1998
** ISBM 0-943396-61-1 ** ISBN 0-943396-61-1
** Willmann-Bell, Inc ** Willmann-Bell, Inc
** Richmond, Virginia (USA) ** Richmond, Virginia (USA)
*/ */

View File

@@ -283,11 +283,11 @@ void sqlite3DeleteFrom(
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
isView = pTab->pSelect!=0; isView = pTab->pSelect!=0;
bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#else #else
# define pTrigger 0 # define pTrigger 0
# define isView 0 # define isView 0
#endif #endif
bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#ifdef SQLITE_OMIT_VIEW #ifdef SQLITE_OMIT_VIEW
# undef isView # undef isView
# define isView 0 # define isView 0

View File

@@ -22,7 +22,7 @@
#ifdef SQLITE_ENABLE_RTREE #ifdef SQLITE_ENABLE_RTREE
# include "rtree.h" # include "rtree.h"
#endif #endif
#ifdef SQLITE_ENABLE_ICU #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
# include "sqliteicu.h" # include "sqliteicu.h"
#endif #endif
#ifdef SQLITE_ENABLE_JSON1 #ifdef SQLITE_ENABLE_JSON1
@@ -3065,7 +3065,7 @@ static int openDatabase(
} }
#endif #endif
#ifdef SQLITE_ENABLE_ICU #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
if( !db->mallocFailed && rc==SQLITE_OK ){ if( !db->mallocFailed && rc==SQLITE_OK ){
rc = sqlite3IcuInit(db); rc = sqlite3IcuInit(db);
} }

View File

@@ -134,7 +134,7 @@ static void checkMutexFree(sqlite3_mutex *p){
assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
#if SQLITE_ENABLE_API_ARMOR #if SQLITE_ENABLE_API_ARMOR
if( p->iType<2 ){ if( ((CheckMutex*)p)->iType<2 )
#endif #endif
{ {
CheckMutex *pCheck = (CheckMutex*)p; CheckMutex *pCheck = (CheckMutex*)p;

View File

@@ -483,7 +483,7 @@ static struct unix_syscall {
#else #else
{ "munmap", (sqlite3_syscall_ptr)0, 0 }, { "munmap", (sqlite3_syscall_ptr)0, 0 },
#endif #endif
#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent) #define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent)
#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 }, { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
@@ -4165,7 +4165,7 @@ static int unixShmSystemLock(
/* Access to the unixShmNode object is serialized by the caller */ /* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode; pShmNode = pFile->pInode->pShmNode;
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
/* Shared locks never span more than one byte */ /* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK ); assert( n==1 || lockType!=F_RDLCK );
@@ -5799,7 +5799,7 @@ static int unixOpen(
** a file-descriptor on the directory too. The first time unixSync() ** a file-descriptor on the directory too. The first time unixSync()
** is called the directory file descriptor will be fsync()ed and close()d. ** is called the directory file descriptor will be fsync()ed and close()d.
*/ */
int syncDir = (isCreate && ( int isNewJrnl = (isCreate && (
eType==SQLITE_OPEN_MASTER_JOURNAL eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_WAL
@@ -5869,7 +5869,7 @@ static int unixOpen(
}else if( !zName ){ }else if( !zName ){
/* If zName is NULL, the upper layer is requesting a temp file. */ /* If zName is NULL, the upper layer is requesting a temp file. */
assert(isDelete && !syncDir); assert(isDelete && !isNewJrnl);
rc = unixGetTempname(pVfs->mxPathname, zTmpname); rc = unixGetTempname(pVfs->mxPathname, zTmpname);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
return rc; return rc;
@@ -5915,6 +5915,9 @@ static int unixOpen(
} }
if( fd<0 ){ if( fd<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
/* If unable to create a journal, change the error code to
** indicate that the directory permissions are wrong. */
if( isNewJrnl && osAccess(zName, F_OK) ) rc = SQLITE_READONLY_DIRECTORY;
goto open_finished; goto open_finished;
} }
@@ -5974,7 +5977,7 @@ static int unixOpen(
if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
noLock = eType!=SQLITE_OPEN_MAIN_DB; noLock = eType!=SQLITE_OPEN_MAIN_DB;
if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC;
if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
#if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_ENABLE_LOCKING_STYLE

View File

@@ -3742,7 +3742,7 @@ static int winShmSystemLock(
int rc = 0; /* Result code form Lock/UnlockFileEx() */ int rc = 0; /* Result code form Lock/UnlockFileEx() */
/* Access to the winShmNode object is serialized by the caller */ /* Access to the winShmNode object is serialized by the caller */
assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
pFile->hFile.h, lockType, ofst, nByte)); pFile->hFile.h, lockType, ofst, nByte));

View File

@@ -655,8 +655,6 @@ static int sqlite3Prepare(
end_prepare: end_prepare:
sqlite3ParserReset(&sParse); sqlite3ParserReset(&sParse);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
return rc; return rc;
} }
static int sqlite3LockAndPrepare( static int sqlite3LockAndPrepare(
@@ -669,6 +667,7 @@ static int sqlite3LockAndPrepare(
const char **pzTail /* OUT: End of parsed string */ const char **pzTail /* OUT: End of parsed string */
){ ){
int rc; int rc;
int cnt = 0;
#ifdef SQLITE_ENABLE_API_ARMOR #ifdef SQLITE_ENABLE_API_ARMOR
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
@@ -679,15 +678,18 @@ static int sqlite3LockAndPrepare(
} }
sqlite3_mutex_enter(db->mutex); sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db); sqlite3BtreeEnterAll(db);
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); do{
if( rc==SQLITE_SCHEMA ){ /* Make multiple attempts to compile the SQL, until it either succeeds
sqlite3ResetOneSchema(db, -1); ** or encounters a permanent error. A schema problem after one schema
sqlite3_finalize(*ppStmt); ** reset is considered a permanent error. */
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
} assert( rc==SQLITE_OK || *ppStmt==0 );
}while( rc==SQLITE_ERROR_RETRY
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db); sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
sqlite3_mutex_leave(db->mutex); sqlite3_mutex_leave(db->mutex);
assert( rc==SQLITE_OK || *ppStmt==0 );
return rc; return rc;
} }

View File

@@ -3895,10 +3895,10 @@ static int lintFkeyIndexes(
** **
** 0. The text of an SQL statement similar to: ** 0. The text of an SQL statement similar to:
** **
** "EXPLAIN QUERY PLAN SELECT rowid FROM child_table WHERE child_key=?" ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
** **
** This is the same SELECT that the foreign keys implementation needs ** This SELECT is similar to the one that the foreign keys implementation
** to run internally on child tables. If there is an index that can ** needs to run internally on child tables. If there is an index that can
** be used to optimize this query, then it can also be used by the FK ** be used to optimize this query, then it can also be used by the FK
** implementation to optimize DELETE or UPDATE statements on the parent ** implementation to optimize DELETE or UPDATE statements on the parent
** table. ** table.
@@ -3926,7 +3926,7 @@ static int lintFkeyIndexes(
*/ */
const char *zSql = const char *zSql =
"SELECT " "SELECT "
" 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '" " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
" || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
" || fkey_collate_clause(" " || fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')" " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"

View File

@@ -470,6 +470,8 @@ int sqlite3_exec(
** the most recent error can be obtained using ** the most recent error can be obtained using
** [sqlite3_extended_errcode()]. ** [sqlite3_extended_errcode()].
*/ */
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
@@ -515,6 +517,7 @@ int sqlite3_exec(
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8))
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))

View File

@@ -2174,6 +2174,7 @@ struct Index {
unsigned isCovering:1; /* True if this is a covering index */ unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nSample; /* Number of elements in aSample[] */ int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */
@@ -2986,7 +2987,7 @@ struct Parse {
int nMem; /* Number of memory cells used so far */ int nMem; /* Number of memory cells used so far */
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table for associated with an index on expr, or negative int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */ ** of the base register during check-constraint eval */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */

View File

@@ -429,6 +429,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "icu", "0", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "icu", "0", TCL_GLOBAL_ONLY);
#endif #endif
#ifdef SQLITE_ENABLE_ICU_COLLATIONS
Tcl_SetVar2(interp, "sqlite_options", "icu_collations", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "icu_collations", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_INCRBLOB #ifdef SQLITE_OMIT_INCRBLOB
Tcl_SetVar2(interp, "sqlite_options", "incrblob", "0", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "incrblob", "0", TCL_GLOBAL_ONLY);
#else #else

View File

@@ -1321,7 +1321,11 @@ static int valueFromExpr(
assert( pExpr!=0 ); assert( pExpr!=0 );
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
if( op==TK_REGISTER ) op = pExpr->op2; if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
#endif
/* Compressed expressions only appear when parsing the DEFAULT clause /* Compressed expressions only appear when parsing the DEFAULT clause
** on a table column definition, and hence only when pCtx==0. This ** on a table column definition, and hence only when pCtx==0. This
@@ -1416,7 +1420,10 @@ static int valueFromExpr(
return rc; return rc;
no_mem: no_mem:
sqlite3OomFault(db); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( pCtx==0 || pCtx->pParse->nErr==0 )
#endif
sqlite3OomFault(db);
sqlite3DbFree(db, zVal); sqlite3DbFree(db, zVal);
assert( *ppVal==0 ); assert( *ppVal==0 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4

View File

@@ -2879,6 +2879,7 @@ static int whereLoopAddBtree(
testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
continue; /* Partial index inappropriate for this query */ continue; /* Partial index inappropriate for this query */
} }
if( pProbe->bNoQuery ) continue;
rSize = pProbe->aiRowLogEst[0]; rSize = pProbe->aiRowLogEst[0];
pNew->u.btree.nEq = 0; pNew->u.btree.nEq = 0;
pNew->u.btree.nBtm = 0; pNew->u.btree.nBtm = 0;

View File

@@ -1690,6 +1690,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
} }
}else if( bStopAtNull ){ }else if( bStopAtNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
endEq = 0; endEq = 0;
nConstraint++; nConstraint++;
} }

View File

@@ -15,7 +15,7 @@
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
ifcapable !icu { ifcapable !icu&&!icu_collations {
finish_test finish_test
return return
} }
@@ -35,54 +35,57 @@ proc test_expr {name settings expr result} {
} $settings $expr] $result } $settings $expr] $result
} }
# Tests of the REGEXP operator. ifcapable icu {
#
test_expr icu-1.1 {i1='hello'} {i1 REGEXP 'hello'} 1
test_expr icu-1.2 {i1='hello'} {i1 REGEXP '.ello'} 1
test_expr icu-1.3 {i1='hello'} {i1 REGEXP '.ell'} 0
test_expr icu-1.4 {i1='hello'} {i1 REGEXP '.ell.*'} 1
test_expr icu-1.5 {i1=NULL} {i1 REGEXP '.ell.*'} {}
# Some non-ascii characters with defined case mappings # Tests of the REGEXP operator.
# #
set ::EGRAVE "\xC8" test_expr icu-1.1 {i1='hello'} {i1 REGEXP 'hello'} 1
set ::egrave "\xE8" test_expr icu-1.2 {i1='hello'} {i1 REGEXP '.ello'} 1
test_expr icu-1.3 {i1='hello'} {i1 REGEXP '.ell'} 0
test_expr icu-1.4 {i1='hello'} {i1 REGEXP '.ell.*'} 1
test_expr icu-1.5 {i1=NULL} {i1 REGEXP '.ell.*'} {}
set ::OGRAVE "\xD2" # Some non-ascii characters with defined case mappings
set ::ograve "\xF2" #
set ::EGRAVE "\xC8"
set ::egrave "\xE8"
# That German letter that looks a bit like a B. The set ::OGRAVE "\xD2"
# upper-case version of which is "SS" (two characters). set ::ograve "\xF2"
#
set ::szlig "\xDF"
# Tests of the upper()/lower() functions. # That German letter that looks a bit like a B. The
# # upper-case version of which is "SS" (two characters).
test_expr icu-2.1 {i1='HellO WorlD'} {upper(i1)} {HELLO WORLD} #
test_expr icu-2.2 {i1='HellO WorlD'} {lower(i1)} {hello world} set ::szlig "\xDF"
test_expr icu-2.3 {i1=$::egrave} {lower(i1)} $::egrave
test_expr icu-2.4 {i1=$::egrave} {upper(i1)} $::EGRAVE
test_expr icu-2.5 {i1=$::ograve} {lower(i1)} $::ograve
test_expr icu-2.6 {i1=$::ograve} {upper(i1)} $::OGRAVE
test_expr icu-2.3 {i1=$::EGRAVE} {lower(i1)} $::egrave
test_expr icu-2.4 {i1=$::EGRAVE} {upper(i1)} $::EGRAVE
test_expr icu-2.5 {i1=$::OGRAVE} {lower(i1)} $::ograve
test_expr icu-2.6 {i1=$::OGRAVE} {upper(i1)} $::OGRAVE
test_expr icu-2.7 {i1=$::szlig} {upper(i1)} "SS" # Tests of the upper()/lower() functions.
test_expr icu-2.8 {i1='SS'} {lower(i1)} "ss" #
test_expr icu-2.1 {i1='HellO WorlD'} {upper(i1)} {HELLO WORLD}
test_expr icu-2.2 {i1='HellO WorlD'} {lower(i1)} {hello world}
test_expr icu-2.3 {i1=$::egrave} {lower(i1)} $::egrave
test_expr icu-2.4 {i1=$::egrave} {upper(i1)} $::EGRAVE
test_expr icu-2.5 {i1=$::ograve} {lower(i1)} $::ograve
test_expr icu-2.6 {i1=$::ograve} {upper(i1)} $::OGRAVE
test_expr icu-2.3 {i1=$::EGRAVE} {lower(i1)} $::egrave
test_expr icu-2.4 {i1=$::EGRAVE} {upper(i1)} $::EGRAVE
test_expr icu-2.5 {i1=$::OGRAVE} {lower(i1)} $::ograve
test_expr icu-2.6 {i1=$::OGRAVE} {upper(i1)} $::OGRAVE
do_execsql_test icu-2.9 { test_expr icu-2.7 {i1=$::szlig} {upper(i1)} "SS"
SELECT upper(char(0xfb04,0xfb04,0xfb04,0xfb04)); test_expr icu-2.8 {i1='SS'} {lower(i1)} "ss"
} {FFLFFLFFLFFL}
# In turkish (locale="tr_TR"), the lower case version of I do_execsql_test icu-2.9 {
# is "small dotless i" (code point 0x131 (decimal 305)). SELECT upper(char(0xfb04,0xfb04,0xfb04,0xfb04));
# } {FFLFFLFFLFFL}
set ::small_dotless_i "\u0131"
test_expr icu-3.1 {i1='I'} {lower(i1)} "i" # In turkish (locale="tr_TR"), the lower case version of I
test_expr icu-3.2 {i1='I'} {lower(i1, 'tr_tr')} $::small_dotless_i # is "small dotless i" (code point 0x131 (decimal 305)).
test_expr icu-3.3 {i1='I'} {lower(i1, 'en_AU')} "i" #
set ::small_dotless_i "\u0131"
test_expr icu-3.1 {i1='I'} {lower(i1)} "i"
test_expr icu-3.2 {i1='I'} {lower(i1, 'tr_tr')} $::small_dotless_i
test_expr icu-3.3 {i1='I'} {lower(i1, 'en_AU')} "i"
}
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Test the collation sequence function. # Test the collation sequence function.
@@ -124,22 +127,23 @@ do_test icu-4.3 {
# #
# http://src.chromium.org/viewvc/chrome/trunk/src/third_party/sqlite/icu-regexp.patch?revision=34807&view=markup # http://src.chromium.org/viewvc/chrome/trunk/src/third_party/sqlite/icu-regexp.patch?revision=34807&view=markup
# #
do_catchsql_test icu-5.1 { SELECT regexp('a[abc]c.*', 'abc') } {0 1} ifcapable icu {
do_catchsql_test icu-5.2 { do_catchsql_test icu-5.1 { SELECT regexp('a[abc]c.*', 'abc') } {0 1}
SELECT regexp('a[abc]c.*') do_catchsql_test icu-5.2 {
} {1 {wrong number of arguments to function regexp()}} SELECT regexp('a[abc]c.*')
do_catchsql_test icu-5.3 { } {1 {wrong number of arguments to function regexp()}}
SELECT regexp('a[abc]c.*', 'abc', 'c') do_catchsql_test icu-5.3 {
} {1 {wrong number of arguments to function regexp()}} SELECT regexp('a[abc]c.*', 'abc', 'c')
do_catchsql_test icu-5.4 { } {1 {wrong number of arguments to function regexp()}}
SELECT 'abc' REGEXP 'a[abc]c.*' do_catchsql_test icu-5.4 {
} {0 1} SELECT 'abc' REGEXP 'a[abc]c.*'
do_catchsql_test icu-5.4 { SELECT 'abc' REGEXP } {1 {near " ": syntax error}} } {0 1}
do_catchsql_test icu-5.5 { SELECT 'abc' REGEXP, 1 } {1 {near ",": syntax error}} do_catchsql_test icu-5.4 {SELECT 'abc' REGEXP } {1 {near " ": syntax error}}
do_catchsql_test icu-5.5 {SELECT 'abc' REGEXP, 1} {1 {near ",": syntax error}}
do_malloc_test icu-6.10 -sqlbody { do_malloc_test icu-6.10 -sqlbody {
SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04)); SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
}
} }
finish_test finish_test

View File

@@ -150,4 +150,21 @@ do_execsql_test 502 {
SELECT j FROM t502 WHERE i IN (1,2,3,4,5) ORDER BY j LIMIT 3; SELECT j FROM t502 WHERE i IN (1,2,3,4,5) ORDER BY j LIMIT 3;
} {1 3 4} } {1 3 4}
# Ticket https://www.sqlite.org/src/info/123c9ba32130a6c9 2017-12-13
# Incorrect result when an idnex is used for an ordered join.
#
# This test case is in the limit2.test module because the problem was first
# exposed by check-in https://www.sqlite.org/src/info/559733b09e which
# implemented the ORDER BY LIMIT optimization that limit2.test strives to
# test.
#
do_execsql_test 600 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1,2);
DROP TABLE IF EXISTS t2;
CREATE TABLE t2(x, y); INSERT INTO t2 VALUES(1,3);
CREATE INDEX t1ab ON t1(a,b);
SELECT y FROM t1, t2 WHERE a=x AND b<=y ORDER BY b DESC;
} {3}
finish_test finish_test

View File

@@ -15,6 +15,11 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set testprefix mjournal set testprefix mjournal
if {[permutation]=="inmemory_journal"} {
finish_test
return
}
# Test that nothing bad happens if a journal file contains a pointer to # Test that nothing bad happens if a journal file contains a pointer to
# a master journal file that does not have a "-" in the name. At one point # a master journal file that does not have a "-" in the name. At one point
# this was causing a segfault on unix. # this was causing a segfault on unix.

View File

@@ -93,6 +93,14 @@ foreach {tn schema output} {
} { } {
} }
10 {
CREATE TABLE parent (id INTEGER PRIMARY KEY);
CREATE TABLE child2 (id INT PRIMARY KEY, parentID INT REFERENCES parent)
WITHOUT ROWID;
} {
CREATE INDEX 'child2_parentID' ON 'child2'('parentID'); --> parent(id)
}
} { } {
forcedelete test.db forcedelete test.db
sqlite3 db test.db sqlite3 db test.db

View File

@@ -213,7 +213,7 @@ do_catchsql_test 3.1 {
("test.db2", "t1", 11, 20) ("test.db2", "t1", 11, 20)
', 'fetch_db_no_such_function' ', 'fetch_db_no_such_function'
); );
} {1 {no such function: fetch_db_no_such_function}} } {1 {sql error: no such function: fetch_db_no_such_function}}
do_catchsql_test 3.2 { do_catchsql_test 3.2 {
CREATE VIRTUAL TABLE temp.xyz USING swarmvtab( CREATE VIRTUAL TABLE temp.xyz USING swarmvtab(

View File

@@ -14,7 +14,7 @@
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set testprefix swarmvtab set testprefix swarmvtab2
do_not_use_codec do_not_use_codec
ifcapable !vtab { ifcapable !vtab {

233
test/swarmvtab3.test Normal file
View File

@@ -0,0 +1,233 @@
# 2017-07-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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is the "swarmvtab" extension
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix swarmvtab3
do_not_use_codec
ifcapable !vtab {
finish_test
return
}
load_static_extension db unionvtab
set nFile $sqlite_open_file_count
do_execsql_test 1.0 {
CREATE TEMP TABLE swarm(id, tbl, minval, maxval);
}
# Set up 100 databases with filenames "remote_test.dbN", where N is between
# 0 and 99.
do_test 1.1 {
for {set i 0} {$i < 100} {incr i} {
set file remote_test.db$i
forcedelete $file
forcedelete test.db$i
sqlite3 rrr $file
rrr eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES($i, $i);
}
rrr close
db eval {
INSERT INTO swarm VALUES($i, 't1', $i, $i);
}
set ::dbcache(test.db$i) 0
}
} {}
proc missing_db {filename} {
set remote "remote_$filename"
forcedelete $filename
file copy $remote $filename
}
db func missing_db missing_db
proc openclose_db {filename bClose} {
if {$bClose} {
incr ::dbcache($filename) -1
} else {
incr ::dbcache($filename) 1
}
if {$::dbcache($filename)==0} {
forcedelete $filename
}
}
db func openclose_db openclose_db
proc check_dbcache {} {
set n 0
for {set i 0} {$i<100} {incr i} {
set exists [file exists test.db$i]
if {$exists!=($::dbcache(test.db$i)!=0)} {
error "inconsistent ::dbcache and disk"
}
incr n $exists
}
return $n
}
foreach {tn nMaxOpen cvt} {
1 5 {
CREATE VIRTUAL TABLE temp.s USING swarmvtab(
'SELECT :prefix || id, tbl, minval, minval FROM swarm',
:prefix='test.db',
missing=missing_db,
openclose=openclose_db,
maxopen=5
)
}
2 3 {
CREATE VIRTUAL TABLE temp.s USING swarmvtab(
'SELECT :prefix || id, tbl, minval, minval FROM swarm',
:prefix='test.db',
missing = 'missing_db',
openclose=[openclose_db],
maxopen = 3
)
}
3 1 {
CREATE VIRTUAL TABLE temp.s USING swarmvtab(
'SELECT :prefix||''.''||:suffix||id, tbl, minval, minval FROM swarm',
:prefix=test, :suffix=db,
missing = 'missing_db',
openclose=[openclose_db],
maxopen = 1
)
}
} {
execsql { DROP TABLE IF EXISTS s }
do_execsql_test 1.$tn.1 $cvt
do_execsql_test 1.$tn.2 {
SELECT b FROM s WHERE a<10;
} {0 1 2 3 4 5 6 7 8 9}
do_test 1.$tn.3 { check_dbcache } $nMaxOpen
do_execsql_test 1.$tn.4 {
SELECT b FROM s WHERE (b%10)=0;
} {0 10 20 30 40 50 60 70 80 90}
do_test 1.$tn.5 { check_dbcache } $nMaxOpen
}
execsql { DROP TABLE IF EXISTS s }
for {set i 0} {$i < 100} {incr i} {
forcedelete remote_test.db$i
}
#----------------------------------------------------------------------------
#
do_execsql_test 2.0 {
DROP TABLE IF EXISTS swarm;
CREATE TEMP TABLE swarm(file, tbl, minval, maxval, ctx);
}
catch { array unset ::dbcache }
# Set up 100 databases with filenames "remote_test.dbN", where N is a
# random integer between 0 and 1,000,000
# 0 and 99.
do_test 2.1 {
for {set i 0} {$i < 100} {incr i} {
while 1 {
set ctx [expr abs(int(rand() *1000000))]
if {[info exists ::dbcache($ctx)]==0} break
}
set file test_remote.db$ctx
forcedelete $file
forcedelete test.db$i
sqlite3 rrr $file
rrr eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES($i, $i);
}
rrr close
db eval {
INSERT INTO swarm VALUES('test.db' || $i, 't1', $i, $i, $file)
}
set ::dbcache(test.db$i) 0
}
} {}
proc missing_db {filename ctx} {
file copy $ctx $filename
}
db func missing_db missing_db
proc openclose_db {filename ctx bClose} {
if {$bClose} {
incr ::dbcache($filename) -1
} else {
incr ::dbcache($filename) 1
}
if {$::dbcache($filename)==0} {
forcedelete $filename
}
}
db func openclose_db openclose_db
proc check_dbcache {} {
set n 0
foreach k [array names ::dbcache] {
set exists [file exists $k]
if {$exists!=($::dbcache($k)!=0)} {
error "inconsistent ::dbcache and disk ($k)"
}
incr n $exists
}
return $n
}
foreach {tn nMaxOpen cvt} {
2 5 {
CREATE VIRTUAL TABLE temp.s USING swarmvtab(
'SELECT file, tbl, minval, minval, ctx FROM swarm',
missing=missing_db,
openclose=openclose_db,
maxopen=5
)
}
} {
execsql { DROP TABLE IF EXISTS s }
do_execsql_test 1.$tn.1 $cvt
do_execsql_test 1.$tn.2 {
SELECT b FROM s WHERE a<10;
} {0 1 2 3 4 5 6 7 8 9}
do_test 1.$tn.3 { check_dbcache } $nMaxOpen
do_execsql_test 1.$tn.4 {
SELECT b FROM s WHERE (b%10)=0;
} {0 10 20 30 40 50 60 70 80 90}
do_test 1.$tn.5 { check_dbcache } $nMaxOpen
}
db close
forcedelete {*}[glob test_remote.db*]
finish_test

View File

@@ -52,21 +52,21 @@ do_test 1.1 {
set ::locks [list] set ::locks [list]
sqlite3 db test.db -vfs T sqlite3 db test.db -vfs T
execsql { SELECT * FROM x } execsql { SELECT * FROM x }
lrange $::locks 0 3 lrange $::locks 0 5
} [list {0 1 lock exclusive} {1 7 lock exclusive} \ } [list {0 1 lock exclusive} {1 2 lock exclusive} {4 4 lock exclusive} \
{1 7 unlock exclusive} {0 1 unlock exclusive} \ {1 2 unlock exclusive} {4 4 unlock exclusive} {0 1 unlock exclusive} \
] ]
do_test 1.2 { do_test 1.2 {
db close db close
set ::locks [list] set ::locks [list]
sqlite3 db test.db -vfs T sqlite3 db test.db -vfs T
execsql { SELECT * FROM x } execsql { SELECT * FROM x }
lrange $::locks 0 3 lrange $::locks 0 5
} [list {0 1 lock exclusive} {1 7 lock exclusive} \ } [list {0 1 lock exclusive} {1 2 lock exclusive} {4 4 lock exclusive} \
{1 7 unlock exclusive} {0 1 unlock exclusive} \ {1 2 unlock exclusive} {4 4 unlock exclusive} {0 1 unlock exclusive} \
] ]
proc lock_callback {method filename handle lock} { proc lock_callback {method filename handle lock} {
if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY } if {$lock == "1 2 lock exclusive"} { return SQLITE_BUSY }
return SQLITE_OK return SQLITE_OK
} }
puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times." puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
@@ -90,6 +90,18 @@ do_test 1.4 {
sqlite3 db test.db -vfs T sqlite3 db test.db -vfs T
catchsql { SELECT * FROM x } catchsql { SELECT * FROM x }
} {1 {locking protocol}} } {1 {locking protocol}}
puts "# Warning: Third time!"
proc lock_callback {method filename handle lock} {
if {$lock == "4 4 lock exclusive"} { return SQLITE_BUSY }
return SQLITE_OK
}
do_test 1.5 {
db close
set ::locks [list]
sqlite3 db test.db -vfs T
catchsql { SELECT * FROM x }
} {1 {locking protocol}}
db close db close
T delete T delete
@@ -135,13 +147,14 @@ T filter xShmLock
T script lock_callback T script lock_callback
proc lock_callback {method file handle spec} { proc lock_callback {method file handle spec} {
if {$spec == "1 7 unlock exclusive"} { if {$spec == "1 2 unlock exclusive"} {
T filter {} T filter {}
set ::r [catchsql { SELECT * FROM b } db2] set ::r [catchsql { SELECT * FROM b } db2]
} }
} }
sqlite3 db test.db sqlite3 db test.db
sqlite3 db2 test.db sqlite3 db2 test.db
puts "# Warning: Another slow test!"
do_test 2.5 { do_test 2.5 {
execsql { SELECT * FROM b } execsql { SELECT * FROM b }
} {Tehran Qom Markazi Qazvin Gilan Ardabil} } {Tehran Qom Markazi Qazvin Gilan Ardabil}
@@ -157,12 +170,13 @@ sqlite3 db2 test.db
T filter xShmLock T filter xShmLock
T script lock_callback T script lock_callback
proc lock_callback {method file handle spec} { proc lock_callback {method file handle spec} {
if {$spec == "1 7 unlock exclusive"} { if {$spec == "1 2 unlock exclusive"} {
T filter {} T filter {}
set ::r [catchsql { SELECT * FROM b } db2] set ::r [catchsql { SELECT * FROM b } db2]
} }
} }
unset ::r unset ::r
puts "# Warning: Last one!"
do_test 2.7 { do_test 2.7 {
execsql { SELECT * FROM b } execsql { SELECT * FROM b }
} {Tehran Qom Markazi Qazvin Gilan Ardabil} } {Tehran Qom Markazi Qazvin Gilan Ardabil}

View File

@@ -262,8 +262,9 @@ do_multiclient_test tn {
} }
} {500} } {500}
do_test $TN.4.2.2 { do_test $TN.4.2.2 {
file size test.db-wal set sz [file size test.db-wal]
} {461152} expr {$sz>400000 && $sz<500000}
} {1}
do_test $TN.4.2.4 { do_test $TN.4.2.4 {
file_control_persist_wal db 1; db close file_control_persist_wal db 1; db close

View File

@@ -651,10 +651,18 @@ static void yy_accept(yyParser*); /* Forward Declaration */
/* /*
** Perform a reduce action and the shift that must immediately ** Perform a reduce action and the shift that must immediately
** follow the reduce. ** follow the reduce.
**
** The yyLookahead and yyLookaheadToken parameters provide reduce actions
** access to the lookahead token (if any). The yyLookahead will be YYNOCODE
** if the lookahead token has already been consumed. As this procedure is
** only called from one place, optimizing compilers will in-line it, which
** means that the extra parameters have no performance impact.
*/ */
static void yy_reduce( static void yy_reduce(
yyParser *yypParser, /* The parser */ yyParser *yypParser, /* The parser */
unsigned int yyruleno /* Number of the rule by which to reduce */ unsigned int yyruleno, /* Number of the rule by which to reduce */
int yyLookahead, /* Lookahead token, or YYNOCODE if none */
ParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */
){ ){
int yygoto; /* The next state */ int yygoto; /* The next state */
int yyact; /* The next action */ int yyact; /* The next action */
@@ -853,7 +861,7 @@ void Parse(
#endif #endif
yymajor = YYNOCODE; yymajor = YYNOCODE;
}else if( yyact <= YY_MAX_REDUCE ){ }else if( yyact <= YY_MAX_REDUCE ){
yy_reduce(yypParser,yyact-YY_MIN_REDUCE); yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor);
}else{ }else{
assert( yyact == YY_ERROR_ACTION ); assert( yyact == YY_ERROR_ACTION );
yyminorunion.yy0 = yyminor; yyminorunion.yy0 = yyminor;