aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/os_unix.c25
-rw-r--r--src/os_win.c19
-rw-r--r--src/sqlite.h.in15
-rw-r--r--src/test1.c33
-rw-r--r--src/wal.c4
5 files changed, 85 insertions, 11 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 7f0013e82..9e7b45821 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -250,8 +250,9 @@ struct unixFile {
/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
-#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
-#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
+#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
+#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
+#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
/*
** Include code that is common to all os_*.c files
@@ -3450,21 +3451,33 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
+ unixFile *pFile = (unixFile*)id;
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = ((unixFile*)id)->eFileLock;
+ *(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
- *(int*)pArg = ((unixFile*)id)->lastErrno;
+ *(int*)pArg = pFile->lastErrno;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
- ((unixFile*)id)->szChunk = *(int *)pArg;
+ pFile->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
- return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
+ return fcntlSizeHint(pFile, *(i64 *)pArg);
+ }
+ case SQLITE_FCNTL_PERSIST_WAL: {
+ int bPersist = *(int*)pArg;
+ if( bPersist<0 ){
+ *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
+ }else if( bPersist==0 ){
+ pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
+ }else{
+ pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
+ }
+ return SQLITE_OK;
}
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
diff --git a/src/os_win.c b/src/os_win.c
index 88b47a469..0ca5db6b4 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -102,8 +102,9 @@ struct winFile {
const sqlite3_io_methods *pMethod; /*** Must be first ***/
sqlite3_vfs *pVfs; /* The VFS used to open this file */
HANDLE h; /* Handle for accessing the file */
- unsigned char locktype; /* Type of lock currently held on this file */
+ u8 locktype; /* Type of lock currently held on this file */
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
+ u8 bPersistWal; /* True to persist WAL files */
DWORD lastErrno; /* The Windows errno from the last I/O error */
DWORD sectorSize; /* Sector size of the device file is on */
winShm *pShm; /* Instance of shared memory on this file */
@@ -1335,17 +1336,18 @@ static int winUnlock(sqlite3_file *id, int locktype){
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){
+ winFile *pFile = (winFile*)id;
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = ((winFile*)id)->locktype;
+ *(int*)pArg = pFile->locktype;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
- *(int*)pArg = (int)((winFile*)id)->lastErrno;
+ *(int*)pArg = (int)pFile->lastErrno;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
- ((winFile*)id)->szChunk = *(int *)pArg;
+ pFile->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
@@ -1355,6 +1357,15 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
SimulateIOErrorBenign(0);
return SQLITE_OK;
}
+ case SQLITE_FCNTL_PERSIST_WAL: {
+ int bPersist = *(int*)pArg;
+ if( bPersist<0 ){
+ *(int*)pArg = pFile->bPersistWal;
+ }else{
+ pFile->bPersistWal = bPersist!=0;
+ }
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_SYNC_OMITTED: {
return SQLITE_OK;
}
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index b8e8bfbc4..eb5f7a02a 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -752,6 +752,20 @@ struct sqlite3_io_methods {
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
** interrogated. The zDbName parameter is ignored.
+**
+** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
+** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
+** write ahead log and shared memory files used for transaction control
+** are automatically deleted when the latest connection to the database
+** closes. Setting persistent WAL mode causes those files to persist after
+** close. Persisting the files is useful when other processes that do not
+** have write permission on the directory containing the database file want
+** to read the database file, as the WAL and shared memory files must exist
+** in order for the database to be readable. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
+** WAL mode. If the integer is -1, then it is overwritten with the current
+** WAL persistence setting.
**
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -763,6 +777,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_FILE_POINTER 7
#define SQLITE_FCNTL_SYNC_OMITTED 8
#define SQLITE_FCNTL_WIN32_AV_RETRY 9
+#define SQLITE_FCNTL_PERSIST_WAL 10
/*
** CAPI3REF: Mutex Handle
diff --git a/src/test1.c b/src/test1.c
index 3301ab740..9a5a50103 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -5129,6 +5129,38 @@ static int file_control_win32_av_retry(
return TCL_OK;
}
+/*
+** tclcmd: file_control_persist_wal DB PERSIST-FLAG
+**
+** This TCL command runs the sqlite3_file_control interface with
+** the SQLITE_FCNTL_PERSIST_WAL opcode.
+*/
+static int file_control_persist_wal(
+ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ int rc;
+ int bPersist;
+ char z[100];
+
+ if( objc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
+ return TCL_ERROR;
+ }
+ if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
+ rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
+ sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
+ Tcl_AppendResult(interp, z, (char*)0);
+ return TCL_OK;
+}
+
/*
** tclcmd: sqlite3_vfs_list
@@ -5928,6 +5960,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
+ { "file_control_persist_wal", file_control_persist_wal, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
diff --git a/src/wal.c b/src/wal.c
index b9a03dff2..3bc42ffb1 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -1804,13 +1804,15 @@ int sqlite3WalClose(
*/
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
if( rc==SQLITE_OK ){
+ int bPersistWal = -1;
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
rc = sqlite3WalCheckpoint(
pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
);
- if( rc==SQLITE_OK ){
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
+ if( rc==SQLITE_OK && bPersistWal!=1 ){
isDelete = 1;
}
}