Compare commits
147 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9af5d394e3 | ||
![]() |
19e1883874 | ||
![]() |
da6f00cc63 | ||
![]() |
aa45304859 | ||
![]() |
e9ef82f592 | ||
![]() |
5bd2d02612 | ||
![]() |
7d322c14cf | ||
![]() |
81d50a0880 | ||
![]() |
cb4a48e249 | ||
![]() |
f5528a1168 | ||
![]() |
742f74ec19 | ||
![]() |
76e67700e0 | ||
![]() |
0d8cea5109 | ||
![]() |
68796a609b | ||
![]() |
ba9c7c10cc | ||
![]() |
7d13a403c4 | ||
![]() |
b7e87a53c7 | ||
![]() |
e24103baad | ||
![]() |
4891bf00db | ||
![]() |
467d804e1a | ||
![]() |
ff46ff5c73 | ||
![]() |
b60eb8bf6e | ||
![]() |
5d30acad2f | ||
![]() |
d352e7d6ac | ||
![]() |
47409209c2 | ||
![]() |
07a7cd3714 | ||
![]() |
47e42cd143 | ||
![]() |
757372ab56 | ||
![]() |
9d086cc562 | ||
![]() |
1fd73f2693 | ||
![]() |
5267068d3d | ||
![]() |
0205717b93 | ||
![]() |
cc74eafee5 | ||
![]() |
45d92dd539 | ||
![]() |
6fe6b73a8d | ||
![]() |
7a1cc96197 | ||
![]() |
1e6ee1929c | ||
![]() |
832406c2b4 | ||
![]() |
7331bc0002 | ||
![]() |
6f5c4810bc | ||
![]() |
b9b790e8cc | ||
![]() |
ecd48447b2 | ||
![]() |
f578ed6838 | ||
![]() |
b17135d81f | ||
![]() |
5d2f5f4655 | ||
![]() |
1adff07cb9 | ||
![]() |
5b39dd45e8 | ||
![]() |
d17b9114aa | ||
![]() |
6c9cc2c4f8 | ||
![]() |
ca773a51de | ||
![]() |
ade7cd53ab | ||
![]() |
e3d452a826 | ||
![]() |
faff28a478 | ||
![]() |
70cfee98e5 | ||
![]() |
d94023257b | ||
![]() |
1651f418e5 | ||
![]() |
77508c4768 | ||
![]() |
ce8a1720d6 | ||
![]() |
d9da500bd7 | ||
![]() |
82ac3d8211 | ||
![]() |
73b1ef33ef | ||
![]() |
b77b56bd52 | ||
![]() |
86b7bb29da | ||
![]() |
e81feadb41 | ||
![]() |
6c45111957 | ||
![]() |
029eb1bf15 | ||
![]() |
2a27e5e4cb | ||
![]() |
6702d6dadc | ||
![]() |
6c75609f48 | ||
![]() |
981dcb6236 | ||
![]() |
3f17a238bb | ||
![]() |
5666f09523 | ||
![]() |
8f1396ae8b | ||
![]() |
aed427074b | ||
![]() |
348093c719 | ||
![]() |
b90edad19d | ||
![]() |
b321a9b0fa | ||
![]() |
234f384386 | ||
![]() |
7271df982d | ||
![]() |
f54bc90ca3 | ||
![]() |
fa4d43fb64 | ||
![]() |
c77906eedd | ||
![]() |
e1c2be1134 | ||
![]() |
2303f0859c | ||
![]() |
938ede2078 | ||
![]() |
0f1e95e616 | ||
![]() |
ebc672832f | ||
![]() |
67f562233f | ||
![]() |
80189c5bfe | ||
![]() |
17e08c6149 | ||
![]() |
e809deee13 | ||
![]() |
226fda81af | ||
![]() |
c25b39e41d | ||
![]() |
1a2a4f12dc | ||
![]() |
50c9522c24 | ||
![]() |
9bf3da81a0 | ||
![]() |
174f4fa241 | ||
![]() |
aae84d814c | ||
![]() |
ea8c9a43aa | ||
![]() |
ca97a18493 | ||
![]() |
69105498b9 | ||
![]() |
bd74861e91 | ||
![]() |
6d671d4c09 | ||
![]() |
8caab4aebe | ||
![]() |
b3168a0056 | ||
![]() |
2c34d3c61e | ||
![]() |
d59a566707 | ||
![]() |
254bcdd02d | ||
![]() |
e31602c62d | ||
![]() |
1e469f79b1 | ||
![]() |
6fdd8fc5f0 | ||
![]() |
e5fd180648 | ||
![]() |
b83e6e9420 | ||
![]() |
d9df7cb876 | ||
![]() |
281ee2f754 | ||
![]() |
f552a23740 | ||
![]() |
3eeda95d36 | ||
![]() |
1f3762607d | ||
![]() |
d445ed094a | ||
![]() |
ce909d1aae | ||
![]() |
0f297b6e50 | ||
![]() |
2d111c8bbb | ||
![]() |
665f3d209b | ||
![]() |
c5140b39ce | ||
![]() |
93543215e0 | ||
![]() |
e698c1f79e | ||
![]() |
597bf19266 | ||
![]() |
eeb778d506 | ||
![]() |
2c4328ed87 | ||
![]() |
f17e510ee5 | ||
![]() |
ca72570a11 | ||
![]() |
d597b966d9 | ||
![]() |
c30d437376 | ||
![]() |
e05f922583 | ||
![]() |
6456b3929c | ||
![]() |
816fc35956 | ||
![]() |
8eed108df1 | ||
![]() |
6cbf8e173f | ||
![]() |
2df2b3d05f | ||
![]() |
40927fd61e | ||
![]() |
50182fa846 | ||
![]() |
5d122d308f | ||
![]() |
288e98fb4b | ||
![]() |
bfcf8d6d67 | ||
![]() |
24f1b25c7b | ||
![]() |
3400e78f38 | ||
![]() |
055cc1e431 |
@ -1633,6 +1633,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\amatch.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\basexx.c \
|
||||
$(TOP)\ext\misc\bgckpt.c \
|
||||
$(TOP)\ext\misc\carray.c \
|
||||
$(TOP)\ext\misc\cksumvfs.c \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
|
98
doc/wal2.md
Normal file
98
doc/wal2.md
Normal file
@ -0,0 +1,98 @@
|
||||
|
||||
Wal2 Mode Notes
|
||||
===============
|
||||
|
||||
## Activating/Deactivating Wal2 Mode
|
||||
|
||||
"Wal2" mode is very similar to "wal" mode. To change a database to wal2 mode,
|
||||
use the command:
|
||||
|
||||
>
|
||||
PRAGMA journal_mode = wal2;
|
||||
|
||||
It is not possible to change a database directly from "wal" mode to "wal2"
|
||||
mode. Instead, it must first be changed to rollback mode. So, to change a wal
|
||||
mode database to wal2 mode, the following two commands may be used:
|
||||
|
||||
>
|
||||
PRAGMA journal_mode = delete;
|
||||
PRAGMA journal_mode = wal2;
|
||||
|
||||
A database in wal2 mode may only be accessed by versions of SQLite compiled
|
||||
from this branch. Attempting to use any other version of SQLite results in an
|
||||
SQLITE_NOTADB error. A wal2 mode database may be changed back to rollback mode
|
||||
(making it accessible by all versions of SQLite) using:
|
||||
|
||||
>
|
||||
PRAGMA journal_mode = delete;
|
||||
|
||||
## The Advantage of Wal2 Mode
|
||||
|
||||
In legacy wal mode, when a writer writes data to the database, it doesn't
|
||||
modify the database file directly. Instead, it appends new data to the
|
||||
"<database>-wal" file. Readers read data from both the original database
|
||||
file and the "<database>-wal" file. At some point, data is copied from the
|
||||
"<database>-wal" file into the database file, after which the wal file can
|
||||
be deleted or overwritten. Copying data from the wal file into the database
|
||||
file is called a "checkpoint", and may be done explictly (either by "PRAGMA
|
||||
wal_checkpoint" or sqlite3_wal_checkpoint_v2()), or
|
||||
automatically (by configuring "PRAGMA wal_autocheckpoint" - this is the
|
||||
default).
|
||||
|
||||
Checkpointers do not block writers, and writers do not block checkpointers.
|
||||
However, if a writer writes to the database while a checkpoint is ongoing,
|
||||
then the new data is appended to the end of the wal file. This means that,
|
||||
even following the checkpoint, the wal file cannot be overwritten or deleted,
|
||||
and so all subsequent transactions must also be appended to the wal file. The
|
||||
work of the checkpointer is not wasted - SQLite remembers which parts of the
|
||||
wal file have already been copied into the db file so that the next checkpoint
|
||||
does not have to do so again - but it does mean that the wal file may grow
|
||||
indefinitely if the checkpointer never gets a chance to finish without a
|
||||
writer appending to the wal file. There are also circumstances in which
|
||||
long-running readers may prevent a checkpointer from checkpointing the entire
|
||||
wal file - also causing the wal file to grow indefinitely in a busy system.
|
||||
|
||||
Wal2 mode does not have this problem. In wal2 mode, wal files do not grow
|
||||
indefinitely even if the checkpointer never has a chance to finish
|
||||
uninterrupted.
|
||||
|
||||
In wal2 mode, the system uses two wal files instead of one. The files are named
|
||||
"<database>-wal" and "<database>-wal2", where "<database>" is of
|
||||
course the name of the database file. When data is written to the database, the
|
||||
writer begins by appending the new data to the first wal file. Once the first
|
||||
wal file has grown large enough, writers switch to appending data to the second
|
||||
wal file. At this point the first wal file can be checkpointed (after which it
|
||||
can be overwritten). Then, once the second wal file has grown large enough and
|
||||
the first wal file has been checkpointed, writers switch back to the first wal
|
||||
file. And so on.
|
||||
|
||||
## Application Programming
|
||||
|
||||
From the point of view of the user, the main differences between wal and
|
||||
wal2 mode are to do with checkpointing:
|
||||
|
||||
* In wal mode, a checkpoint may be attempted at any time. In wal2
|
||||
mode, the checkpointer has to wait until writers have switched
|
||||
to the "other" wal file before a checkpoint can take place.
|
||||
|
||||
* In wal mode, the wal-hook (callback registered using
|
||||
sqlite3_wal_hook()) is invoked after a transaction is committed
|
||||
with the total number of pages in the wal file as an argument. In wal2
|
||||
mode, the argument is either the total number of uncheckpointed pages in
|
||||
both wal files, or - if the "other" wal file is empty or already
|
||||
checkpointed - 0.
|
||||
|
||||
Clients are recommended to use the same strategies for checkpointing wal2 mode
|
||||
databases as for wal databases - by registering a wal-hook using
|
||||
sqlite3_wal_hook() and attempting a checkpoint when the parameter
|
||||
exceeds a certain threshold.
|
||||
|
||||
However, it should be noted that although the wal-hook is invoked after each
|
||||
transaction is committed to disk and database locks released, it is still
|
||||
invoked from within the sqlite3_step() call used to execute the "COMMIT"
|
||||
command. In BEGIN CONCURRENT systems, where the "COMMIT" is often protected by
|
||||
an application mutex, this may reduce concurrency. In such systems, instead of
|
||||
executing a checkpoint from within the wal-hook, a thread might defer this
|
||||
action until after the application mutex has been released.
|
||||
|
||||
|
228
ext/misc/bgckpt.c
Normal file
228
ext/misc/bgckpt.c
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
** 2017-10-11
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
*/
|
||||
|
||||
#if !defined(SQLITE_TEST) || defined(SQLITE_OS_UNIX)
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/*
|
||||
** API declarations.
|
||||
*/
|
||||
typedef struct Checkpointer Checkpointer;
|
||||
int sqlite3_bgckpt_create(const char *zFilename, Checkpointer **pp);
|
||||
int sqlite3_bgckpt_checkpoint(Checkpointer *p, int bBlock);
|
||||
void sqlite3_bgckpt_destroy(Checkpointer *p);
|
||||
|
||||
|
||||
struct Checkpointer {
|
||||
sqlite3 *db; /* Database handle */
|
||||
|
||||
pthread_t thread; /* Background thread */
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
int rc; /* Error from "PRAGMA wal_checkpoint" */
|
||||
int bCkpt; /* True if checkpoint requested */
|
||||
int bExit; /* True if exit requested */
|
||||
};
|
||||
|
||||
static void *bgckptThreadMain(void *pCtx){
|
||||
int rc = SQLITE_OK;
|
||||
Checkpointer *p = (Checkpointer*)pCtx;
|
||||
|
||||
while( rc==SQLITE_OK ){
|
||||
int bExit;
|
||||
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
if( p->bCkpt==0 && p->bExit==0 ){
|
||||
pthread_cond_wait(&p->cond, &p->mutex);
|
||||
}
|
||||
p->bCkpt = 0;
|
||||
bExit = p->bExit;
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
|
||||
if( bExit ) break;
|
||||
rc = sqlite3_exec(p->db, "PRAGMA wal_checkpoint", 0, 0, 0);
|
||||
if( rc==SQLITE_BUSY ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
p->rc = rc;
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sqlite3_bgckpt_destroy(Checkpointer *p){
|
||||
if( p ){
|
||||
void *ret = 0;
|
||||
|
||||
/* Signal the background thread to exit */
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
p->bExit = 1;
|
||||
pthread_cond_broadcast(&p->cond);
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
|
||||
pthread_join(p->thread, &ret);
|
||||
sqlite3_close(p->db);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int sqlite3_bgckpt_create(const char *zFilename, Checkpointer **pp){
|
||||
Checkpointer *pNew = 0;
|
||||
int rc;
|
||||
|
||||
pNew = (Checkpointer*)sqlite3_malloc(sizeof(Checkpointer));
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pNew, 0, sizeof(Checkpointer));
|
||||
rc = sqlite3_open(zFilename, &pNew->db);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pthread_mutex_init(&pNew->mutex, 0);
|
||||
pthread_cond_init(&pNew->cond, 0);
|
||||
pthread_create(&pNew->thread, 0, bgckptThreadMain, (void*)pNew);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_bgckpt_destroy(pNew);
|
||||
pNew = 0;
|
||||
}
|
||||
*pp = pNew;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3_bgckpt_checkpoint(Checkpointer *p, int bBlock){
|
||||
int rc;
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
rc = p->rc;
|
||||
if( rc==SQLITE_OK ){
|
||||
p->bCkpt = 1;
|
||||
pthread_cond_broadcast(&p->cond);
|
||||
}
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
#include "tclsqlite.h"
|
||||
|
||||
const char *sqlite3ErrName(int rc);
|
||||
|
||||
static void SQLITE_TCLAPI bgckpt_del(void * clientData){
|
||||
Checkpointer *pCkpt = (Checkpointer*)clientData;
|
||||
sqlite3_bgckpt_destroy(pCkpt);
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: $ckpt SUBCMD ...
|
||||
*/
|
||||
static int SQLITE_TCLAPI bgckpt_obj_cmd(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
Checkpointer *pCkpt = (Checkpointer*)clientData;
|
||||
const char *aCmd[] = { "checkpoint", "destroy", 0 };
|
||||
int iCmd;
|
||||
|
||||
if( objc<2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SUBCMD ...");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( Tcl_GetIndexFromObj(interp, objv[1], aCmd, "sub-command", 0, &iCmd) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
switch( iCmd ){
|
||||
case 0: {
|
||||
int rc;
|
||||
int bBlock = 0;
|
||||
|
||||
if( objc>3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?BLOCKING?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( objc==3 && Tcl_GetBooleanFromObj(interp, objv[2], &bBlock) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = sqlite3_bgckpt_checkpoint(pCkpt, bBlock);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: bgckpt CMDNAME FILENAME
|
||||
*/
|
||||
static int SQLITE_TCLAPI bgckpt_cmd(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
const char *zCmd;
|
||||
const char *zFilename;
|
||||
int rc;
|
||||
Checkpointer *pCkpt;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CMDNAME FILENAME");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zCmd = Tcl_GetString(objv[1]);
|
||||
zFilename = Tcl_GetString(objv[2]);
|
||||
|
||||
rc = sqlite3_bgckpt_create(zFilename, &pCkpt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_CreateObjCommand(interp, zCmd, bgckpt_obj_cmd, (void*)pCkpt, bgckpt_del);
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int Bgckpt_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(interp, "bgckpt", bgckpt_cmd, 0, 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#else
|
||||
# include "tclsqlite.h"
|
||||
int Bgckpt_Init(Tcl_Interp *interp){ return TCL_OK; }
|
||||
#endif
|
@ -1,10 +1,7 @@
|
||||
_fiddle_exec
|
||||
_fiddle_interrupt
|
||||
_fiddle_experiment
|
||||
_fiddle_the_db
|
||||
_fiddle_db_arg
|
||||
_fiddle_db_filename
|
||||
_fiddle_exec
|
||||
_fiddle_experiment
|
||||
_fiddle_interrupt
|
||||
_fiddle_main
|
||||
_fiddle_reset_db
|
||||
_fiddle_db_handle
|
||||
_fiddle_db_vfs
|
||||
_fiddle_export_db
|
72
ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api
Normal file
72
ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api
Normal file
@ -0,0 +1,72 @@
|
||||
_sqlite3_bind_blob
|
||||
_sqlite3_bind_double
|
||||
_sqlite3_bind_int
|
||||
_sqlite3_bind_int64
|
||||
_sqlite3_bind_null
|
||||
_sqlite3_bind_parameter_count
|
||||
_sqlite3_bind_parameter_index
|
||||
_sqlite3_bind_text
|
||||
_sqlite3_changes
|
||||
_sqlite3_changes64
|
||||
_sqlite3_clear_bindings
|
||||
_sqlite3_close_v2
|
||||
_sqlite3_column_blob
|
||||
_sqlite3_column_bytes
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_double
|
||||
_sqlite3_column_int
|
||||
_sqlite3_column_int64
|
||||
_sqlite3_column_name
|
||||
_sqlite3_column_text
|
||||
_sqlite3_column_type
|
||||
_sqlite3_compileoption_get
|
||||
_sqlite3_compileoption_used
|
||||
_sqlite3_create_function_v2
|
||||
_sqlite3_data_count
|
||||
_sqlite3_db_filename
|
||||
_sqlite3_db_name
|
||||
_sqlite3_errmsg
|
||||
_sqlite3_error_offset
|
||||
_sqlite3_errstr
|
||||
_sqlite3_exec
|
||||
_sqlite3_expanded_sql
|
||||
_sqlite3_extended_errcode
|
||||
_sqlite3_extended_result_codes
|
||||
_sqlite3_finalize
|
||||
_sqlite3_initialize
|
||||
_sqlite3_interrupt
|
||||
_sqlite3_libversion
|
||||
_sqlite3_libversion_number
|
||||
_sqlite3_open
|
||||
_sqlite3_open_v2
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_reset
|
||||
_sqlite3_result_blob
|
||||
_sqlite3_result_double
|
||||
_sqlite3_result_error
|
||||
_sqlite3_result_error_code
|
||||
_sqlite3_result_error_nomem
|
||||
_sqlite3_result_error_toobig
|
||||
_sqlite3_result_int
|
||||
_sqlite3_result_null
|
||||
_sqlite3_result_text
|
||||
_sqlite3_sourceid
|
||||
_sqlite3_sql
|
||||
_sqlite3_step
|
||||
_sqlite3_strglob
|
||||
_sqlite3_strlike
|
||||
_sqlite3_total_changes
|
||||
_sqlite3_total_changes64
|
||||
_sqlite3_value_blob
|
||||
_sqlite3_value_bytes
|
||||
_sqlite3_value_double
|
||||
_sqlite3_value_text
|
||||
_sqlite3_value_type
|
||||
_sqlite3_vfs_find
|
||||
_sqlite3_vfs_register
|
||||
_sqlite3_wasm_db_error
|
||||
_sqlite3_wasm_enum_json
|
||||
_malloc
|
||||
_free
|
@ -1,155 +0,0 @@
|
||||
_malloc
|
||||
_free
|
||||
_realloc
|
||||
_sqlite3_aggregate_context
|
||||
_sqlite3_auto_extension
|
||||
_sqlite3_bind_blob
|
||||
_sqlite3_bind_double
|
||||
_sqlite3_bind_int
|
||||
_sqlite3_bind_int64
|
||||
_sqlite3_bind_null
|
||||
_sqlite3_bind_parameter_count
|
||||
_sqlite3_bind_parameter_index
|
||||
_sqlite3_bind_parameter_name
|
||||
_sqlite3_bind_pointer
|
||||
_sqlite3_bind_text
|
||||
_sqlite3_busy_handler
|
||||
_sqlite3_busy_timeout
|
||||
_sqlite3_cancel_auto_extension
|
||||
_sqlite3_changes
|
||||
_sqlite3_changes64
|
||||
_sqlite3_clear_bindings
|
||||
_sqlite3_close_v2
|
||||
_sqlite3_collation_needed
|
||||
_sqlite3_column_blob
|
||||
_sqlite3_column_bytes
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_decltype
|
||||
_sqlite3_column_double
|
||||
_sqlite3_column_int
|
||||
_sqlite3_column_int64
|
||||
_sqlite3_column_name
|
||||
_sqlite3_column_text
|
||||
_sqlite3_column_type
|
||||
_sqlite3_column_value
|
||||
_sqlite3_commit_hook
|
||||
_sqlite3_compileoption_get
|
||||
_sqlite3_compileoption_used
|
||||
_sqlite3_complete
|
||||
_sqlite3_context_db_handle
|
||||
_sqlite3_create_collation
|
||||
_sqlite3_create_collation_v2
|
||||
_sqlite3_create_function
|
||||
_sqlite3_create_function_v2
|
||||
_sqlite3_data_count
|
||||
_sqlite3_db_filename
|
||||
_sqlite3_db_handle
|
||||
_sqlite3_db_name
|
||||
_sqlite3_db_readonly
|
||||
_sqlite3_db_status
|
||||
_sqlite3_deserialize
|
||||
_sqlite3_errcode
|
||||
_sqlite3_errmsg
|
||||
_sqlite3_error_offset
|
||||
_sqlite3_errstr
|
||||
_sqlite3_exec
|
||||
_sqlite3_expanded_sql
|
||||
_sqlite3_extended_errcode
|
||||
_sqlite3_extended_result_codes
|
||||
_sqlite3_file_control
|
||||
_sqlite3_finalize
|
||||
_sqlite3_free
|
||||
_sqlite3_get_auxdata
|
||||
_sqlite3_get_autocommit
|
||||
_sqlite3_initialize
|
||||
_sqlite3_interrupt
|
||||
_sqlite3_is_interrupted
|
||||
_sqlite3_keyword_count
|
||||
_sqlite3_keyword_name
|
||||
_sqlite3_keyword_check
|
||||
_sqlite3_last_insert_rowid
|
||||
_sqlite3_libversion
|
||||
_sqlite3_libversion_number
|
||||
_sqlite3_limit
|
||||
_sqlite3_malloc
|
||||
_sqlite3_malloc64
|
||||
_sqlite3_msize
|
||||
_sqlite3_open
|
||||
_sqlite3_open_v2
|
||||
_sqlite3_overload_function
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_randomness
|
||||
_sqlite3_realloc
|
||||
_sqlite3_realloc64
|
||||
_sqlite3_reset
|
||||
_sqlite3_reset_auto_extension
|
||||
_sqlite3_result_blob
|
||||
_sqlite3_result_double
|
||||
_sqlite3_result_error
|
||||
_sqlite3_result_error_code
|
||||
_sqlite3_result_error_nomem
|
||||
_sqlite3_result_error_toobig
|
||||
_sqlite3_result_int
|
||||
_sqlite3_result_int64
|
||||
_sqlite3_result_null
|
||||
_sqlite3_result_pointer
|
||||
_sqlite3_result_subtype
|
||||
_sqlite3_result_text
|
||||
_sqlite3_result_zeroblob
|
||||
_sqlite3_result_zeroblob64
|
||||
_sqlite3_rollback_hook
|
||||
_sqlite3_serialize
|
||||
_sqlite3_set_auxdata
|
||||
_sqlite3_set_last_insert_rowid
|
||||
_sqlite3_shutdown
|
||||
_sqlite3_sourceid
|
||||
_sqlite3_sql
|
||||
_sqlite3_status
|
||||
_sqlite3_status64
|
||||
_sqlite3_step
|
||||
_sqlite3_stmt_busy
|
||||
_sqlite3_stmt_explain
|
||||
_sqlite3_stmt_isexplain
|
||||
_sqlite3_stmt_readonly
|
||||
_sqlite3_stmt_status
|
||||
_sqlite3_strglob
|
||||
_sqlite3_stricmp
|
||||
_sqlite3_strlike
|
||||
_sqlite3_strnicmp
|
||||
_sqlite3_table_column_metadata
|
||||
_sqlite3_total_changes
|
||||
_sqlite3_total_changes64
|
||||
_sqlite3_trace_v2
|
||||
_sqlite3_txn_state
|
||||
_sqlite3_update_hook
|
||||
_sqlite3_uri_boolean
|
||||
_sqlite3_uri_int64
|
||||
_sqlite3_uri_key
|
||||
_sqlite3_uri_parameter
|
||||
_sqlite3_user_data
|
||||
_sqlite3_value_blob
|
||||
_sqlite3_value_bytes
|
||||
_sqlite3_value_double
|
||||
_sqlite3_value_dup
|
||||
_sqlite3_value_free
|
||||
_sqlite3_value_frombind
|
||||
_sqlite3_value_int
|
||||
_sqlite3_value_int64
|
||||
_sqlite3_value_nochange
|
||||
_sqlite3_value_numeric_type
|
||||
_sqlite3_value_pointer
|
||||
_sqlite3_value_subtype
|
||||
_sqlite3_value_text
|
||||
_sqlite3_value_type
|
||||
_sqlite3_vfs_find
|
||||
_sqlite3_vfs_register
|
||||
_sqlite3_vfs_unregister
|
||||
_sqlite3_vtab_collation
|
||||
_sqlite3_vtab_distinct
|
||||
_sqlite3_vtab_in
|
||||
_sqlite3_vtab_in_first
|
||||
_sqlite3_vtab_in_next
|
||||
_sqlite3_vtab_nochange
|
||||
_sqlite3_vtab_on_conflict
|
||||
_sqlite3_vtab_rhs_value
|
@ -1,4 +1,3 @@
|
||||
//#ifnot omit-oo1
|
||||
/*
|
||||
2022-08-24
|
||||
|
||||
@ -42,13 +41,9 @@
|
||||
- `onready` (optional, but...): this callback is called with no
|
||||
arguments when the worker fires its initial
|
||||
'sqlite3-api'/'worker1-ready' message, which it does when
|
||||
sqlite3.initWorker1API() completes its initialization. This is the
|
||||
simplest way to tell the worker to kick off work at the earliest
|
||||
opportunity, and the only way to know when the worker module has
|
||||
completed loading. The irony of using a callback for this, instead
|
||||
of returning a promise from sqlite3Worker1Promiser() is not lost on
|
||||
the developers: see sqlite3Worker1Promiser.v2() which uses a
|
||||
Promise instead.
|
||||
sqlite3.initWorker1API() completes its initialization. This is
|
||||
the simplest way to tell the worker to kick off work at the
|
||||
earliest opportunity.
|
||||
|
||||
- `onunhandled` (optional): a callback which gets passed the
|
||||
message event object for any worker.onmessage() events which
|
||||
@ -119,7 +114,7 @@
|
||||
by all client code except that which tests this API. The `row`
|
||||
property contains the row result in the form implied by the
|
||||
`rowMode` option (defaulting to `'array'`). The `rowNumber` is a
|
||||
1-based integer value incremented by 1 on each call into the
|
||||
1-based integer value incremented by 1 on each call into th
|
||||
callback.
|
||||
|
||||
At the end of the result set, the same event is fired with
|
||||
@ -127,17 +122,8 @@
|
||||
the end of the result set has been reached. Note that the rows
|
||||
arrive via worker-posted messages, with all the implications
|
||||
of that.
|
||||
|
||||
Notable shortcomings:
|
||||
|
||||
- This API was not designed with ES6 modules in mind. Neither Firefox
|
||||
nor Safari support, as of March 2023, the {type:"module"} flag to the
|
||||
Worker constructor, so that particular usage is not something we're going
|
||||
to target for the time being:
|
||||
|
||||
https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
|
||||
*/
|
||||
globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
// Inspired by: https://stackoverflow.com/a/52439530
|
||||
if(1===arguments.length && 'function'===typeof arguments[0]){
|
||||
const f = config;
|
||||
@ -160,7 +146,6 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
if(!config.worker) config.worker = callee.defaultConfig.worker;
|
||||
if('function'===typeof config.worker) config.worker = config.worker();
|
||||
let dbId;
|
||||
let promiserFunc;
|
||||
config.worker.onmessage = function(ev){
|
||||
ev = ev.data;
|
||||
debug('worker1.onmessage',ev);
|
||||
@ -168,14 +153,14 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
if(!msgHandler){
|
||||
if(ev && 'sqlite3-api'===ev.type && 'worker1-ready'===ev.result) {
|
||||
/*fired one time when the Worker1 API initializes*/
|
||||
if(config.onready) config.onready(promiserFunc);
|
||||
if(config.onready) config.onready();
|
||||
return;
|
||||
}
|
||||
msgHandler = handlerMap[ev.type] /* check for exec per-row callback */;
|
||||
if(msgHandler && msgHandler.onrow){
|
||||
msgHandler.onrow(ev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(config.onunhandled) config.onunhandled(arguments[0]);
|
||||
else err("sqlite3Worker1Promiser() unhandled worker message:",ev);
|
||||
return;
|
||||
@ -197,19 +182,19 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
try {msgHandler.resolve(ev)}
|
||||
catch(e){msgHandler.reject(e)}
|
||||
}/*worker.onmessage()*/;
|
||||
return promiserFunc = function(/*(msgType, msgArgs) || (msgEnvelope)*/){
|
||||
return function(/*(msgType, msgArgs) || (msgEnvelope)*/){
|
||||
let msg;
|
||||
if(1===arguments.length){
|
||||
msg = arguments[0];
|
||||
}else if(2===arguments.length){
|
||||
msg = Object.create(null);
|
||||
msg.type = arguments[0];
|
||||
msg.args = arguments[1];
|
||||
msg.dbId = msg.args.dbId;
|
||||
msg = {
|
||||
type: arguments[0],
|
||||
args: arguments[1]
|
||||
};
|
||||
}else{
|
||||
toss("Invalid arguments for sqlite3Worker1Promiser()-created factory.");
|
||||
toss("Invalid arugments for sqlite3Worker1Promiser()-created factory.");
|
||||
}
|
||||
if(!msg.dbId && msg.type!=='open') msg.dbId = dbId;
|
||||
if(!msg.dbId) msg.dbId = dbId;
|
||||
msg.messageId = genMsgId(msg);
|
||||
msg.departureTime = performance.now();
|
||||
const proxy = Object.create(null);
|
||||
@ -251,96 +236,28 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
return p;
|
||||
};
|
||||
}/*sqlite3Worker1Promiser()*/;
|
||||
|
||||
globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
self.sqlite3Worker1Promiser.defaultConfig = {
|
||||
worker: function(){
|
||||
//#if target=es6-module
|
||||
return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{
|
||||
type: 'module'
|
||||
});
|
||||
//#if target=es6-bundler-friendly
|
||||
return new Worker("sqlite3-worker1.js");
|
||||
//#else
|
||||
let theJs = "sqlite3-worker1.js";
|
||||
if(this.currentScript){
|
||||
const src = this.currentScript.src.split('/');
|
||||
src.pop();
|
||||
theJs = src.join('/')+'/' + theJs;
|
||||
//sqlite3.config.warn("promiser currentScript, theJs =",this.currentScript,theJs);
|
||||
}else if(globalThis.location){
|
||||
//sqlite3.config.warn("promiser globalThis.location =",globalThis.location);
|
||||
const urlParams = new URL(globalThis.location.href).searchParams;
|
||||
//console.warn("promiser currentScript, theJs =",this.currentScript,theJs);
|
||||
}else{
|
||||
//console.warn("promiser self.location =",self.location);
|
||||
const urlParams = new URL(self.location.href).searchParams;
|
||||
if(urlParams.has('sqlite3.dir')){
|
||||
theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
|
||||
}
|
||||
}
|
||||
return new Worker(theJs + globalThis.location.search);
|
||||
return new Worker(theJs + self.location.search);
|
||||
//#endif
|
||||
}
|
||||
//#ifnot target=es6-module
|
||||
.bind({
|
||||
currentScript: globalThis?.document?.currentScript
|
||||
})
|
||||
//#endif
|
||||
,
|
||||
}.bind({
|
||||
currentScript: self?.document?.currentScript
|
||||
}),
|
||||
onerror: (...args)=>console.error('worker1 promiser error',...args)
|
||||
}/*defaultConfig*/;
|
||||
|
||||
/**
|
||||
sqlite3Worker1Promiser.v2(), added in 3.46, works identically to
|
||||
sqlite3Worker1Promiser() except that it returns a Promise instead
|
||||
of relying an an onready callback in the config object. The Promise
|
||||
resolves to the same factory function which
|
||||
sqlite3Worker1Promiser() returns.
|
||||
|
||||
If config is-a function or is an object which contains an onready
|
||||
function, that function is replaced by a proxy which will resolve
|
||||
after calling the original function and will reject if that
|
||||
function throws.
|
||||
*/
|
||||
sqlite3Worker1Promiser.v2 = function(config){
|
||||
let oldFunc;
|
||||
if( 'function' == typeof config ){
|
||||
oldFunc = config;
|
||||
config = {};
|
||||
}else if('function'===typeof config?.onready){
|
||||
oldFunc = config.onready;
|
||||
delete config.onready;
|
||||
}
|
||||
const promiseProxy = Object.create(null);
|
||||
config = Object.assign((config || Object.create(null)),{
|
||||
onready: async function(func){
|
||||
try {
|
||||
if( oldFunc ) await oldFunc(func);
|
||||
promiseProxy.resolve(func);
|
||||
}
|
||||
catch(e){promiseProxy.reject(e)}
|
||||
}
|
||||
});
|
||||
const p = new Promise(function(resolve,reject){
|
||||
promiseProxy.resolve = resolve;
|
||||
promiseProxy.reject = reject;
|
||||
});
|
||||
try{
|
||||
this.original(config);
|
||||
}catch(e){
|
||||
promiseProxy.reject(e);
|
||||
}
|
||||
return p;
|
||||
}.bind({
|
||||
/* We do this because clients are
|
||||
recommended to delete globalThis.sqlite3Worker1Promiser. */
|
||||
original: sqlite3Worker1Promiser
|
||||
});
|
||||
|
||||
//#if target=es6-module
|
||||
/**
|
||||
When built as a module, we export sqlite3Worker1Promiser.v2()
|
||||
instead of sqlite3Worker1Promise() because (A) its interface is more
|
||||
conventional for ESM usage and (B) the ESM option export option for
|
||||
this API did not exist until v2 was created, so there's no backwards
|
||||
incompatibility.
|
||||
*/
|
||||
export default sqlite3Worker1Promiser.v2;
|
||||
//#endif /* target=es6-module */
|
||||
//#else
|
||||
/* Built with the omit-oo1 flag. */
|
||||
//#endif ifnot omit-oo1
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
two lines and ensure that these files are on the web server. -->
|
||||
<!--script src="jqterm/jqterm-bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="jqterm/jquery.terminal.min.css"/-->
|
||||
<link rel="stylesheet" href="emscripten.css"/>
|
||||
<style>
|
||||
/* The following styles are for app-level use. */
|
||||
:root {
|
||||
@ -170,31 +171,6 @@
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
/* emcscript-related styling, used during the module load/intialization processes... */
|
||||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { border: 1px solid black; }
|
||||
#module-spinner { overflow: visible; }
|
||||
#module-spinner > * {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.spinner {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin: 0px auto;
|
||||
animation: rotation 0.8s linear infinite;
|
||||
border-left: 10px solid rgb(0,150,240);
|
||||
border-right: 10px solid rgb(0,150,240);
|
||||
border-bottom: 10px solid rgb(0,150,240);
|
||||
border-top: 10px solid rgb(100,0,200);
|
||||
border-radius: 100%;
|
||||
background-color: rgb(200,100,250);
|
||||
}
|
||||
@keyframes rotation {
|
||||
from {transform: rotate(0deg);}
|
||||
to {transform: rotate(360deg);}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -297,6 +273,11 @@
|
||||
</fieldset>
|
||||
</div>
|
||||
</div> <!-- #view-split -->
|
||||
<!-- Maintenance notes:
|
||||
|
||||
... TODO... currently being refactored...
|
||||
|
||||
-->
|
||||
<script src="fiddle.js"></script>
|
||||
</body>
|
||||
</html>
|
1
main.mk
1
main.mk
@ -671,6 +671,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/basexx.c \
|
||||
$(TOP)/ext/misc/bgckpt.c \
|
||||
$(TOP)/ext/misc/carray.c \
|
||||
$(TOP)/ext/misc/cksumvfs.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
|
80
manifest
80
manifest
@ -1,11 +1,11 @@
|
||||
C Update\sthe\scompile-for-*.md\sdocuments.
|
||||
D 2024-10-25T15:28:00.541
|
||||
C Merge\sthe\slatest\strunk\senhancements\sand\sespecially\sthe\sautosetup\schanges\ninto\sthe\swal2\sbranch.
|
||||
D 2024-10-25T19:40:29.762
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md b6e6c1baf38e4339bd3f1e0e5e5bfd0a9a93d133360691b2785c2d4b2f2dcec2
|
||||
F Makefile.in 5a95c68b70be1448a6f226c09c1df5e338cc496e70987173fcfdca9ad94cb5a4
|
||||
F Makefile.linux-generic 8df0e6ee5e4671f844caf27f88d2be7421e904639f7a0ffdce0e2cd4ea11e8c0
|
||||
F Makefile.msc 28318970f86f601ac79b5e6a514a52fb33a1526d0e0e915b4edc2f41846c1d4a
|
||||
F Makefile.linux-generic 8df0e6ee5e4671f844caf27f88d2be7421e904639f7a0ffdce0e2cd4ea11e8c0 w Makefile.linux-gcc
|
||||
F Makefile.msc 8219d6072fc0727edc0b3be355f08364d32587a62bbff788a2c5bbc08f9c9dd3
|
||||
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
|
||||
F VERSION 8dc0c3df15fd5ff0622f88fc483533fce990b1cbb2f5fb9fdfb4dbd71eef2889
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@ -67,6 +67,7 @@ F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d
|
||||
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F doc/wal-lock.md 781726aaba20bafeceb7ba9f91d5c98c6731691b30c954e37cf0b49a053d461d
|
||||
F doc/wal2.md a807405a05e19a4945c5905a9ffa0fe45b8560dd7572461192501f565c19cdb5
|
||||
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
@ -406,6 +407,7 @@ F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e
|
||||
F ext/misc/base64.c a71b131e50300c654a66c469a25b62874481f3d1cb3beb56aca9a68edd812e0d
|
||||
F ext/misc/base85.c 073054111988db593ef5fdb87ab8c459df1ea0c3aaaddf0f5bfa3d72b7e6280a
|
||||
F ext/misc/basexx.c 89ad6b76558efbceb627afd5e2ef1d84b2e96d9aaf9b7ecb20e3d00b51be6fcf
|
||||
F ext/misc/bgckpt.c 18cfc9c39ffab3299f730f86ae2991c8574c0bd9ec80efd2f89196798a7b7181
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
F ext/misc/btreeinfo.c cb952620eedf5c0b7625b678f0f08e54d2ec0011d4e50efda5ebdc97f3df7d04
|
||||
F ext/misc/carray.c 34fac63770971611c5285de0a9f0ac67d504eaf66be891f637add9290f1c76a5
|
||||
@ -622,7 +624,7 @@ F ext/session/test_session.c aa29abdcc9011ac02f4fa38e8ede226106eaeee7c3ea7d8b2b9
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
|
||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
|
||||
F ext/wasm/GNUmakefile 311aa0d5edc7006409962cc77cc26560d92f9be69c2c4302e8bbc68189fd02db
|
||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||
@ -631,7 +633,7 @@ F ext/wasm/SQLTester/SQLTester.mjs 66e1adc3d79467b68e3e40614fd42c1a577c7e219ec09
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0
|
||||
F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 2bcbbfe3b95c043ed6037e2708a2ee078d212dd1612c364f93588d8dc97300fe
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c5eaceabb9e759aaae7d3101a4a3e542f96ab2c99d89a80ce20ec18c23115f33
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||
@ -653,7 +655,7 @@ F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js bb5e96cd0fd6e1e54538256433f1c60a
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 9b86ca2d8276cf919fbc9ba2a10e9786033b64f92c2db844d951804dee6c4b4e
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
|
||||
F ext/wasm/api/sqlite3-wasm.c 83f5e9f998e9fa4261eb84e9f092210e3ffe03895119f5ded0429eb34ab9d2be
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46f303ba8ddd1b2f0a391798837beddfa72e8c897038c8047eda49ce7d5ed46b
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js f10c3ecd9df06f6320073c2ce230a7ed7c56034d8b88c1e57095f2a97faf423a
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
@ -677,8 +679,8 @@ F ext/wasm/dist.make 653e212c1e84aa3be168d62a10616ccea45ee9585b0192745d2706707a5
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make ec2353f0eddade864f67b993376a0949e27b72465c24b1970940e48b70bc2df1
|
||||
F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
|
||||
F ext/wasm/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
|
||||
F ext/wasm/fiddle/fiddle.js b444a5646a9aac9f3fc06c53d78af5e1912eb235d69a8e6010723e4eb0e9d4a1
|
||||
F ext/wasm/fiddle/index.html c79b1741cbeba78f88af0a84cf5ec7de87a909a6a8d10a369b1f4824c66c2088
|
||||
F ext/wasm/index-dist.html 564b5ec5669676482c5a25dea9e721d8eafed426ecb155f93d29aeff8507511f
|
||||
F ext/wasm/index.html e4bbffdb3d40eff12b3f9c7abedef91787e2935620b7f8d40f2c774b80ad8fa9
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
||||
@ -707,7 +709,7 @@ F ext/wasm/wasmfs.make bc8bb227f35d5bd3863a7bd2233437c37472a0d81585979f058f9b9b5
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk a26d970036f31c538426ff12d7bb99384402bec16aeef63ac6f795531143fabc
|
||||
F main.mk 9f7af0da18c747bcc894a55d525509ca960ad713149b7b508bd14bb0dcc767ba
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@ -726,13 +728,13 @@ F src/auth.c 4c1ea890e0069ad73bead5d17a5b12c34cfa4f1a24175c8147ea439b64be271c
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c 63ca6b647342e8cef643863cd0962a542f133e1069460725ba4461dcda92b03c
|
||||
F src/btree.c 8d5a555642cf2fbae9735445eda1640316ab3401c02401efb73c1d1d88612399
|
||||
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c 3a1840d9d171ce2d24f4c1f7acda7266ab796c664290c1acba65ff98ce2bd01e
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
|
||||
F src/ctime.c 193f6f9a75204274b7e7f45ac6d6517c12c70b55a5dfb39312dfc3a52e2a8138
|
||||
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
|
||||
F src/dbpage.c db1be8adaf1f839ad733c08baeac5c22aa912f7b535865c0c061382602081360
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
@ -774,13 +776,13 @@ F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d87210
|
||||
F src/os_unix.c 0ad4e0885294b3a0e135a18533590ec9ad91ffe82f6a08e55b40babd51772928
|
||||
F src/os_win.c 69fa1aaff68270423c85cff4327ba17ef99a1eb017e1a2bfb97416d9b8398b05
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 9656ad4e8331efb8a4f94f7a0c6440b98caea073950a367ea0c728a53b8e62c9
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/pager.c 2f89b83e0a85635ebae908325029a21bd6cdcc0c604e9289354215fb6c3e4ec3
|
||||
F src/pager.h fc0c95d27f2aefffcb39b4373b3557e89e1b4b9a36b183cc04d6f22002bf0ad2
|
||||
F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
|
||||
F src/pragma.c cd613126f7cdd0c2ded4648c3c7b7b0239e678d7f3489e88c4b6d6858372fd07
|
||||
F src/pragma.c 92daeda7cadb4d96564f9326a6558e1eb73b81afab584e188b7b8b9463de5cec
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c 3ba0ad907b7773ed642f66cea8a2c9c8edc18841aa1050b6218dbb3479e86225
|
||||
F src/printf.c 6a87534ebfb9e5346011191b1f3a7ebc457f5938c7e4feeea478ecf53f6a41b2
|
||||
@ -818,7 +820,7 @@ F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c9
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
F src/test_fs.c c411c40baba679536fc34e2679349f59d8225570aed3488b5b3ef1908525a3d5
|
||||
F src/test_func.c 8c0e89192f70fac307822d1ac2911ee51751288780b3db0c5ab5ca75fa0fe851
|
||||
F src/test_hexio.c 0f777bf9fbb2684bb4978372bacc90ef7337d5d9e3cebe067a9409941e88bacf
|
||||
F src/test_hexio.c 7449504e4bde876ba91b202617a9228c7c8c2e7bd8b957302f3803ac0e9e353c
|
||||
F src/test_init.c 17313332d58e90defc527129d5eda4a08bd6b6e8de7207a231523c8d98fb445e
|
||||
F src/test_intarray.c e4216aadee9df2de7d1aee7e70f6b22c80ee79ece72a63d57105db74217639e5
|
||||
F src/test_intarray.h 6c3534641108cd1bea517a8e117dcba237081310a29a4c35bd2190caa8972293
|
||||
@ -839,7 +841,7 @@ F src/test_schema.c b06d3ddc3edc173c143878f3edb869dd200d57d918ae2f38820534f9a5e3
|
||||
F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
|
||||
F src/test_superlock.c 18355ca274746aa6909e3744163e5deb1196a85d5bc64b9cd377273cef626da7
|
||||
F src/test_syscall.c 9ad7ab39910c16d29411678d91b0d27a7a996a718df5ee93dcd635e846d0275c
|
||||
F src/test_tclsh.c 6077f2bdc6b4ea2bace2a0cd6ea48e0a4651007ae7382c13efc0c495eb0c6956
|
||||
F src/test_tclsh.c efa390787ecfbae22e0a0a05d9ee771a9db78ffd84e2eea092899c2d80d57b0e
|
||||
F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e048424
|
||||
F src/test_thread.c d7a8bcea7445f37cc2a1f7f81dd6059634f45e0c61bfe80182b02872fb0328bb
|
||||
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
|
||||
@ -857,11 +859,11 @@ F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba
|
||||
F src/util.c ceebf912f673247e305f16f97f0bb7285fca1d37413b79680714a553a9021d33
|
||||
F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
|
||||
F src/vdbe.c 1f56a0ae24115c2e37213e77cf79aa3b8c8d0366755707385564f6b8dd83d0fb
|
||||
F src/vdbe.c 8fa7f0fc9a90791e86dd254c20b2426415254981aa79547eef8da7bc41e90f69
|
||||
F src/vdbe.h c2549a215898a390de6669cfa32adba56f0d7e17ba5a7f7b14506d6fd5f0c36a
|
||||
F src/vdbeInt.h af7d7e8291edd0b19f2cd698e60e4d4031078f9a2f2328ac8f0b7efb134f8a1d
|
||||
F src/vdbeapi.c 53c7e26a2c0821a892b20eee2cde4656e31998212f3d515576c780dfaa45fd17
|
||||
F src/vdbeaux.c f06f011e4fac948941ea821ac365a9f1c163ef473e63756d6e499a37c6bda9ef
|
||||
F src/vdbeaux.c 7a87d215ea1814160634748ebebd919c921984e60ddef91fc3161480ff623ddc
|
||||
F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797
|
||||
F src/vdbemem.c df568ef0187e4be2788c35174f6d9b8566ab9475f9aff2d73907ed05aa5684b2
|
||||
F src/vdbesort.c d0a3c7056c081703c8b6d91ad60f17da5e062a5c64bf568ed0fa1b5f4cae311f
|
||||
@ -869,8 +871,8 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c 316cd48e9320660db3047cd306cd056e4361180cebb4d0f10a39244e10c11422
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 8b7e309a8012659ac9275ad8cdcc6acaf73fa04b1090e38a01335f230fd10681
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/wal.c 70d127be90923ec33cc53f7206d947173f1e4e4a98b34115d92861e1584e36ef
|
||||
F src/wal.h 97b8a9903387401377b59507e86b93a148ef1ad4e5ce0f23659a12dcdce56af2
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c 4de9e7ca5f49e4a21c1d733e2b2fbbc8b62b1a157a58a562c569da84cfcb005b
|
||||
F src/whereInt.h 1e36ec50392f7cc3d93d1152d4338064cd522b87156a0739388b7e273735f0ca
|
||||
@ -1047,7 +1049,7 @@ F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
|
||||
F test/corrupt7.test ffa86896fe63a3d00b0a131e1e64f402e4da9f7e5d89609d6501c851e511d73a
|
||||
F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
|
||||
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
|
||||
F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
|
||||
F test/corruptA.test 56e8f321adaf3411960e9d2c7136669d8e1a91cbde6cf401ea84e6d6c7ccbe10
|
||||
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
|
||||
F test/corruptC.test 7d6d9e907334ea3ccb7111a0656cafa30a28f8a5f2aaf1c45ad712236302856a
|
||||
F test/corruptD.test 614320aa519f6bf6c7dd2f581f9513ff7b6826954180cca1a606d0e25ea084a3
|
||||
@ -1540,7 +1542,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
|
||||
F test/percentile.test 52ba89d6ee6b65f770972b67dace358bab7cdbd532803d3db157845268e789cd
|
||||
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
|
||||
F test/permutations.test e285997e45dfbb522ca1ba2e034a008a905b30a369690022c68f926a4229033e
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
@ -1565,7 +1567,7 @@ F test/quote.test 7b01b2a261bc26d9821aea9f4941ce1e08191d62fc55ba8862440fb3a59197
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/rdonly.test 21e99ee237265d0cf95a0c84b50c784e834acaa4ef05d92a27b262626a656682
|
||||
F test/readonly.test 69a7ccec846cad2e000b3539d56360d02f327061dc5e41f7f9a3e01f19719952
|
||||
F test/recover.test a163a156ea9f2beea63fa83c4dcd8dea6e57b8a569fc647155e3d2754eaac1b5
|
||||
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
|
||||
@ -1596,11 +1598,11 @@ F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972
|
||||
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
|
||||
F test/savepoint.test 6e9804a17767f08432c7a5e738b9a8f4b891d243110b63d3a41d270d3d1378ec
|
||||
F test/savepoint.test 63a120ec4fbbd5025b238c259d12ed0516fbf4bca6384041cb995ade9a5f00d2
|
||||
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
|
||||
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
|
||||
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
|
||||
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint6.test 48a645a7bb3a59a6fcf06a7364cfe5b655c336760de39068f7c241b0fc80d963
|
||||
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
|
||||
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
|
||||
F test/scanstatus.test b249328caf4d317e71058006872b8012598a5fa045b30bf24a81eeff650ab49e
|
||||
@ -1735,7 +1737,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 7b44f1a9b9a2de8112695b908afc21dd9a68cd2d44e84b73f1b27b53492c0d59
|
||||
F test/tester.tcl b1ffedf6bc6e0044448813e37f3ec3496e35268c35802a508f2f013cf5f74247
|
||||
F test/testrunner.tcl bc1a8d21a1aa3a5cf7c4883cbee4b6748790fe960fad06ca5db74ec914bd6525 x
|
||||
F test/testrunner_data.tcl e3037f54cdb67479827cdfe8b8962a38811a496c1ad81956c085c64aa34e7a12
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
@ -1958,7 +1960,7 @@ F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3
|
||||
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
|
||||
F test/upsert5.test 9953b180d02d1369cdbb6c73c900834e5fef8cb78e98e07511c8762ec21cc176
|
||||
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
|
||||
F test/uri.test c1abaaaa28e9422d61e5f3f9cbc8ef993ec49fe802f581520731708561d49384
|
||||
F test/uri.test 8f27eaa41804099fca15101e30fd1b29aebbebf32d4e3c24614fa6319216936d
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
|
||||
@ -2004,8 +2006,20 @@ F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/vtabdistinct.test 7688f0889358f849fd60bbfde1ded38b014b18066076d4bfbb75395804dfe072
|
||||
F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12
|
||||
F test/vtabrhs1.test 9b5ecbc74a689500c33a4b2b36761f9bcc22fcc4e3f9d21066ee0c9c74cf5f6c
|
||||
F test/wal.test 519c550255c78f55959e9159b93ebbfad2b4e9f36f5b76284da41f572f9d27da
|
||||
F test/wal.test a5d6c7f4bd79251ed344229d96d44ecdfb896bdbd32b7e65f118756699c7e473
|
||||
F test/wal2.test 44fe1cb4935dbbddfa0a34c2c4fd90f0ba8654d59b83c4136eb90fb327fd264f
|
||||
F test/wal2big.test 829141cbecdda4329db8fa38705424c4a73db72a06b9540b06811a825d330409
|
||||
F test/wal2fault.test 2e8e60cacd5bcd451618aeffd05f676894d17202d3e2986e288d36e2c5993249
|
||||
F test/wal2lock.test 0ef98d72dc6bcf7711dedd684760488400d9a9a6eec0dc5d3822060437793552
|
||||
F test/wal2openclose.test 2b26be723ea7f4263c8d5d70b37efd1c359561a0526e39466c45fe8e6478daee
|
||||
F test/wal2recover.test 348a3f2a4c79359790f70fd692dcd0c8f04e42a85365e688778c945e10bae02b
|
||||
F test/wal2recover2.test 3fe5d5932b16a3a38304a85bafed1f965faef40c230fd450838a0502e61343bb
|
||||
F test/wal2recover3.test 4a91689e165a38bc401736e6518188c2b0ff4fa1566d1810b8867536db128177
|
||||
F test/wal2rewrite.test 6ca6f631ffcf871240beab5f02608913fd075c6d0d31310b026c8383c65c9f9c
|
||||
F test/wal2rollback.test 23adc4a099b23f6aaea8b04fdca1c35861d887dd80f8be7da2d5273eb777e428
|
||||
F test/wal2savepoint.test c380512ec1f97012cfc753e718bf3df38f51e7c319110e1cae25094a33b371c4
|
||||
F test/wal2simple.test 320a08927f307d0ead26fa3fcef4e3f64279f49be9504f918cb33294f75aeec8
|
||||
F test/wal2snapshot.test 7a5f4629a3c43a43c3440b8b2ea9f07de91a46b0b9eea5f08f62b5bf5b6468df
|
||||
F test/wal3.test 5de023bb862fd1eb9d2ad26fa8d9c43abb5370582e5b08b2ae0d6f93661bc310
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
|
||||
@ -2031,7 +2045,7 @@ F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
|
||||
F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
|
||||
F test/walpersist.test 8d78a1ec91299163451417b451a2bac3481f8eb9f455b1ca507a6625c927ca6e
|
||||
F test/walprotocol.test 1b3f922125e341703f6e946d77fdc564d38fb3e07a9385cfdc6c99cac1ecf878
|
||||
F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db868eebc131
|
||||
F test/walprotocol2.test 7e4bedd5ee83607e2928ac438bf7332a396b980d3e02aa0746509ce11ad1f13c
|
||||
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
|
||||
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
|
||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||
@ -2155,7 +2169,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
|
||||
F tool/mkccode.tcl 4cb8ad7e7330aaed052b0657a1bfacbc67103c400e41860aff643a482cfc2d3e x
|
||||
F tool/mkctimec.tcl e3af51acc2ef92062fe6d622de010a27a34b497258a248dada04388b916c61c6 x
|
||||
F tool/mkctimec.tcl 24074f287208f82f6dfbbe81f9e911849171a9c633961901f2c056cddb8d1663 x
|
||||
F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559
|
||||
F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
@ -2237,8 +2251,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P d8c0e0184226bdae9785199d486200e49db7973d78502d09db7a7e34ab0af941
|
||||
R 4d14b0cf75d6af0603108fd77389184c
|
||||
P d34b6a91389ff82fba4086d142c560e9daff534076df99a4ed0cdbffa9fce85f c4da7fa279274e5a6fe214b5c22f17bcf9b40299aeeab5bfbdae2ba0b2de6af0
|
||||
R 1cc2dc06766dce2d924adb093cc54a86
|
||||
U drh
|
||||
Z 668ae18c27501de00efe113f6d944d91
|
||||
Z 4d107c7057c87f70942d8be94a90ffe5
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
c4da7fa279274e5a6fe214b5c22f17bcf9b40299aeeab5bfbdae2ba0b2de6af0
|
||||
4ddea432bb19abf33a8a202a1a6d512d008e810e98a5ff19e2d699ce40da2e9a
|
||||
|
10
src/btree.c
10
src/btree.c
@ -3308,10 +3308,10 @@ static int lockBtree(BtShared *pBt){
|
||||
goto page1_init_failed;
|
||||
}
|
||||
#else
|
||||
if( page1[18]>2 ){
|
||||
if( page1[18]>3 ){
|
||||
pBt->btsFlags |= BTS_READ_ONLY;
|
||||
}
|
||||
if( page1[19]>2 ){
|
||||
if( page1[19]>3 ){
|
||||
goto page1_init_failed;
|
||||
}
|
||||
|
||||
@ -3323,9 +3323,9 @@ static int lockBtree(BtShared *pBt){
|
||||
** may not be the latest version - there may be a newer one in the log
|
||||
** file.
|
||||
*/
|
||||
if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
|
||||
if( page1[19]>=2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
|
||||
int isOpen = 0;
|
||||
rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
|
||||
rc = sqlite3PagerOpenWal(pBt->pPager, (page1[19]==3), &isOpen);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto page1_init_failed;
|
||||
}else{
|
||||
@ -11413,7 +11413,7 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
|
||||
BtShared *pBt = pBtree->pBt;
|
||||
int rc; /* Return code */
|
||||
|
||||
assert( iVersion==1 || iVersion==2 );
|
||||
assert( iVersion==1 || iVersion==2 || iVersion==3 );
|
||||
|
||||
/* If setting the version fields to 1, do not automatically open the
|
||||
** WAL connection, even if the version fields are currently set to 2.
|
||||
|
@ -782,6 +782,7 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#ifdef SQLITE_VDBE_COVERAGE
|
||||
"VDBE_COVERAGE",
|
||||
#endif
|
||||
"WAL2",
|
||||
#ifdef SQLITE_WIN32_MALLOC
|
||||
"WIN32_MALLOC",
|
||||
#endif
|
||||
|
54
src/pager.c
54
src/pager.c
@ -789,20 +789,6 @@ static const unsigned char aJournalMagic[] = {
|
||||
# define USEFETCH(x) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The argument to this macro is a file descriptor (type sqlite3_file*).
|
||||
** Return 0 if it is not open, or non-zero (but not 1) if it is.
|
||||
**
|
||||
** This is so that expressions can be written as:
|
||||
**
|
||||
** if( isOpen(pPager->jfd) ){ ...
|
||||
**
|
||||
** instead of
|
||||
**
|
||||
** if( pPager->jfd->pMethods ){ ...
|
||||
*/
|
||||
#define isOpen(pFd) ((pFd)->pMethods!=0)
|
||||
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
/*
|
||||
** Return true if page pgno can be read directly from the database file
|
||||
@ -941,6 +927,7 @@ static int assert_pager_state(Pager *p){
|
||||
assert( isOpen(p->jfd)
|
||||
|| p->journalMode==PAGER_JOURNALMODE_OFF
|
||||
|| p->journalMode==PAGER_JOURNALMODE_WAL
|
||||
|| p->journalMode==PAGER_JOURNALMODE_WAL2
|
||||
);
|
||||
}
|
||||
assert( pPager->dbOrigSize==pPager->dbFileSize );
|
||||
@ -955,6 +942,7 @@ static int assert_pager_state(Pager *p){
|
||||
assert( isOpen(p->jfd)
|
||||
|| p->journalMode==PAGER_JOURNALMODE_OFF
|
||||
|| p->journalMode==PAGER_JOURNALMODE_WAL
|
||||
|| p->journalMode==PAGER_JOURNALMODE_WAL2
|
||||
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
|
||||
);
|
||||
assert( pPager->dbOrigSize<=pPager->dbHintSize );
|
||||
@ -967,6 +955,7 @@ static int assert_pager_state(Pager *p){
|
||||
assert( isOpen(p->jfd)
|
||||
|| p->journalMode==PAGER_JOURNALMODE_OFF
|
||||
|| p->journalMode==PAGER_JOURNALMODE_WAL
|
||||
|| p->journalMode==PAGER_JOURNALMODE_WAL2
|
||||
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
|
||||
);
|
||||
break;
|
||||
@ -2088,7 +2077,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
|
||||
}
|
||||
pPager->journalOff = 0;
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|
||||
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
|
||||
|| (pPager->exclusiveMode && pPager->journalMode<PAGER_JOURNALMODE_WAL)
|
||||
){
|
||||
rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
|
||||
pPager->journalOff = 0;
|
||||
@ -2103,6 +2092,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
|
||||
assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_WAL
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_WAL2
|
||||
);
|
||||
sqlite3OsClose(pPager->jfd);
|
||||
if( bDelete ){
|
||||
@ -3258,6 +3248,10 @@ static int pagerBeginReadTransaction(Pager *pPager){
|
||||
if( rc!=SQLITE_OK || changed ){
|
||||
pager_reset(pPager);
|
||||
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
|
||||
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_WAL2
|
||||
);
|
||||
pPager->journalMode = sqlite3WalJournalMode(pPager->pWal);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -3353,9 +3347,9 @@ static int pagerOpenWalIfPresent(Pager *pPager){
|
||||
rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
|
||||
}else{
|
||||
testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
|
||||
rc = sqlite3PagerOpenWal(pPager, 0);
|
||||
rc = sqlite3PagerOpenWal(pPager, 0, 0);
|
||||
}
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
|
||||
}else if( pPager->journalMode>=PAGER_JOURNALMODE_WAL ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
|
||||
}
|
||||
}
|
||||
@ -4860,6 +4854,7 @@ int sqlite3PagerOpen(
|
||||
nPathname + 8 + 1 + /* Journal filename */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
nPathname + 4 + 1 + /* WAL filename */
|
||||
nPathname + 5 + 1 + /* Second WAL filename */
|
||||
#endif
|
||||
3 /* Terminator */
|
||||
);
|
||||
@ -4912,6 +4907,8 @@ int sqlite3PagerOpen(
|
||||
sqlite3FileSuffix3(zFilename, pPager->zWal);
|
||||
pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1);
|
||||
#endif
|
||||
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
|
||||
memcpy(pPtr, "-wal2", 5); pPtr += 5 + 1;
|
||||
}else{
|
||||
pPager->zWal = 0;
|
||||
}
|
||||
@ -7348,7 +7345,8 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
||||
|| eMode==PAGER_JOURNALMODE_OFF /* 2 */
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY /* 4 */
|
||||
|| eMode==PAGER_JOURNALMODE_WAL /* 5 */ );
|
||||
|| eMode==PAGER_JOURNALMODE_WAL /* 5 */
|
||||
|| eMode==PAGER_JOURNALMODE_WAL2 /* 6 */ );
|
||||
|
||||
/* This routine is only called from the OP_JournalMode opcode, and
|
||||
** the logic there will never allow a temporary file to be changed
|
||||
@ -7382,9 +7380,12 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
||||
assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
|
||||
assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
|
||||
assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
|
||||
assert( (PAGER_JOURNALMODE_WAL2 & 5)==4 );
|
||||
|
||||
assert( isOpen(pPager->fd) || pPager->exclusiveMode );
|
||||
if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
|
||||
if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0
|
||||
&& eMode!=PAGER_JOURNALMODE_WAL2 /* TODO: fix this if possible */
|
||||
){
|
||||
/* In this case we would like to delete the journal file. If it is
|
||||
** not possible, then that is not a problem. Deleting the journal file
|
||||
** here is an optimization only.
|
||||
@ -7559,7 +7560,7 @@ static int pagerExclusiveLock(Pager *pPager){
|
||||
** lock on the database file and use heap-memory to store the wal-index
|
||||
** in. Otherwise, use the normal shared-memory.
|
||||
*/
|
||||
static int pagerOpenWal(Pager *pPager){
|
||||
static int pagerOpenWal(Pager *pPager, int bWal2){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( pPager->pWal==0 && pPager->tempFile==0 );
|
||||
@ -7580,7 +7581,7 @@ static int pagerOpenWal(Pager *pPager){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3WalOpen(pPager->pVfs,
|
||||
pPager->fd, pPager->zWal, pPager->exclusiveMode,
|
||||
pPager->journalSizeLimit, &pPager->pWal
|
||||
pPager->journalSizeLimit, bWal2, &pPager->pWal
|
||||
);
|
||||
}
|
||||
pagerFixMaplimit(pPager);
|
||||
@ -7606,6 +7607,7 @@ static int pagerOpenWal(Pager *pPager){
|
||||
*/
|
||||
int sqlite3PagerOpenWal(
|
||||
Pager *pPager, /* Pager object */
|
||||
int bWal2, /* Open in wal2 mode if not already open */
|
||||
int *pbOpen /* OUT: Set to true if call is a no-op */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
@ -7622,9 +7624,9 @@ int sqlite3PagerOpenWal(
|
||||
/* Close any rollback journal previously open */
|
||||
sqlite3OsClose(pPager->jfd);
|
||||
|
||||
rc = pagerOpenWal(pPager);
|
||||
rc = pagerOpenWal(pPager, bWal2);
|
||||
if( rc==SQLITE_OK ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_WAL;
|
||||
pPager->journalMode = bWal2?PAGER_JOURNALMODE_WAL2:PAGER_JOURNALMODE_WAL;
|
||||
pPager->eState = PAGER_OPEN;
|
||||
}
|
||||
}else{
|
||||
@ -7646,7 +7648,9 @@ int sqlite3PagerOpenWal(
|
||||
int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
|
||||
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_WAL2
|
||||
);
|
||||
|
||||
/* If the log file is not already open, but does exist in the file-system,
|
||||
** it may need to be checkpointed before the connection can switch to
|
||||
@ -7661,7 +7665,7 @@ int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK && logexists ){
|
||||
rc = pagerOpenWal(pPager);
|
||||
rc = pagerOpenWal(pPager, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
19
src/pager.h
19
src/pager.h
@ -82,6 +82,23 @@ typedef struct PgHdr DbPage;
|
||||
#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
|
||||
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
|
||||
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
|
||||
#define PAGER_JOURNALMODE_WAL2 6 /* Use write-ahead logging mode 2 */
|
||||
|
||||
#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL || (x)==PAGER_JOURNALMODE_WAL2)
|
||||
|
||||
/*
|
||||
** The argument to this macro is a file descriptor (type sqlite3_file*).
|
||||
** Return 0 if it is not open, or non-zero (but not 1) if it is.
|
||||
**
|
||||
** This is so that expressions can be written as:
|
||||
**
|
||||
** if( isOpen(pPager->jfd) ){ ...
|
||||
**
|
||||
** instead of
|
||||
**
|
||||
** if( pPager->jfd->pMethods ){ ...
|
||||
*/
|
||||
#define isOpen(pFd) ((pFd)->pMethods!=0)
|
||||
|
||||
/*
|
||||
** Flags that make up the mask passed to sqlite3PagerGet().
|
||||
@ -175,7 +192,7 @@ int sqlite3PagerSharedLock(Pager *pPager);
|
||||
int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
|
||||
int sqlite3PagerWalSupported(Pager *pPager);
|
||||
int sqlite3PagerWalCallback(Pager *pPager);
|
||||
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
|
||||
int sqlite3PagerOpenWal(Pager *pPager, int, int *pisOpen);
|
||||
int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
|
||||
# ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
|
||||
|
@ -290,7 +290,7 @@ const char *sqlite3JournalModename(int eMode){
|
||||
static char * const azModeName[] = {
|
||||
"delete", "persist", "off", "truncate", "memory"
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
, "wal"
|
||||
, "wal", "wal2"
|
||||
#endif
|
||||
};
|
||||
assert( PAGER_JOURNALMODE_DELETE==0 );
|
||||
@ -299,6 +299,7 @@ const char *sqlite3JournalModename(int eMode){
|
||||
assert( PAGER_JOURNALMODE_TRUNCATE==3 );
|
||||
assert( PAGER_JOURNALMODE_MEMORY==4 );
|
||||
assert( PAGER_JOURNALMODE_WAL==5 );
|
||||
assert( PAGER_JOURNALMODE_WAL2==6 );
|
||||
assert( eMode>=0 && eMode<=ArraySize(azModeName) );
|
||||
|
||||
if( eMode==ArraySize(azModeName) ) return 0;
|
||||
|
@ -187,7 +187,7 @@ static int SQLITE_TCLAPI hexio_write(
|
||||
}
|
||||
|
||||
/*
|
||||
** USAGE: hexio_get_int HEXDATA
|
||||
** USAGE: hexio_get_int [-littleendian] HEXDATA
|
||||
**
|
||||
** Interpret the HEXDATA argument as a big-endian integer. Return
|
||||
** the value of that integer. HEXDATA can contain between 2 and 8
|
||||
@ -205,12 +205,20 @@ static int SQLITE_TCLAPI hexio_get_int(
|
||||
const unsigned char *zIn;
|
||||
unsigned char *aOut;
|
||||
unsigned char aNum[4];
|
||||
int bLittle = 0;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA");
|
||||
if( objc==3 ){
|
||||
Tcl_Size n;
|
||||
char *z = Tcl_GetStringFromObj(objv[1], &n);
|
||||
if( n>=2 && n<=13 && memcmp(z, "-littleendian", n)==0 ){
|
||||
bLittle = 1;
|
||||
}
|
||||
}
|
||||
if( (objc-bLittle)!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "[-littleendian] HEXDATA");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
|
||||
zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1+bLittle], &nIn);
|
||||
aOut = sqlite3_malloc64( 1 + nIn/2 );
|
||||
if( aOut==0 ){
|
||||
return TCL_ERROR;
|
||||
@ -223,7 +231,11 @@ static int SQLITE_TCLAPI hexio_get_int(
|
||||
memcpy(&aNum[4-nOut], aOut, nOut);
|
||||
}
|
||||
sqlite3_free(aOut);
|
||||
val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
|
||||
if( bLittle ){
|
||||
val = (int)((u32)aNum[3]<<24) | (aNum[2]<<16) | (aNum[1]<<8) | aNum[0];
|
||||
}else{
|
||||
val = (int)((u32)aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(val));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
|
||||
extern int Fts5tcl_Init(Tcl_Interp *);
|
||||
extern int SqliteRbu_Init(Tcl_Interp*);
|
||||
extern int Sqlitetesttcl_Init(Tcl_Interp*);
|
||||
extern int Bgckpt_Init(Tcl_Interp*);
|
||||
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
||||
extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
|
||||
#endif
|
||||
@ -161,6 +162,8 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
|
||||
Fts5tcl_Init(interp);
|
||||
SqliteRbu_Init(interp);
|
||||
Sqlitetesttcl_Init(interp);
|
||||
Bgckpt_Init(interp);
|
||||
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
||||
Sqlitetestfts3_Init(interp);
|
||||
|
63
src/vdbe.c
63
src/vdbe.c
@ -7912,6 +7912,7 @@ case OP_JournalMode: { /* out2 */
|
||||
|| eNew==PAGER_JOURNALMODE_OFF
|
||||
|| eNew==PAGER_JOURNALMODE_MEMORY
|
||||
|| eNew==PAGER_JOURNALMODE_WAL
|
||||
|| eNew==PAGER_JOURNALMODE_WAL2
|
||||
|| eNew==PAGER_JOURNALMODE_QUERY
|
||||
);
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
@ -7930,16 +7931,25 @@ case OP_JournalMode: { /* out2 */
|
||||
/* Do not allow a transition to journal_mode=WAL for a database
|
||||
** in temporary storage or if the VFS does not support shared memory
|
||||
*/
|
||||
if( eNew==PAGER_JOURNALMODE_WAL
|
||||
if( isWalMode(eNew)
|
||||
&& (sqlite3Strlen30(zFilename)==0 /* Temp file */
|
||||
|| !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */
|
||||
){
|
||||
eNew = eOld;
|
||||
}
|
||||
|
||||
if( (eNew!=eOld)
|
||||
&& (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
|
||||
){
|
||||
if( eNew!=eOld && (isWalMode(eNew) || isWalMode(eOld)) ){
|
||||
|
||||
/* Prevent changing directly to wal2 from wal mode. And vice versa. */
|
||||
if( isWalMode(eNew) && isWalMode(eOld) ){
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3VdbeError(p, "cannot change from %s to %s mode",
|
||||
sqlite3JournalModename(eOld), sqlite3JournalModename(eNew)
|
||||
);
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
|
||||
/* Prevent switching into or out of wal/wal2 mode mid-transaction */
|
||||
if( !db->autoCommit || db->nVdbeRead>1 ){
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3VdbeError(p,
|
||||
@ -7947,31 +7957,34 @@ case OP_JournalMode: { /* out2 */
|
||||
(eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
|
||||
);
|
||||
goto abort_due_to_error;
|
||||
}else{
|
||||
|
||||
if( eOld==PAGER_JOURNALMODE_WAL ){
|
||||
/* If leaving WAL mode, close the log file. If successful, the call
|
||||
** to PagerCloseWal() checkpoints and deletes the write-ahead-log
|
||||
** file. An EXCLUSIVE lock may still be held on the database file
|
||||
** after a successful return.
|
||||
*/
|
||||
rc = sqlite3PagerCloseWal(pPager, db);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3PagerSetJournalMode(pPager, eNew);
|
||||
}
|
||||
}else if( eOld==PAGER_JOURNALMODE_MEMORY ){
|
||||
/* Cannot transition directly from MEMORY to WAL. Use mode OFF
|
||||
** as an intermediate */
|
||||
sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open a transaction on the database file. Regardless of the journal
|
||||
** mode, this transaction always uses a rollback journal.
|
||||
if( isWalMode(eOld) ){
|
||||
/* If leaving WAL mode, close the log file. If successful, the call
|
||||
** to PagerCloseWal() checkpoints and deletes the write-ahead-log
|
||||
** file. An EXCLUSIVE lock may still be held on the database file
|
||||
** after a successful return.
|
||||
*/
|
||||
assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE );
|
||||
rc = sqlite3PagerCloseWal(pPager, db);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
|
||||
sqlite3PagerSetJournalMode(pPager, eNew);
|
||||
}
|
||||
}else if( eOld==PAGER_JOURNALMODE_MEMORY ){
|
||||
/* Cannot transition directly from MEMORY to WAL. Use mode OFF
|
||||
** as an intermediate */
|
||||
sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
|
||||
}
|
||||
|
||||
/* Open a transaction on the database file. Regardless of the journal
|
||||
** mode, this transaction always uses a rollback journal.
|
||||
*/
|
||||
assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE );
|
||||
if( rc==SQLITE_OK ){
|
||||
/* 1==rollback, 2==wal, 3==wal2 */
|
||||
rc = sqlite3BtreeSetVersion(pBt,
|
||||
1 + isWalMode(eNew) + (eNew==PAGER_JOURNALMODE_WAL2)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* ifndef SQLITE_OMIT_WAL */
|
||||
|
@ -2941,7 +2941,8 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
||||
/* OFF */ 0,
|
||||
/* TRUNCATE */ 1,
|
||||
/* MEMORY */ 0,
|
||||
/* WAL */ 0
|
||||
/* WAL */ 0,
|
||||
/* WAL2 */ 0
|
||||
};
|
||||
Pager *pPager; /* Pager associated with pBt */
|
||||
needXcommit = 1;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03)
|
||||
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
# define sqlite3WalOpen(x,y,z) 0
|
||||
# define sqlite3WalOpen(w,x,y,z) 0
|
||||
# define sqlite3WalLimit(x,y)
|
||||
# define sqlite3WalClose(v,w,x,y,z) 0
|
||||
# define sqlite3WalBeginReadTransaction(y,z) 0
|
||||
@ -45,6 +45,7 @@
|
||||
# define sqlite3WalFramesize(z) 0
|
||||
# define sqlite3WalFindFrame(x,y,z) 0
|
||||
# define sqlite3WalFile(x) 0
|
||||
# define sqlite3WalJournalMode(x) 0
|
||||
# undef SQLITE_USE_SEH
|
||||
#else
|
||||
|
||||
@ -56,7 +57,7 @@
|
||||
typedef struct Wal Wal;
|
||||
|
||||
/* Open and close a connection to a write-ahead log. */
|
||||
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
|
||||
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *,int,i64,int,Wal**);
|
||||
int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);
|
||||
|
||||
/* Set the limiting size of a WAL file. */
|
||||
@ -147,6 +148,9 @@ int sqlite3WalFramesize(Wal *pWal);
|
||||
/* Return the sqlite3_file object for the WAL file */
|
||||
sqlite3_file *sqlite3WalFile(Wal *pWal);
|
||||
|
||||
/* Return the journal mode (WAL or WAL2) used by this Wal object. */
|
||||
int sqlite3WalJournalMode(Wal *pWal);
|
||||
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
int sqlite3WalWriteLock(Wal *pWal, int bLock);
|
||||
void sqlite3WalDb(Wal *pWal, sqlite3 *db);
|
||||
|
@ -47,7 +47,7 @@ db close
|
||||
forcecopy test.db test.db-template
|
||||
|
||||
set unreadable_version 02
|
||||
ifcapable wal { set unreadable_version 03 }
|
||||
ifcapable wal { set unreadable_version 04 }
|
||||
do_test corruptA-2.1 {
|
||||
forcecopy test.db-template test.db
|
||||
hexio_write test.db 19 $unreadable_version ;# the read format number
|
||||
|
@ -465,18 +465,21 @@ lappend ::testsuitelist xxx
|
||||
test_suite "coverage-wal" -description {
|
||||
Coverage tests for file wal.c.
|
||||
} -files {
|
||||
wal.test wal2.test wal3.test wal4.test wal5.test
|
||||
wal2big.test wal2recover.test wal2rewrite.test
|
||||
wal2simple.test wal2snapshot.test wal2.test
|
||||
wal3.test wal4.test wal5.test
|
||||
wal64k.test wal6.test wal7.test wal8.test wal9.test
|
||||
walbak.test walbig.test walblock.test walcksum.test walcrash2.test
|
||||
walcrash3.test walcrash4.test walcrash.test walfault.test walhook.test
|
||||
walmode.test walnoshm.test waloverwrite.test walpersist.test
|
||||
walprotocol2.test walprotocol.test walro2.test walrofault.test
|
||||
walro.test walshared.test walslow.test walvfs.test
|
||||
walfault2.test
|
||||
nockpt.test
|
||||
|
||||
walbak.test walbig.test walblock.test walcksum.test
|
||||
walfault.test walhook.test walmode.test walnoshm.test
|
||||
waloverwrite.test walpersist.test walprotocol2.test
|
||||
walprotocol.test walro2.test walrofault.test walro.test
|
||||
walshared.test walslow.test wal.test
|
||||
wal2savepoint.test wal2lock.test wal2recover2.test
|
||||
walvfs.test walfault2.test nockpt.test
|
||||
snapshot2.test snapshot3.test snapshot4.test
|
||||
snapshot_fault.test snapshot.test snapshot_up.test
|
||||
walcrash2.test walcrash3.test walcrash4.test walcrash.test
|
||||
wal2fault.test
|
||||
}
|
||||
|
||||
test_suite "coverage-pager" -description {
|
||||
@ -1034,6 +1037,23 @@ test_suite "wal" -description {
|
||||
fts3c.test fts3d.test fts3e.test fts3query.test
|
||||
}
|
||||
|
||||
test_suite "wal2" -description {
|
||||
Run tests with journal_mode=WAL2
|
||||
} -initialize {
|
||||
set ::G(savepoint6_iterations) 100
|
||||
} -shutdown {
|
||||
unset -nocomplain ::G(savepoint6_iterations)
|
||||
} -files {
|
||||
savepoint.test savepoint2.test savepoint6.test
|
||||
trans.test avtrans.test
|
||||
|
||||
fts3aa.test fts3ab.test fts3ac.test fts3ad.test
|
||||
fts3ae.test fts3af.test fts3ag.test fts3ah.test
|
||||
fts3ai.test fts3aj.test fts3ak.test fts3al.test
|
||||
fts3am.test fts3an.test fts3ao.test fts3b.test
|
||||
fts3c.test fts3d.test fts3e.test fts3query.test
|
||||
}
|
||||
|
||||
test_suite "rtree" -description {
|
||||
All R-tree related tests. Provides coverage of source file rtree.c.
|
||||
} -files [glob -nocomplain $::testdir/../ext/rtree/*.test]
|
||||
|
@ -41,7 +41,7 @@ do_test rdonly-1.1.1 {
|
||||
sqlite3_db_readonly db main
|
||||
} {0}
|
||||
|
||||
# Changes the write version from 1 to 3. Verify that the database
|
||||
# Changes the write version from 1 to 4. Verify that the database
|
||||
# can be read but not written.
|
||||
#
|
||||
do_test rdonly-1.2 {
|
||||
@ -49,7 +49,7 @@ do_test rdonly-1.2 {
|
||||
hexio_get_int [hexio_read test.db 18 1]
|
||||
} 1
|
||||
do_test rdonly-1.3 {
|
||||
hexio_write test.db 18 03
|
||||
hexio_write test.db 18 04
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
@ -83,7 +83,7 @@ do_test rdonly-1.5 {
|
||||
# the database is read-only until after it is locked.
|
||||
#
|
||||
set ro_version 02
|
||||
ifcapable wal { set ro_version 03 }
|
||||
ifcapable wal { set ro_version 04 }
|
||||
do_test rdonly-1.6 {
|
||||
hexio_write test.db 18 $ro_version ; # write-version
|
||||
hexio_write test.db 24 11223344 ; # change-counter
|
||||
|
@ -30,6 +30,7 @@ do_test savepoint-1.1 {
|
||||
RELEASE sp1;
|
||||
}
|
||||
} {}
|
||||
wal_check_journal_mode savepoint-1.1
|
||||
do_test savepoint-1.2 {
|
||||
execsql {
|
||||
SAVEPOINT sp1;
|
||||
@ -807,7 +808,8 @@ do_test savepoint-11.6 {
|
||||
integrity_check savepoint-11.7
|
||||
do_test savepoint-11.8 {
|
||||
execsql { ROLLBACK }
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
file size test.db
|
||||
} {8192}
|
||||
|
||||
|
@ -15,6 +15,10 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
proc sql {zSql} {
|
||||
if {0 && $::debug_op} {
|
||||
puts stderr "$zSql ;"
|
||||
flush stderr
|
||||
}
|
||||
uplevel db eval [list $zSql]
|
||||
#puts stderr "$zSql ;"
|
||||
}
|
||||
@ -67,11 +71,13 @@ proc x_to_y {x} {
|
||||
# delete_rows XVALUES
|
||||
#
|
||||
proc savepoint {zName} {
|
||||
if {$::debug_op} { puts stderr "savepoint $zName" ; flush stderr }
|
||||
catch { sql "SAVEPOINT $zName" }
|
||||
lappend ::lSavepoint [list $zName [array get ::aEntry]]
|
||||
}
|
||||
|
||||
proc rollback {zName} {
|
||||
if {$::debug_op} { puts stderr "rollback $zName" ; flush stderr }
|
||||
catch { sql "ROLLBACK TO $zName" }
|
||||
for {set i [expr {[llength $::lSavepoint]-1}]} {$i>=0} {incr i -1} {
|
||||
set zSavepoint [lindex $::lSavepoint $i 0]
|
||||
@ -89,6 +95,7 @@ proc rollback {zName} {
|
||||
}
|
||||
|
||||
proc release {zName} {
|
||||
if {$::debug_op} { puts stderr "release $zName" ; flush stderr }
|
||||
catch { sql "RELEASE $zName" }
|
||||
for {set i [expr {[llength $::lSavepoint]-1}]} {$i>=0} {incr i -1} {
|
||||
set zSavepoint [lindex $::lSavepoint $i 0]
|
||||
@ -104,6 +111,7 @@ proc release {zName} {
|
||||
}
|
||||
|
||||
proc insert_rows {lX} {
|
||||
if {$::debug_op} { puts stderr "insert_rows $lX" ; flush stderr }
|
||||
foreach x $lX {
|
||||
set y [x_to_y $x]
|
||||
|
||||
@ -116,6 +124,7 @@ proc insert_rows {lX} {
|
||||
}
|
||||
|
||||
proc delete_rows {lX} {
|
||||
if {$::debug_op} { puts stderr "delete_rows $lX" ; flush stderr }
|
||||
foreach x $lX {
|
||||
# Update database [db]
|
||||
sql "DELETE FROM t1 WHERE x = $x"
|
||||
@ -164,6 +173,11 @@ proc random_integers {nRes nRange} {
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
set ::debug_op 0
|
||||
proc debug_ops {} {
|
||||
set ::debug_op 1
|
||||
}
|
||||
|
||||
proc database_op {} {
|
||||
set i [expr int(rand()*2)]
|
||||
if {$i==0} {
|
||||
@ -185,9 +199,6 @@ proc savepoint_op {} {
|
||||
set C [lindex $cmds [expr int(rand()*6)]]
|
||||
set N [lindex $names [expr int(rand()*5)]]
|
||||
|
||||
#puts stderr " $C $N ; "
|
||||
#flush stderr
|
||||
|
||||
$C $N
|
||||
return ok
|
||||
}
|
||||
|
@ -553,6 +553,7 @@ proc reset_db {} {
|
||||
forcedelete test.db
|
||||
forcedelete test.db-journal
|
||||
forcedelete test.db-wal
|
||||
forcedelete test.db-wal2
|
||||
sqlite3 db ./test.db
|
||||
set ::DB [sqlite3_connection_pointer db]
|
||||
if {[info exists ::SETUP_SQL]} {
|
||||
@ -2297,17 +2298,32 @@ proc drop_all_indexes {{db db}} {
|
||||
# Returns true if this test should be run in WAL mode. False otherwise.
|
||||
#
|
||||
proc wal_is_wal_mode {} {
|
||||
expr {[permutation] eq "wal"}
|
||||
if {[permutation] eq "wal"} { return 1 }
|
||||
if {[permutation] eq "wal2"} { return 2 }
|
||||
return 0
|
||||
}
|
||||
proc wal_set_journal_mode {{db db}} {
|
||||
if { [wal_is_wal_mode] } {
|
||||
$db eval "PRAGMA journal_mode = WAL"
|
||||
switch -- [wal_is_wal_mode] {
|
||||
0 {
|
||||
}
|
||||
|
||||
1 {
|
||||
$db eval "PRAGMA journal_mode = WAL"
|
||||
}
|
||||
|
||||
2 {
|
||||
$db eval "PRAGMA journal_mode = WAL2"
|
||||
}
|
||||
}
|
||||
}
|
||||
proc wal_check_journal_mode {testname {db db}} {
|
||||
if { [wal_is_wal_mode] } {
|
||||
$db eval { SELECT * FROM sqlite_master }
|
||||
do_test $testname [list $db eval "PRAGMA main.journal_mode"] {wal}
|
||||
set expected "wal"
|
||||
if {[wal_is_wal_mode]==2} {
|
||||
set expected "wal2"
|
||||
}
|
||||
do_test $testname [list $db eval "PRAGMA main.journal_mode"] $expected
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,11 +282,11 @@ ifcapable wal {
|
||||
INSERT INTO t2 VALUES('x', 'y');
|
||||
}
|
||||
lsort [array names ::T1]
|
||||
} {test.db1 test.db1-journal test.db1-wal}
|
||||
} {test.db1 test.db1-journal test.db1-wal test.db1-wal2}
|
||||
|
||||
do_test 5.1.2 {
|
||||
lsort [array names ::T2]
|
||||
} {test.db2 test.db2-journal test.db2-wal}
|
||||
} {test.db2 test.db2-journal test.db2-wal test.db2-wal2}
|
||||
db close
|
||||
|
||||
tvfs1 delete
|
||||
|
@ -1175,7 +1175,7 @@ foreach {tn pgsz works} {
|
||||
9 32768 1
|
||||
10 65536 1
|
||||
11 131072 0
|
||||
11 1016 0
|
||||
12 1016 0
|
||||
} {
|
||||
|
||||
if {$::SQLITE_MAX_PAGE_SIZE < $pgsz} {
|
||||
@ -1185,14 +1185,14 @@ foreach {tn pgsz works} {
|
||||
for {set pg 1} {$pg <= 3} {incr pg} {
|
||||
forcecopy testX.db test.db
|
||||
forcedelete test.db-wal
|
||||
|
||||
|
||||
# Check that the database now exists and consists of three pages. And
|
||||
# that there is no associated wal file.
|
||||
#
|
||||
do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0
|
||||
do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1
|
||||
do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3]
|
||||
|
||||
|
||||
do_test wal-18.2.$tn.$pg.4 {
|
||||
|
||||
# Create a wal file that contains a single frame (database page
|
||||
@ -1224,16 +1224,16 @@ foreach {tn pgsz works} {
|
||||
puts -nonewline $fd $framehdr
|
||||
puts -nonewline $fd $framebody
|
||||
close $fd
|
||||
|
||||
|
||||
file size test.db-wal
|
||||
} [wal_file_size 1 $pgsz]
|
||||
|
||||
|
||||
do_test wal-18.2.$tn.$pg.5 {
|
||||
sqlite3 db test.db
|
||||
set rc [catch { db one {PRAGMA integrity_check} } msg]
|
||||
expr { $rc!=0 || $msg!="ok" }
|
||||
} $works
|
||||
|
||||
|
||||
db close
|
||||
}
|
||||
}
|
||||
|
73
test/wal2big.test
Normal file
73
test/wal2big.test
Normal file
@ -0,0 +1,73 @@
|
||||
# 2017 September 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# TESTRUNNER: slow
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2big
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 10000000;
|
||||
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200000
|
||||
)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
} {wal2 10000000}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200000
|
||||
)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
list [expr [file size test.db-wal]>10000000] \
|
||||
[expr [file size test.db-wal2]>10000000]
|
||||
} {1 1}
|
||||
|
||||
do_test 1.3 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {400000 ok}
|
||||
|
||||
do_test 1.4 {
|
||||
db2 close
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} {400000 ok}
|
||||
|
||||
finish_test
|
52
test/wal2fault.test
Normal file
52
test/wal2fault.test
Normal file
@ -0,0 +1,52 @@
|
||||
# 2010 May 03
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
set testprefix wal2fault
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x,y);
|
||||
PRAGMA journal_mode = wal2;
|
||||
WITH s(i) AS ( SELECT 100 UNION ALL SELECT i-1 FROM s WHERE (i-1)>0 )
|
||||
INSERT INTO t1 SELECT i, randomblob(i) FROM s;
|
||||
WITH s(i) AS ( SELECT 100 UNION ALL SELECT i-1 FROM s WHERE (i-1)>0 )
|
||||
INSERT INTO t1 SELECT i, randomblob(i) FROM s;
|
||||
} {wal2}
|
||||
|
||||
do_test 1.1 {
|
||||
expr [file size test.db-wal]>10000
|
||||
} {1}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1 -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
SELECT count(*) FROM sqlite_master;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
106
test/wal2lock.test
Normal file
106
test/wal2lock.test
Normal file
@ -0,0 +1,106 @@
|
||||
# 2018 December 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 testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2lock
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
db close
|
||||
testvfs tvfs
|
||||
sqlite3 db test.db -vfs tvfs
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA journal_mode = wal2;
|
||||
CREATE TABLE y1(y, yy);
|
||||
CREATE INDEX y1y ON y1(y);
|
||||
CREATE INDEX y1yy ON y1(yy);
|
||||
INSERT INTO y1 VALUES(1, 2), (3, 4), (5, 6);
|
||||
} {wal2}
|
||||
|
||||
tvfs script vfs_callback
|
||||
tvfs filter xShmLock
|
||||
|
||||
set ::lock [list]
|
||||
proc vfs_callback {func file name lock} {
|
||||
lappend ::lock $lock
|
||||
return SQLITE_OK
|
||||
}
|
||||
|
||||
do_execsql_test 1.1.1 {
|
||||
SELECT * FROM y1
|
||||
} {1 2 3 4 5 6}
|
||||
do_test 1.1.2 {
|
||||
set ::lock
|
||||
} {{4 1 lock shared} {4 1 unlock shared}}
|
||||
|
||||
set ::bFirst 1
|
||||
proc vfs_callback {func file name lock} {
|
||||
if {$::bFirst} {
|
||||
set ::bFirst 0
|
||||
return SQLITE_BUSY
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT * FROM y1
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
set ::bFirst 1
|
||||
proc vfs_callback {func file name lock} {
|
||||
if {$::bFirst} {
|
||||
set ::bFirst 0
|
||||
return SQLITE_IOERR
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
do_catchsql_test 1.3 {
|
||||
SELECT * FROM y1
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
|
||||
puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite"
|
||||
puts "# is built on unix without HAVE_USLEEP defined, it may be much longer."
|
||||
proc vfs_callback {func file name lock} { return SQLITE_BUSY }
|
||||
do_catchsql_test 1.4 {
|
||||
SELECT * FROM y1
|
||||
} {1 {locking protocol}}
|
||||
proc vfs_callback {func file name lock} { return SQLITE_OK }
|
||||
|
||||
sqlite3 db2 test.db -vfs tvfs
|
||||
set ::bFirst 1
|
||||
|
||||
proc vfs_callback {func file name lock} {
|
||||
if {$::bFirst} {
|
||||
set ::bFirst 0
|
||||
db2 eval { INSERT INTO y1 VALUES(7, 8) }
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 1.5.1 {
|
||||
SELECT * FROM y1
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
do_execsql_test 1.5.2 {
|
||||
SELECT * FROM y1
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
|
||||
db close
|
||||
db2 close
|
||||
tvfs delete
|
||||
finish_test
|
81
test/wal2openclose.test
Normal file
81
test/wal2openclose.test
Normal file
@ -0,0 +1,81 @@
|
||||
# 2017 September 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2openclose
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA journal_size_limit = 75000;
|
||||
} {wal2 0 75000}
|
||||
|
||||
do_test 1.1 {
|
||||
for {set ii 1} {$ii <= 200} {incr ii} {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES($ii, $ii, $ii);
|
||||
}
|
||||
}
|
||||
expr ([file size test.db-wal2] - 75000) > 30000
|
||||
} {1}
|
||||
|
||||
do_test 1.2 {
|
||||
db close
|
||||
list [file exists test.db-wal] [file exists test.db-wal2]
|
||||
} {0 0}
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 1.3 {
|
||||
SELECT sum(c) FROM t1
|
||||
} {20100}
|
||||
db close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
} {wal2}
|
||||
db_save_and_close
|
||||
|
||||
db_restore_and_reopen
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3}
|
||||
|
||||
do_test 2.2 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {INSERT INTO t1 VALUES(4, 5, 6)}
|
||||
db2 close
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
|
||||
|
||||
finish_test
|
271
test/wal2recover.test
Normal file
271
test/wal2recover.test
Normal file
@ -0,0 +1,271 @@
|
||||
# 2018 December 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2recover
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
proc db_copy {from to} {
|
||||
forcecopy $from $to
|
||||
forcecopy ${from}-wal ${to}-wal
|
||||
forcecopy ${from}-wal2 ${to}-wal2
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 15000;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
} {wal2 15000 0}
|
||||
|
||||
do_test 1.1 {
|
||||
for {set i 1} {$i <= 1000} {incr i} {
|
||||
execsql { INSERT INTO t1 VALUES(random(), random(), random()) }
|
||||
db_copy test.db test.db2
|
||||
sqlite3 db2 test.db
|
||||
set res [execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} db2]
|
||||
db2 close
|
||||
if {$res != [list $i ok]} {
|
||||
error "failure on iteration $i"
|
||||
}
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
CREATE TABLE t2(x UNIQUE);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(randomblob(4000));
|
||||
INSERT INTO t1 VALUES(randomblob(4000));
|
||||
INSERT INTO t1 VALUES(randomblob(4000));
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES(randomblob(4000));
|
||||
INSERT INTO t2 VALUES(randomblob(4000));
|
||||
INSERT INTO t2 VALUES(randomblob(4000));
|
||||
COMMIT;
|
||||
} {wal2 10000 0}
|
||||
do_test 2.0.1 {
|
||||
list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
|
||||
} {5120 28328 28328}
|
||||
|
||||
# Test recovery with both wal files intact.
|
||||
#
|
||||
do_test 2.1 {
|
||||
db_copy test.db test.db2
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {3 3 ok}
|
||||
|
||||
do_test 2.2 {
|
||||
db2 close
|
||||
db_copy test.db test.db2
|
||||
hexio_write test.db2-wal 16 12345678
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
} db2
|
||||
} {0 3}
|
||||
|
||||
do_test 2.3 {
|
||||
db2 close
|
||||
db_copy test.db test.db2
|
||||
hexio_write test.db2-wal2 16 12345678
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {3 0 ok}
|
||||
|
||||
do_test 2.4 {
|
||||
db2 close
|
||||
db_copy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {3 0 ok}
|
||||
|
||||
do_test 2.5 {
|
||||
db2 close
|
||||
db_copy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal2
|
||||
forcecopy test.db-wal2 test.db2-wal
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {3 3 ok}
|
||||
|
||||
do_test 2.6 {
|
||||
db2 close
|
||||
db_copy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal2
|
||||
close [open test.db-wal w]
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {3 0 ok}
|
||||
|
||||
do_test 2.7 {
|
||||
db2 close
|
||||
db_copy test.db test.db2
|
||||
forcedelete test.db2-wal
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
} db2
|
||||
} {0 0 ok}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a TEXT, b TEXT, c TEXT);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA cache_size = 5;
|
||||
} {wal2 10000 0}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200)
|
||||
INSERT INTO t1 SELECT i, i, i FROM s;
|
||||
|
||||
INSERT INTO t1 VALUES(201, 201, 201);
|
||||
} {}
|
||||
|
||||
do_test 3.2 {
|
||||
list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
|
||||
} {5120 15752 4224}
|
||||
|
||||
do_test 3.3 {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA cache_size = 5;
|
||||
BEGIN;
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200)
|
||||
INSERT INTO t1 SELECT i, i, i FROM s;
|
||||
} db2
|
||||
list [file size test.db2] [file size test.db2-wal] [file size test.db2-wal2]
|
||||
} {5120 15752 23088}
|
||||
|
||||
|
||||
if {$tcl_platform(platform)!="windows"} {
|
||||
# These cannot be run under windows, as the *-shm file may not be read
|
||||
# while it is locked by the database connection.
|
||||
do_test 3.4 {
|
||||
set fd [open test.db2-shm]
|
||||
fconfigure $fd -translation binary
|
||||
set data [read $fd]
|
||||
close $fd
|
||||
|
||||
set fd [open test.db-shm w]
|
||||
fconfigure $fd -translation binary
|
||||
puts -nonewline $fd $data
|
||||
close $fd
|
||||
|
||||
execsql {
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
|
||||
INSERT INTO t1 SELECT i, i, i FROM s;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} {211 ok}
|
||||
|
||||
do_test 3.5 {
|
||||
list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
|
||||
} {5120 15752 18896}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
PRAGMA journal_mode = wal2;
|
||||
CREATE TABLE xyz(x, y, z);
|
||||
INSERT INTO xyz VALUES('x', 'y', 'z');
|
||||
} {wal2}
|
||||
db close
|
||||
do_test 4.1 {
|
||||
close [open test.db-wal w]
|
||||
file mkdir test.db-wal2
|
||||
sqlite3 db test.db
|
||||
catchsql { SELECT * FROM xyz }
|
||||
} {1 {unable to open database file}}
|
||||
db close
|
||||
file delete test.db-wal2
|
||||
db2 close
|
||||
|
||||
do_test 4.2 {
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
INSERT INTO xyz VALUES('a', 'b', 'c');
|
||||
}
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
forcedelete test.db2-wal2
|
||||
file mkdir test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
catchsql { SELECT * FROM xyz } db2
|
||||
} {1 {unable to open database file}}
|
||||
db2 close
|
||||
file delete test.db2-wal2
|
||||
|
||||
|
||||
finish_test
|
273
test/wal2recover2.test
Normal file
273
test/wal2recover2.test
Normal file
@ -0,0 +1,273 @@
|
||||
# 2018 December 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2recover2
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(x);
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t1 SELECT i FROM s;
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t2 SELECT i FROM s;
|
||||
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
} {wal2 10000}
|
||||
|
||||
set ::L 1125750
|
||||
set ::M 1126500
|
||||
set ::H 1127250
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
UPDATE t1 SET x=x+1;
|
||||
UPDATE t2 SET x=x+1 WHERE rowid<=750;
|
||||
|
||||
SELECT sum(x) FROM t1;
|
||||
SELECT sum(x) FROM t2;
|
||||
} [list $H $M]
|
||||
|
||||
do_test 1.2 {
|
||||
list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
|
||||
} {31744 14704 7368}
|
||||
|
||||
proc cksum {zIn data} {
|
||||
if {[string length $zIn]==0} {
|
||||
set s0 0
|
||||
set s1 0
|
||||
} else {
|
||||
set s0 [hexio_get_int [string range $zIn 0 7]]
|
||||
set s1 [hexio_get_int [string range $zIn 8 15]]
|
||||
}
|
||||
set n [expr [string length $data] / 8]
|
||||
|
||||
for {set i 0} {$i < $n} {incr i 2} {
|
||||
set x0 [hexio_get_int -l [string range $data [expr $i*8] [expr $i*8+7]]]
|
||||
set x1 [hexio_get_int -l [string range $data [expr $i*8+8] [expr $i*8+8+7]]]
|
||||
|
||||
set s0 [expr ($s0 + $x0 + $s1) & 0xFFFFFFFF]
|
||||
set s1 [expr ($s1 + $x1 + $s0) & 0xFFFFFFFF]
|
||||
}
|
||||
|
||||
return "[hexio_render_int32 $s0][hexio_render_int32 $s1]"
|
||||
}
|
||||
|
||||
proc fix_wal_cksums {file} {
|
||||
# Fix the checksum on the wal header.
|
||||
set data [hexio_read $file 0 32]
|
||||
set cksum [cksum {} [string range $data 0 47]]
|
||||
set salt [hexio_read $file 16 8]
|
||||
hexio_write $file 24 $cksum
|
||||
|
||||
# Fix the checksums for all pages in the wal file.
|
||||
set pgsz [hexio_get_int [hexio_read $file 8 4]]
|
||||
set sz [file size $file]
|
||||
for {set off 32} {$off < $sz} {incr off [expr $pgsz+24]} {
|
||||
set e [hexio_read $file $off 8]
|
||||
set cksum [cksum $cksum $e]
|
||||
|
||||
set p [hexio_read $file [expr $off+24] $pgsz]
|
||||
set cksum [cksum $cksum $p]
|
||||
|
||||
hexio_write $file [expr $off+8] $salt
|
||||
hexio_write $file [expr $off+16] $cksum
|
||||
}
|
||||
}
|
||||
|
||||
proc wal_incr_hdrfield {file field} {
|
||||
switch -- $field {
|
||||
nCkpt { set offset 12 }
|
||||
salt0 { set offset 16 }
|
||||
salt1 { set offset 20 }
|
||||
default {
|
||||
error "unknown field $field - should be \"nCkpt\", \"salt0\" or \"salt1\""
|
||||
}
|
||||
}
|
||||
|
||||
# Increment the value in the wal header.
|
||||
set v [hexio_get_int [hexio_read $file $offset 4]]
|
||||
incr v
|
||||
hexio_write $file $offset [hexio_render_int32 $v]
|
||||
|
||||
# Fix various checksums
|
||||
fix_wal_cksums $file
|
||||
}
|
||||
|
||||
proc wal_set_nckpt {file val} {
|
||||
# Increment the value in the wal header.
|
||||
hexio_write $file 12 [hexio_render_int32 $val]
|
||||
|
||||
# Fix various checksums
|
||||
fix_wal_cksums $file
|
||||
}
|
||||
|
||||
proc wal_set_follow {file prevfile} {
|
||||
set pgsz [hexio_get_int [hexio_read $prevfile 8 4]]
|
||||
set sz [file size $prevfile]
|
||||
set cksum [hexio_read $prevfile [expr $sz-$pgsz-8] 8]
|
||||
|
||||
hexio_write $file 16 $cksum
|
||||
fix_wal_cksums $file
|
||||
}
|
||||
|
||||
foreach {tn file field} {
|
||||
1 test.db2-wal salt0
|
||||
2 test.db2-wal salt1
|
||||
3 test.db2-wal nCkpt
|
||||
4 test.db2-wal2 salt0
|
||||
5 test.db2-wal2 salt1
|
||||
6 test.db2-wal2 nCkpt
|
||||
} {
|
||||
do_test 1.3.$tn {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
wal_incr_hdrfield $file $field
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT sum(x) FROM t1;
|
||||
SELECT sum(x) FROM t2;
|
||||
} db2
|
||||
} [list $H $L]
|
||||
db2 close
|
||||
}
|
||||
|
||||
do_test 1.4 {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal2 test.db2-wal
|
||||
forcedelete test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT sum(x) FROM t1;
|
||||
SELECT sum(x) FROM t2;
|
||||
} db2
|
||||
} [list $L $M]
|
||||
|
||||
do_test 1.5 {
|
||||
db2 close
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal2 test.db2-wal
|
||||
forcecopy test.db-wal test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT sum(x) FROM t1;
|
||||
SELECT sum(x) FROM t2;
|
||||
} db2
|
||||
} [list $H $M]
|
||||
|
||||
db2 close
|
||||
foreach {tn file field} {
|
||||
1 test.db2-wal salt0
|
||||
2 test.db2-wal salt1
|
||||
3 test.db2-wal2 salt0
|
||||
4 test.db2-wal2 salt1
|
||||
} {
|
||||
do_test 1.6.$tn {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal2 test.db2-wal
|
||||
forcecopy test.db-wal test.db2-wal2
|
||||
wal_incr_hdrfield $file $field
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT sum(x) FROM t1;
|
||||
SELECT sum(x) FROM t2;
|
||||
} db2
|
||||
} [list $H $L]
|
||||
db2 close
|
||||
}
|
||||
|
||||
foreach {tn nCkpt1 nCkpt2 res} [list \
|
||||
1 2 1 "$H $M" \
|
||||
2 2 2 "$L $M" \
|
||||
3 3 1 "$H $L" \
|
||||
4 15 14 "$H $M" \
|
||||
5 0 15 "$H $M" \
|
||||
6 1 15 "$L $M" \
|
||||
] {
|
||||
do_test 1.7.$tn {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal2 test.db2-wal
|
||||
forcecopy test.db-wal test.db2-wal2
|
||||
|
||||
wal_set_nckpt test.db2-wal2 $nCkpt2
|
||||
wal_set_nckpt test.db2-wal $nCkpt1
|
||||
wal_set_follow test.db2-wal test.db2-wal2
|
||||
|
||||
|
||||
sqlite3 db2 test.db2
|
||||
execsql {
|
||||
SELECT sum(x) FROM t1;
|
||||
SELECT sum(x) FROM t2;
|
||||
} db2
|
||||
} $res
|
||||
db2 close
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 1.8.1 {
|
||||
PRAGMA autovacuum = 0;
|
||||
PRAGMA page_size = 4096;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(x);
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t1 SELECT i FROM s;
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t2 SELECT i FROM s;
|
||||
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t2 SELECT i FROM s;
|
||||
} {wal2 10000}
|
||||
|
||||
do_test 1.8.2 {
|
||||
list [file size test.db-wal] [file size test.db-wal2]
|
||||
} {24752 0}
|
||||
|
||||
do_execsql_test 1.8.3 { PRAGMA user_version = 123 }
|
||||
do_test 1.8.4 {
|
||||
list [file size test.db-wal] [file size test.db-wal2]
|
||||
} {24752 4152}
|
||||
|
||||
do_test 1.8.5 {
|
||||
hexio_write test.db-wal2 [expr 56+16] 0400
|
||||
fix_wal_cksums test.db-wal2
|
||||
} {}
|
||||
|
||||
ifcapable oversize_cell_check {
|
||||
set msg {database disk image is malformed}
|
||||
} else {
|
||||
set msg {malformed database schema (?)}
|
||||
}
|
||||
|
||||
do_test 1.8.6 {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
catchsql { SELECT * FROM sqlite_master } db2
|
||||
} [list 1 $msg]
|
||||
db2 close
|
||||
|
||||
finish_test
|
52
test/wal2recover3.test
Normal file
52
test/wal2recover3.test
Normal file
@ -0,0 +1,52 @@
|
||||
# 2022 June 28
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2recover3
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(x);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
} {wal2 0 10000}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t1 SELECT i FROM s;
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
|
||||
INSERT INTO t2 SELECT i FROM s;
|
||||
}
|
||||
|
||||
db_save_and_close
|
||||
set fd [open sv_test.db-wal2 r+]
|
||||
seek $fd 4000
|
||||
puts -nonewline $fd 0
|
||||
close $fd
|
||||
|
||||
db_restore_and_reopen
|
||||
do_execsql_test 1.2 {
|
||||
SELECT sql FROM sqlite_schema;
|
||||
} {{CREATE TABLE t1(x)} {CREATE TABLE t2(x)}}
|
||||
|
||||
finish_test
|
||||
|
92
test/wal2rewrite.test
Normal file
92
test/wal2rewrite.test
Normal file
@ -0,0 +1,92 @@
|
||||
# 2017 September 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2rewrite
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
proc filesize {filename} {
|
||||
if {[file exists $filename]} {
|
||||
return [file size $filename]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
foreach {tn jrnlmode} {
|
||||
1 wal
|
||||
2 wal2
|
||||
} {
|
||||
reset_db
|
||||
execsql "PRAGMA journal_mode = $jrnlmode"
|
||||
do_execsql_test $tn.1 {
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
PRAGMA cache_size = 5;
|
||||
PRAGMA wal_autocheckpoint = 10;
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER, c BLOB);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION SELECT i+1 FROM s WHERE i<10
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i, randomblob(800) FROM s;
|
||||
} {10000 10}
|
||||
|
||||
for {set i 0} {$i < 4} {incr i} {
|
||||
do_execsql_test $tn.$i.1 {
|
||||
UPDATE t1 SET c=randomblob(800) WHERE (b%10)==5 AND ($i%2)
|
||||
}
|
||||
do_execsql_test $tn.$i.2 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
UPDATE t1 SET b=b+10, c=randomblob(800);
|
||||
}
|
||||
execsql COMMIT
|
||||
|
||||
do_test $tn.$i.3 { expr [filesize test.db-wal] < 100000 } 1
|
||||
do_test $tn.$i.4 { expr [filesize test.db-wal2] < 100000 } 1
|
||||
|
||||
set sum [db eval {SELECT sum(b), md5sum(c) FROM t1}]
|
||||
|
||||
do_test $tn.$i.5 {
|
||||
foreach f [glob -nocomplain test.db2*] {forcedelete $f}
|
||||
foreach f [glob -nocomplain test.db*] {
|
||||
forcecopy $f [string map {test.db test.db2} $f]
|
||||
}
|
||||
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval {SELECT sum(b), md5sum(c) FROM t1}
|
||||
} $sum
|
||||
db2 close
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
62
test/wal2rollback.test
Normal file
62
test/wal2rollback.test
Normal file
@ -0,0 +1,62 @@
|
||||
# 2017 September 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2rollback
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE INDEX i2 ON t1(b);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA cache_size = 5;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 1000
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i, randomblob(200) FROM s;
|
||||
} {wal2 10000}
|
||||
|
||||
do_test 1.1 {
|
||||
expr [file size test.db-wal] > 10000
|
||||
} 1
|
||||
|
||||
do_test 1.2 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=b+1;
|
||||
INSERT INTO t2 VALUES(1,2,3);
|
||||
}
|
||||
expr [file size test.db-wal2] > 10000
|
||||
} {1}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 1.3 {
|
||||
ROLLBACK;
|
||||
SELECT * FROM t2;
|
||||
SELECT count(*) FROM t1 WHERE a=b;
|
||||
PRAGMA integrity_check;
|
||||
} {1000 ok}
|
||||
|
||||
|
||||
|
||||
finish_test
|
73
test/wal2savepoint.test
Normal file
73
test/wal2savepoint.test
Normal file
@ -0,0 +1,73 @@
|
||||
# 2018 December 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2savepoint
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
reset_prng_state
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 15000;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA cache_size = 5;
|
||||
} {wal2 15000 0}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
|
||||
} {5120 23088 0}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
BEGIN;
|
||||
SAVEPOINT abc;
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 100)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
ROLLBACK TO abc;
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {210 ok}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
BEGIN;
|
||||
SAVEPOINT abc;
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 100)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
ROLLBACK TO abc;
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
|
||||
INSERT INTO t1 SELECT random(), random(), random() FROM s;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {220 ok}
|
||||
|
||||
|
||||
finish_test
|
475
test/wal2simple.test
Normal file
475
test/wal2simple.test
Normal file
@ -0,0 +1,475 @@
|
||||
# 2017 September 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix wal2simple
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests verify that a client can switch in and out of wal
|
||||
# and wal2 mode. But that it is not possible to change directly from wal
|
||||
# to wal2, or from wal2 to wal mode.
|
||||
#
|
||||
do_execsql_test 1.1.0 {
|
||||
PRAGMA journal_mode = wal2
|
||||
} {wal2}
|
||||
execsql { SELECT * FROM sqlite_master}
|
||||
do_execsql_test 1.x {
|
||||
PRAGMA journal_mode;
|
||||
PRAGMA main.journal_mode;
|
||||
} {wal2 wal2}
|
||||
db close
|
||||
do_test 1.1.1 { file size test.db } {1024}
|
||||
do_test 1.1.2 { hexio_read test.db 18 2 } 0303
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 1.2.0 {
|
||||
SELECT * FROM sqlite_master;
|
||||
PRAGMA journal_mode = delete;
|
||||
} {delete}
|
||||
db close
|
||||
do_test 1.2.1 { file size test.db } {1024}
|
||||
do_test 1.2.2 { hexio_read test.db 18 2 } 0101
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 1.3.0 {
|
||||
SELECT * FROM sqlite_master;
|
||||
PRAGMA journal_mode = wal;
|
||||
} {wal}
|
||||
db close
|
||||
do_test 1.3.1 { file size test.db } {1024}
|
||||
do_test 1.3.2 { hexio_read test.db 18 2 } 0202
|
||||
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 1.4.0 {
|
||||
PRAGMA journal_mode = wal2;
|
||||
} {1 {cannot change from wal to wal2 mode}}
|
||||
do_execsql_test 1.4.1 {
|
||||
PRAGMA journal_mode = wal;
|
||||
PRAGMA journal_mode = delete;
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_mode = wal2;
|
||||
} {wal delete wal2 wal2}
|
||||
do_catchsql_test 1.4.2 {
|
||||
PRAGMA journal_mode = wal;
|
||||
} {1 {cannot change from wal2 to wal mode}}
|
||||
db close
|
||||
do_test 1.4.3 { hexio_read test.db 18 2 } 0303
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that recovery in wal2 mode works.
|
||||
#
|
||||
forcedelete test.db test.db-wal test.db-wal2
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 5000;
|
||||
} {wal2 5000}
|
||||
|
||||
proc wal_hook {DB nm nFrame} { $DB eval { PRAGMA wal_checkpoint } }
|
||||
db wal_hook {wal_hook db}
|
||||
|
||||
for {set i 1} {$i <= 200} {incr i} {
|
||||
execsql { INSERT INTO t1 VALUES(NULL, randomblob(100)) }
|
||||
set res [db eval { SELECT sum(a), md5sum(b) FROM t1 }]
|
||||
|
||||
do_test 2.1.$i {
|
||||
foreach f [glob -nocomplain test.db2*] { forcedelete $f }
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval { SELECT sum(a), md5sum(b) FROM t1 }
|
||||
} $res
|
||||
|
||||
db2 close
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(x BLOB, y INTEGER PRIMARY KEY);
|
||||
CREATE INDEX i1 ON t1(x);
|
||||
PRAGMA cache_size = 5;
|
||||
PRAGMA journal_mode = wal2;
|
||||
} {wal2}
|
||||
|
||||
do_test 3.1 {
|
||||
execsql BEGIN
|
||||
for {set i 1} {$i < 1000} {incr i} {
|
||||
execsql { INSERT INTO t1 VALUES(randomblob(800), $i) }
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
catch { db close }
|
||||
foreach f [glob -nocomplain test.db*] { forcedelete $f }
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
PRAGMA journal_mode = wal2;
|
||||
} {wal2}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
SELECT * FROM t1;
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2}
|
||||
|
||||
do_test 4.4 {
|
||||
sqlite3 db2 test.db
|
||||
execsql { SELECT * FROM t1 } db2
|
||||
} {1 2}
|
||||
|
||||
do_test 4.5 {
|
||||
lsort [glob test.db*]
|
||||
} {test.db test.db-shm test.db-wal test.db-wal2}
|
||||
|
||||
do_test 4.6 {
|
||||
db close
|
||||
db2 close
|
||||
sqlite3 db test.db
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 4.7 {
|
||||
PRAGMA journal_size_limit = 4000;
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
INSERT INTO t1 VALUES(11, 12);
|
||||
INSERT INTO t1 VALUES(13, 14);
|
||||
INSERT INTO t1 VALUES(15, 16);
|
||||
INSERT INTO t1 VALUES(17, 18);
|
||||
SELECT * FROM t1;
|
||||
} {4000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}
|
||||
|
||||
do_test 4.8 {
|
||||
sqlite3 db2 test.db
|
||||
execsql { SELECT * FROM t1 } db2
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}
|
||||
|
||||
do_test 4.9 {
|
||||
db close
|
||||
db2 close
|
||||
lsort [glob test.db*]
|
||||
} {test.db}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1 ON t1(b, c);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 4000;
|
||||
} {wal2 4000}
|
||||
|
||||
proc wal_hook {DB nm nFrame} {
|
||||
$DB eval { PRAGMA wal_checkpoint }
|
||||
}
|
||||
db wal_hook [list wal_hook db]
|
||||
|
||||
|
||||
foreach js {4000 8000 12000} {
|
||||
foreach NROW [list 100 200 300 400 500 600 1000] {
|
||||
do_test 5.$js.$NROW.1 {
|
||||
db eval "DELETE FROM t1"
|
||||
db eval "PRAGMA journal_size_limit = $js"
|
||||
set nTotal 0
|
||||
for {set i 0} {$i < $NROW} {incr i} {
|
||||
db eval { INSERT INTO t1 VALUES($i, $i, randomblob(abs(random()%50))) }
|
||||
incr nTotal $i
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_test 5.$js.$NROW.2 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {
|
||||
PRAGMA integrity_check;
|
||||
SELECT count(*), sum(b) FROM t1;
|
||||
}
|
||||
} [list ok $NROW $nTotal]
|
||||
|
||||
db2 close
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE tx(x);
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA journal_size_limit = 3500;
|
||||
} {wal2 3500}
|
||||
|
||||
do_test 6.1 {
|
||||
for {set i 0} {$i < 10} {incr i} {
|
||||
execsql "CREATE TABLE t$i (x);"
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 6.2.1 {
|
||||
foreach f [glob -nocomplain test.db2*] { forcedelete $f }
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval { SELECT * FROM sqlite_master }
|
||||
} {}
|
||||
do_test 6.2.2 {
|
||||
db2 eval {
|
||||
PRAGMA journal_mode = wal2;
|
||||
SELECT * FROM sqlite_master;
|
||||
}
|
||||
} {wal2}
|
||||
|
||||
do_test 6.3.1 {
|
||||
db2 close
|
||||
foreach f [glob -nocomplain test.db2*] { forcedelete $f }
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval { SELECT * FROM sqlite_master }
|
||||
} {table tx tx 2 {CREATE TABLE tx(x)}}
|
||||
do_test 6.3.2 {
|
||||
db2 eval {
|
||||
PRAGMA journal_mode = wal2;
|
||||
SELECT * FROM sqlite_master;
|
||||
}
|
||||
} {wal2 table tx tx 2 {CREATE TABLE tx(x)}}
|
||||
|
||||
do_test 6.4.1 {
|
||||
db2 close
|
||||
foreach f [glob -nocomplain test.db2*] { forcedelete $f }
|
||||
forcecopy test.db-wal2 test.db2-wal2
|
||||
forcecopy test.db-wal test.db2-wal
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval { SELECT * FROM sqlite_master }
|
||||
} {}
|
||||
do_test 6.4.2 {
|
||||
db2 eval {
|
||||
PRAGMA journal_mode = wal2;
|
||||
SELECT * FROM sqlite_master;
|
||||
}
|
||||
} {wal2}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
sqlite3 db2 test.db
|
||||
do_execsql_test 7.0 {
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
PRAGMA journal_mode = wal2;
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
BEGIN;
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES( randomblob(8000) );
|
||||
COMMIT;
|
||||
} {10000 wal2 0}
|
||||
|
||||
do_test 7.1 {
|
||||
list [file size test.db-wal] [file size test.db-wal2]
|
||||
} {9464 0}
|
||||
|
||||
# Connection db2 is holding a PART1 lock.
|
||||
#
|
||||
# 7.2.2: Test that the PART1 does not prevent db from switching to the
|
||||
# other wal file.
|
||||
#
|
||||
# 7.2.3: Test that the PART1 does prevent a checkpoint of test.db-wal.
|
||||
#
|
||||
# 7.2.4: Test that after the PART1 is released the checkpoint is possible.
|
||||
#
|
||||
do_test 7.2.1 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT count(*) FROM t1;
|
||||
} db2
|
||||
} {1}
|
||||
do_test 7.2.2 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES( randomblob(800) );
|
||||
INSERT INTO t1 VALUES( randomblob(800) );
|
||||
}
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {13656 3176 1024}
|
||||
do_test 7.2.3 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {13656 3176 1024}
|
||||
do_test 7.2.4 {
|
||||
execsql { END } db2
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {13656 3176 11264}
|
||||
|
||||
# Connection db2 is holding a PART2_FULL1 lock.
|
||||
#
|
||||
# 7.3.2: Test that the lock does not prevent checkpointing.
|
||||
#
|
||||
# 7.3.3: Test that the lock does prevent the writer from overwriting
|
||||
# test.db-wal.
|
||||
#
|
||||
# 7.3.4: Test that after the PART2_FULL1 is released the writer can
|
||||
# switch wal files and overwrite test.db-wal
|
||||
#
|
||||
db close
|
||||
db2 close
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
do_test 7.3.1 {
|
||||
execsql {
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
INSERT INTO t1 VALUES(randomblob(10000));
|
||||
INSERT INTO t1 VALUES(randomblob(500));
|
||||
}
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT count(*) FROM t1;
|
||||
} db2
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 3176 12288}
|
||||
do_test 7.3.2 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 3176 22528}
|
||||
do_test 7.3.3 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(randomblob(10000));
|
||||
INSERT INTO t1 VALUES(randomblob(500));
|
||||
}
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 18896 22528}
|
||||
do_test 7.3.4 {
|
||||
execsql END db2
|
||||
execsql { INSERT INTO t1 VALUES(randomblob(5000)); }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 18896 22528}
|
||||
|
||||
# Connection db2 is holding a PART2 lock.
|
||||
#
|
||||
# 7.4.2: Test that the lock does not prevent writer switching to test.db-wal.
|
||||
#
|
||||
# 7.3.3: Test that the lock does prevent checkpointing of test.db-wal2.
|
||||
#
|
||||
# 7.3.4: Test that after the PART2 is released test.db-wal2 can be
|
||||
# checkpointed.
|
||||
#
|
||||
db close
|
||||
db2 close
|
||||
breakpoint
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
do_test 7.4.1 {
|
||||
execsql {
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
INSERT INTO t1 VALUES(randomblob(10000));
|
||||
INSERT INTO t1 VALUES(randomblob(10000));
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT count(*) FROM t1;
|
||||
} db2
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 12608 50176}
|
||||
do_test 7.4.2 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(randomblob(5000));
|
||||
}
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 12608 50176}
|
||||
do_test 7.4.3 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 12608 50176}
|
||||
do_test 7.4.4 {
|
||||
execsql END db2
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 12608 60416}
|
||||
|
||||
# Connection db2 is holding a PART1_FULL2 lock.
|
||||
#
|
||||
# 7.5.2: Test that the lock does not prevent a checkpoint of test.db-wal2.
|
||||
#
|
||||
# 7.5.3: Test that the lock does prevent the writer from overwriting
|
||||
# test.db-wal2.
|
||||
#
|
||||
# 7.5.4: Test that after the PART1_FULL2 lock is released, the writer
|
||||
# can switch to test.db-wal2.
|
||||
#
|
||||
db close
|
||||
db2 close
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
do_test 7.5.1 {
|
||||
execsql {
|
||||
PRAGMA wal_autocheckpoint = 0;
|
||||
PRAGMA journal_size_limit = 10000;
|
||||
INSERT INTO t1 VALUES(randomblob(10000));
|
||||
INSERT INTO t1 VALUES(randomblob(10000));
|
||||
PRAGMA wal_checkpoint;
|
||||
INSERT INTO t1 VALUES(randomblob(5000));
|
||||
}
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT count(*) FROM t1;
|
||||
} db2
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 12608 76800}
|
||||
do_test 7.5.2 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {12608 12608 87040}
|
||||
do_test 7.5.3.1 {
|
||||
execsql { INSERT INTO t1 VALUES(randomblob(5000)) }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {14704 12608 87040}
|
||||
do_test 7.5.3.2 {
|
||||
execsql { INSERT INTO t1 VALUES(randomblob(5000)) }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {22040 12608 87040}
|
||||
do_test 7.5.4 {
|
||||
execsql END db2
|
||||
execsql { INSERT INTO t1 VALUES(randomblob(5000)) }
|
||||
list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
|
||||
} {22040 12608 87040}
|
||||
|
||||
|
||||
finish_test
|
||||
|
93
test/wal2snapshot.test
Normal file
93
test/wal2snapshot.test
Normal file
@ -0,0 +1,93 @@
|
||||
# 2018 December 5
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL2" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set testprefix wal2snapshot
|
||||
ifcapable !wal {finish_test ; return }
|
||||
ifcapable !snapshot {finish_test; return}
|
||||
|
||||
foreach {tn mode} {1 wal 2 wal2} {
|
||||
reset_db
|
||||
do_execsql_test $tn.1 "PRAGMA journal_mode = $mode" $mode
|
||||
|
||||
do_execsql_test $tn.2 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
# Check that sqlite3_snapshot_get() is an error for a wal2 db.
|
||||
#
|
||||
if {$tn==1} {
|
||||
do_test 1.3 {
|
||||
set S [sqlite3_snapshot_get db main]
|
||||
sqlite3_snapshot_free $S
|
||||
} {}
|
||||
} else {
|
||||
do_test 2.3 {
|
||||
list [catch { sqlite3_snapshot_get db main } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
}
|
||||
|
||||
# Check that sqlite3_snapshot_recover() is an error for a wal2 db.
|
||||
#
|
||||
do_execsql_test $tn.4 COMMIT
|
||||
if {$tn==1} {
|
||||
do_test 1.5 {
|
||||
sqlite3_snapshot_recover db main
|
||||
} {}
|
||||
} else {
|
||||
do_test 2.5 {
|
||||
list [catch { sqlite3_snapshot_recover db main } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
}
|
||||
|
||||
# Check that sqlite3_snapshot_open() is an error for a wal2 db.
|
||||
#
|
||||
if {$tn==1} {
|
||||
do_test 1.6 {
|
||||
execsql BEGIN
|
||||
set SNAPSHOT [sqlite3_snapshot_get_blob db main]
|
||||
sqlite3_snapshot_open_blob db main $SNAPSHOT
|
||||
execsql COMMIT
|
||||
} {}
|
||||
} else {
|
||||
do_test 2.6.1 {
|
||||
execsql BEGIN
|
||||
set res [
|
||||
list [catch { sqlite3_snapshot_open_blob db main $SNAPSHOT } msg] $msg
|
||||
]
|
||||
execsql COMMIT
|
||||
set res
|
||||
} {1 SQLITE_ERROR}
|
||||
do_test 2.6.2 {
|
||||
execsql BEGIN
|
||||
execsql {SELECT * FROM sqlite_master}
|
||||
set res [
|
||||
list [catch { sqlite3_snapshot_open_blob db main $SNAPSHOT } msg] $msg
|
||||
]
|
||||
execsql COMMIT
|
||||
set res
|
||||
} {1 SQLITE_ERROR}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -85,7 +85,7 @@ proc lock_callback {method filename handle lock} {
|
||||
db2 eval { INSERT INTO x VALUES('x') }
|
||||
}
|
||||
}
|
||||
db timeout 10
|
||||
db timeout 1100
|
||||
do_catchsql_test 2.4 {
|
||||
BEGIN EXCLUSIVE;
|
||||
} {0 {}}
|
||||
|
@ -390,6 +390,8 @@ set options(THREADSAFE) {
|
||||
#endif
|
||||
}
|
||||
|
||||
set options(WAL2) { "WAL2", }
|
||||
|
||||
proc trim_name {in} {
|
||||
set ret $in
|
||||
if {[string range $in 0 6]=="SQLITE_"} {
|
||||
|
Loading…
x
Reference in New Issue
Block a user