Compare commits

...

57 Commits

Author SHA1 Message Date
drh d23cae475d Bring the apple-wal-readonly branch up to date with the latest changes
in apple-osx, and especially the fix for disappearing WAL transactions.

FossilOrigin-Name: 5791232778c825ec487a06c72b638dcb247cdd58
2011-05-19 02:34:30 +00:00
drh d736884f3d Pull all the latest trunk changes, and especially the fix for WAL cache
spills causing transactions to disappear, into the apple-osx branch.

FossilOrigin-Name: 8d1a6bb002a7817fa7df932f7cab7220c1d62c0e
2011-05-19 01:51:25 +00:00
drh 7ae193a5cd Pull in the patches to support read-only WAL databases into a new branch
off of the apple-osx branch.  This also pulls in all the other pending
3.7.7 changes such as URI support.

FossilOrigin-Name: 97b980107676b2ea45a07c9c1a7de2e1ca74881f
2011-05-12 15:32:51 +00:00
dan a96a399ec9 Add missing comments associated with readonly shm changes.
FossilOrigin-Name: 6a2ea52e6c09a570428161090c2f087c66f714ec
2011-05-11 17:36:17 +00:00
dan 3640db58d0 Merge latest trunk changes. Add a couple of readonly shm tests.
FossilOrigin-Name: cde45a033ee6834900f5f5c272c383408883a74c
2011-05-11 15:53:16 +00:00
dan b6d2f9c5ef Only open a read-only connection to shared-memory if the "readonly_shm=1" option is specified as part of the database file URI (and if a read-write connection fails).
FossilOrigin-Name: 671ba5fc59f7a958e5a4138d2425b1173a442ad7
2011-05-11 14:57:33 +00:00
dan 4edc6bf3ee Add experimental support for read-only connections to WAL databases.
FossilOrigin-Name: bb59f9862da45d25fb51d7821130854828c91c98
2011-05-10 17:31:29 +00:00
drh 283f9e7ee6 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: f9b149e53815235aaf92f722e37c4819503d72b3
2011-05-05 15:52:46 +00:00
drh fa64665a49 Update the apple-osx branch to version 3.7.6.1.
FossilOrigin-Name: 289194d68e891e4977407d07e452e48844777a36
2011-04-13 15:42:26 +00:00
drh e127a2ea9f Pull all the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 4eaef4ad4cfda519f18922a249904d16489ee606
2011-04-09 18:13:35 +00:00
drh 5be1b1f262 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: c77a767cbd22354d9f6d5cef0d81ea721be593c7
2011-04-05 22:10:50 +00:00
drh 25d2380356 Pull the latest changes from trunk (and hence from schema-parse-refactor)
into the apple-osx branch.

FossilOrigin-Name: 8e885ddea0fc5d4c4256025c127e5d41d63c47a5
2011-04-05 13:38:12 +00:00
drh 69d67f5412 Merge in the latest changes from trunk.
FossilOrigin-Name: 6d78a25ddce75f63581be60c34dbc75f34c243df
2011-04-04 13:11:07 +00:00
drh 6f7fe3ef3e This is a version of the SQLite 3.7.5 release with Apple's changes for MacOS.
FossilOrigin-Name: 55d2e55b7b0f7851a565e3a982f772afdf8d7a12
2011-02-10 01:49:18 +00:00
drh e3a4e11bcc Pull in all the changes from trunk up through the version 3.7.5
release candidate 1.

FossilOrigin-Name: 09d6c91dcff0699daec02de0cfd1cdc4e61b4f6b
2011-01-27 18:48:02 +00:00
drh 67d225da53 Merge in all changes to the trunk through version 3.7.4rc3.
FossilOrigin-Name: d2ccf7fc0673e875ff7b84cd37b89c65df4bec7f
2010-12-07 15:49:03 +00:00
drh 5a5ced7da9 Merge all the latest changes from the trunk into the apple-osx branch.
FossilOrigin-Name: c8bc057c7def6bbbebd89ee52b582bad75fb0509
2010-11-19 23:50:48 +00:00
adam 985be1bce6 Integrated proxy locking file support for WAL journal mode and double free fix
FossilOrigin-Name: fd4d38fa66de85676189ff4922fb1bf5f8cac9c4
2010-11-09 00:43:59 +00:00
adam 99f24349ea fixed memory leak in proxy lock file error handling
FossilOrigin-Name: e01c5f3eda7fe6e6afe9c3894384f09b58173da1
2010-09-10 23:16:16 +00:00
adam 890b69fb83 replaced relative lock proxy paths with absolute
FossilOrigin-Name: 782c33512ab2b677b0734c591fcecddc5a655203
2010-09-10 20:19:06 +00:00
adam f5d6f1e0c5 replaced relative lock proxy paths with absolute
FossilOrigin-Name: 6a88cd46aeef3c50c91d5aadc61dd0b0982f8a4f
2010-09-10 00:59:28 +00:00
drh 5ec0cfe070 Make sure SQLite is running with MEMSTATUS enabled at the beginning of every
test script.

FossilOrigin-Name: b6e9a4d8f7d8b683b4098270e0be149df1ef295f
2010-09-10 00:18:12 +00:00
drh 3b3b1a538d Make sure MEMSTATUS is enabled at the beginning of the memsubsys2.test
script.

FossilOrigin-Name: cf23a354975f581c2cf2299e2b2a4e00819830ad
2010-09-09 23:40:42 +00:00
drh b0fa210aa3 The merge for check-in [415c448dc4] did not do exactly write, resulting in
a subtle bug in the SQLITE_FCNTL_SIZE_HINT logic.  This check-in is the
fix.

FossilOrigin-Name: badaaa18fd4a4402add6ae1b3ecadbb79f91fe37
2010-09-09 23:31:36 +00:00
drh 801829c812 Merge in the R-tree fix from the trunk.
FossilOrigin-Name: 02ee0bd5a305e3a6cd76f2e304f8a7effacd8433
2010-08-24 01:51:07 +00:00
drh 9b3c15e860 Merge changes through release 3.7.2 into the apple-osx branch.
FossilOrigin-Name: 415c448dc45a297bd1b0bbce25c4572eeab286f0
2010-08-24 01:08:11 +00:00
drh 61d3bfb78b Merge the 3.7.1 pre-release snapshot changes as of [2010-08-18]
into the apple-osx branch.

FossilOrigin-Name: 866e9286ae4226b2bec40ef18c672a41768abf1f
2010-08-18 00:24:09 +00:00
adam 45d55a254b Updating apple-osx with minor source fixes, database truncate and replace private calls and a bunch of conditionalization for tests running in different environments
FossilOrigin-Name: 5e2ee7db0f7a2a042b182336438107e2248d7b88
2010-08-18 00:09:47 +00:00
drh 51e5db70b6 Merge in all changes up to the 3.7.0.1 release.
FossilOrigin-Name: f88c6367d2f96cc93846ba38e6b963a1a3936e8d
2010-08-07 11:46:07 +00:00
drh f219bba933 Backport fix [a6bb2108bfb56] for a typo in the OS/2 interface.
FossilOrigin-Name: 042a1abb030a0711386add7eb6e10832cc8b0f57
2010-08-04 12:31:10 +00:00
drh a0166e1873 Update the version number to 3.7.0.1.
FossilOrigin-Name: 5074b85967df8f55739ba790924347c764288a88
2010-08-04 12:19:24 +00:00
drh aff0449d8f Backport fix [267492d3a7eff7b] for the performance regression caused by
automatic indexing and reported by ticket [8011086c85c6c4040].

FossilOrigin-Name: 3f367fe00e2adf87f3cc426466db4e3088e6f175
2010-08-04 12:13:35 +00:00
drh c55e9b815f Backport the [65b8636ac6e5] fix for ticket [51ae9cad317a1] to version 3.7.0.
FossilOrigin-Name: dec70c63d052bbe41fc4a065109d2845c67d3f15
2010-08-04 11:59:06 +00:00
drh 03ba419b3c Merge in changes up to and including the 3.6.23.1 release.
FossilOrigin-Name: 21ca87f69125a9e7124c6ddc566d17f64661b0d3
2010-06-16 19:48:56 +00:00
drh c4098a3d9f Cherry-pick the SQLITE_FCNTL_SIZE_HINT patch (check-in [2b7e3b4a30d6a7c4a8]
and bump the version number to 3.6.23.2.

FossilOrigin-Name: 776679af588625f13307369770979bccae7cf03a
2010-05-19 22:09:19 +00:00
drh 21ce77989a Disable the corruptE test which SQLITE_OVERSIZE_CELL_CHECK is enabled.
This is a cherrypick merge from check-in [1dc4f9fe9b83467ba].

FossilOrigin-Name: a40d080ca3c5f152f3296caf48f20728f61317de
2010-05-19 20:30:15 +00:00
drh 91973abb4b Include shell.c and sqlite3.def in the amalgamation ZIP archive.
Ticket [e063139eb3f8]

FossilOrigin-Name: b51fcac9fb4207810ee8d33ead47886e9c46d224
2010-03-31 11:56:47 +00:00
drh 722db051c6 Update the version number to 3.6.23.1.
FossilOrigin-Name: b078b588d617e07886ad156e9f54ade6d823568e
2010-03-26 22:28:06 +00:00
drh 87dd60cd8d Pull in other fixes from the trunk: check-ins [bea9258643],
[f186b6a619], and [bb591802ff].

FossilOrigin-Name: b1f342a6643829020beef542a0700d90822e6467
2010-03-26 21:53:11 +00:00
drh 7244fdc446 Fix to the crash8.test test script.
FossilOrigin-Name: f18a129a7aab09a1e0d34155e82bcbf7479a401d
2010-03-26 21:47:59 +00:00
drh 4f7e8fcded Enhance FTS3 to take advantage of the MAX() optimization.
Cherrypick of [b7e42ae774].

FossilOrigin-Name: 4b65b4805100852a2b6a834aa6efc0bbf25b539f
2010-03-26 17:42:57 +00:00
drh 95063a5774 Correctly handle strings with zero-length tokens in the FTS3 offsets()
function.  This is a cherrypick of [d37034f7fc].

FossilOrigin-Name: ff6ae4f0e461fb5f8d08a0092488b7cd71cffb05
2010-03-26 17:40:32 +00:00
drh ad7c2a87f5 After any rollback that modifies the database file, sync the database
before deleting the rollback journal.  This is a cherry-pick merge
of check-ins [b21b911f23] and [f2326dad4e]

FossilOrigin-Name: ca0bc2a22e893062876f67e0f53cbab44b45665d
2010-03-26 17:37:12 +00:00
adam cc3ec7cb2b fix merge error and compiler warning
FossilOrigin-Name: 5c0afe70a5ee2b378896bf30426823dc5ae4e95c
2010-02-26 22:05:01 +00:00
adam 3942b4b147 More double free paranoia
FossilOrigin-Name: 62dfb44b3b66c4acb1a7a10c44cbee1022a88883
2010-02-26 20:54:10 +00:00
drh 9aa0012a08 Merge latest changes from the trunk into the apple-osx branch.
FossilOrigin-Name: 4b72e39bd00572d9375639f4b978eff1b1d9aa20
2010-02-17 19:34:11 +00:00
adam efd8e3b33d Updated open mask to include SQLITE_OPEN_AUTOPROXY
FossilOrigin-Name: 7c3bede3f21812aa78105c6685654f12f0460eea
2010-01-26 01:14:33 +00:00
drh 0b90b2209f Align the os_unix.c source file with the version found on trunk.
FossilOrigin-Name: fa0f6c140e8ff9a5eed1d8a339fb6d55ecdca688
2010-01-20 13:20:22 +00:00
drh 9782039bde Update the Apple OS-X branch to include all of the latest changes in trunk.
FossilOrigin-Name: 96499b1dd69a0954e30e4b5b4f2272ab306afcdb
2010-01-20 01:26:07 +00:00
adam 332aa832ce robustness fixes for preventing a finalized statement from being reused
FossilOrigin-Name: a7a0c8d644873764cb799f9d6aacede4a4fb531f
2010-01-19 23:50:21 +00:00
drh bf4cad1e4c Update the OS-X branch to include all trunk changes through version 3.6.22.
FossilOrigin-Name: 541e2b488e4e40706e457c6d3b5647d53da02ce9
2010-01-06 13:12:48 +00:00
drh b0c5edcd06 Fix the main.mk makefile so that the sqlrr extension is built into the
amalgamation correctly.

FossilOrigin-Name: a3204d8a217d47e5120ab16918c1b7d4be5a021e
2009-12-23 18:06:49 +00:00
drh 2250799f0c Merge the latest changes on trunk (and especially the fix for
the (xANDy)OR(z) bug) into apple-osx.

FossilOrigin-Name: 5754a3a56144ee0e073c80651bf11cb23ee7f447
2009-12-16 23:46:11 +00:00
drh ca071dfd75 Merge all changes associated with the version 3.6.21 release into the OS-X
branch.

FossilOrigin-Name: ad08794d7239bb804eb39c00170821732b60cb65
2009-12-07 23:53:51 +00:00
adam ac0c39980a Fix for lock structure sharing with AFP-style locking
FossilOrigin-Name: 62f15c0aeaec5d778addb6edba62411c698bec0f
2009-11-09 19:30:44 +00:00
drh 04d4227255 Fix an undefined variable on non-Mac builds.
FossilOrigin-Name: 9552de8fb5ec7554c989edc138c0324c5fd0a206
2009-11-05 18:31:55 +00:00
adam e6c3c72c1b Merging in OSX customizations:
A ext/sqlrr/sqlrr.[ch]
-- add sql recording/replay support (very experimental extension -- pre alpha)

M ext/rtree/rtree.c
-- fix cast compiler warning

M src/func.c
-- substring backward compatiblity <rdar://problem/6778339> 

M src/legacy.c
-- replay recorder calls

M src/main.c
-- if SQLITE_ENABLE_AUTO_PROFILE, call sqlite3_profile when env(SQLITE_AUTO_PROFILE)   
-- replay recorder calls

M src/mem1.c
-- use custom malloc zone on single core systems

M src/os_unix.c
-- hostid via gethostuuid
-- read-only file system support for proxy locking
-- improved handling of simulated shared lock on AFP/SMB on 64 bit systems
-- disable whole-file-lock NFS file locking
-- fix for downgrading from exclusive to shared lock on NFS
-- proxy lock breaking & recreating local lock files
-- support SQLITE_OPEN_AUTOPROXY flag
-- only write 1st byte into new zero-length files if fs is DOS
-- cache fs type info in unixFile struct
-- force use of fsync() even if fdatasync() is available
-- remove flock locking style support for SMB
-- replace strcpy with strlcpy

M src/prepare.c
-- replay recorder calls

M src/sqlite.h.in
-- added SQLITE_OPEN_AUTOPROXY

M src/sqliteInt.h
-- include replay recorder header

M src/vdbeapi.c
-- checking for NULL statement for <rdar://6646331> 
-- replay recorder calls

FossilOrigin-Name: 941a01eb868815f566539e9ab21f807d9e798e40
2009-11-03 22:34:35 +00:00
67 changed files with 2389 additions and 364 deletions
+14
View File
@@ -323,6 +323,9 @@ SRC += \
SRC += \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
SRC += \
$(TOP)/ext/sqlrr/sqlrr.h \
$(TOP)/ext/sqlrr/sqlrr.c
# Generated source code files
@@ -470,6 +473,17 @@ EXTHDR += \
$(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
$(TOP)/ext/rtree/sqlite3rtree.h
EXTHDR += \
$(TOP)/ext/sqlrr/sqlrr.h
# If using the amalgamation, use sqlite3.c directly to build the test
# fixture. Otherwise link against libsqlite3.la. (This distinction is
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
+1
View File
@@ -105,6 +105,7 @@
#include <string.h>
#include <assert.h>
#include <stdint.h>
#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
+54
View File
@@ -0,0 +1,54 @@
sqlrr - 10/19/2009
SQL Replay Recording
SUMMARY
-------------------------------------------------------
This extension enables recording sqlite API calls that access the database so that they can be replayed or examined.
USAGE
------------------------------------------------------
Recording is enabled by compiling sqlite with symbolic constant SQLITE_ENABLE_SQLRR defined.
By default logs are written to /tmp/<databasename>_<pid>_<connection_number>.sqlrr, to choose another directory, set the environment variable SQLITE_REPLAY_RECORD_DIR to that path.
FILE FORMAT
-----------------------------------------------------
file: <header>[<sql-command>]*
header: <signature><format-version>
signature: SQLRR (5 bytes)
format-version: n (1 byte)
sql-command: <timestamp><type><arg-data>
timestamp: n (16 bytes)
type: n (1 byte)
open 0
close 1
exec 8
bind-text 16
bind-double 17
bind-int 18
bind-null 19
bind-value 20
bind-clear 21
prep 32
step 33
reset 34
finalize 35
open-arg-data: <connection><path><flags>
close-arg-data: <connection>
exec-arg-data: <connection><len><statement-text>
bind-text-arg-data: <statement-ref><index><len><data>
bind-double-arg-data: <statement-ref><index><data>
bind-int-arg-data: <statement-ref><index><data>
bind-null-arg-data: <statement-ref><index>
bind-value-arg-data: <statement-ref><index><len><data> ???
bind-clear-arg-data: <statement-ref>
prep-arg-data: <connection><len><statement-text>
step-arg-data: <statement-ref>
reset-arg-data: <statement-ref>
finalize-arg-data: <statement-ref>
NOTES
+581
View File
@@ -0,0 +1,581 @@
/*
* sqlrr.c
*/
#include "sqlrr.h"
#if defined(SQLITE_ENABLE_SQLRR)
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include <errno.h>
#include <pthread.h>
#include <libkern/OSAtomic.h>
#include "sqliteInt.h"
#include "vdbeInt.h"
#define LOGSUFFIXLEN 48
/*
* Data types
*/
typedef struct SRRLogRef SRRLogRef;
struct SRRLogRef {
int fd;
sqlite3 *db;
const char *dbPath;
char *logPath;
int connection;
int depth;
SRRLogRef *nextRef;
};
/*
* Globals
*/
SRRLogRef *logRefHead = NULL;
int dbLogCount = 0;
static int srr_enabled = 1;
pthread_mutex_t srr_log_mutex;
static volatile int32_t srr_initialized = 0;
/*
* Log management
*/
extern void SRRecInitialize() {
int go = OSAtomicCompareAndSwap32Barrier(0, 1, &srr_initialized);
if( go ){
pthread_mutex_init(&srr_log_mutex, NULL);
}
}
static SRRLogRef *createLog(sqlite3 *db, const char *dbPath) {
SRRLogRef *ref = NULL;
char *baseDir = getenv("SQLITE_REPLAY_RECORD_DIR");
char logPath[MAXPATHLEN] = "";
char suffix[LOGSUFFIXLEN] = "";
const char *dbName = dbPath;
int len = 0;
int index = 0;
int fd = -1;
size_t out;
unsigned char version = SRR_FILE_VERSION;
SRRecInitialize();
/* construct the path for the log file
* ${SQLITE_REPLAY_DIR}/<dbname>_<pid>_<connection_number>.sqlrr
*/
if (baseDir == NULL) {
baseDir = "/tmp"; /* getenv(TMPDIR) */
}
len = strlen(baseDir);
strlcat(logPath, baseDir, MAXPATHLEN);
if ((len>0) && (baseDir[len-1] != '/')) {
strlcat(logPath, "/", MAXPATHLEN);
}
len = strlen(dbPath);
for (index = len-2; index >= 0; index --){
if (dbPath[index] == '/') {
dbName = &dbPath[index+1];
break;
}
}
strlcat(logPath, dbName, MAXPATHLEN);
int cNum = ++dbLogCount;
snprintf(suffix, sizeof(suffix), "_%d_%d_XXXX.sqlrr", getpid(), cNum);
len = strlcat(logPath, suffix, MAXPATHLEN);
/* make it unique if we have the space */
if ((len + 1) < MAXPATHLEN) {
fd = mkstemps(logPath, 6);
} else {
fprintf(stderr, "Failed to create sqlite replay log path for %s [%s]\n", dbPath, logPath);
return NULL;
}
if (fd == -1) {
fprintf(stderr, "Failed to create sqlite replay log file for %s with path %s [%s]\n", dbPath, logPath, strerror(errno));
return NULL;
}
fprintf(stdout, "Writing sqlite replay log file %s\n", logPath);
out = write(fd, SRR_FILE_SIGNATURE, SRR_FILE_SIGNATURE_LEN);
if (out!=-1) {
out = write(fd, &version, 1);
}
if (out == -1){
fprintf(stderr, "Write failure on log [%s]: %s\n", logPath, strerror(errno));
close(fd);
return NULL;
}
len = strlen(logPath) + 1;
ref = (SRRLogRef *)malloc(sizeof(SRRLogRef));
ref->db = db;
ref->dbPath = dbPath;
ref->logPath = (char *)malloc(len * sizeof(char));
strlcpy(ref->logPath, logPath, len);
ref->fd = fd;
ref->connection = cNum;
ref->depth = 0;
pthread_mutex_lock(&srr_log_mutex);
ref->nextRef = logRefHead;
logRefHead = ref;
pthread_mutex_unlock(&srr_log_mutex);
return ref;
}
static void closeLog(sqlite3 *db) {
SRRLogRef *ref = NULL;
SRRLogRef *lastRef = NULL;
pthread_mutex_lock(&srr_log_mutex);
for (ref = logRefHead; ref != NULL; ref = ref->nextRef) {
if (ref->db == db) {
if (lastRef == NULL) {
logRefHead = ref->nextRef;
} else {
lastRef->nextRef = ref->nextRef;
}
}
}
pthread_mutex_unlock(&srr_log_mutex);
if (ref != NULL) {
fprintf(stdout, "Closing sqlite replay log file %s\n", ref->logPath);
close(ref->fd);
free(ref->logPath);
free(ref);
}
}
static SRRLogRef *getLog(sqlite3 *db) {
pthread_mutex_lock(&srr_log_mutex);
SRRLogRef *ref = logRefHead;
for (ref = logRefHead; ref != NULL; ref = ref->nextRef) {
if (ref->db == db) {
pthread_mutex_unlock(&srr_log_mutex);
return ref;
}
}
pthread_mutex_unlock(&srr_log_mutex);
return NULL;
}
/*
* SQLite recording API
*/
void SQLiteReplayRecorder(int flag) {
srr_enabled = flag;
}
// open-arg-data: <connection><len><path><flags>
void _SRRecOpen(sqlite3 *db, const char *path, int flags) {
if (!srr_enabled) return;
if (db) {
SRRLogRef *ref = createLog(db, path);
if (ref) {
SRRCommand code = SRROpen;
int len = strlen(path);
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out=write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) { out=write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
if (out!=-1) { out=write(ref->fd, &len, sizeof(len)); }
if (out!=-1) { out=write(ref->fd, path, len); }
if (out!=-1) { out=write(ref->fd, &flags, sizeof(flags)); }
if (out==-1) {
fprintf(stderr, "Error writing open to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(db);
}
}
}
}
//close-arg-data: <connection>
void SRRecClose(sqlite3 *db) {
if (!srr_enabled) return;
if (db) {
SRRLogRef *ref = getLog(db);
if (ref) {
SRRCommand code = SRRClose;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
if (out==-1) {
fprintf(stderr, "Error writing close to log file [%s]: %s\n", ref->logPath, strerror(errno));
}
closeLog(db);
}
}
}
// exec-arg-data: <connection><len><statement-text>
void SRRecExec(sqlite3 *db, const char *sql) {
if (!srr_enabled) return;
if (db) {
SRRLogRef *ref = getLog(db);
if (ref) {
if (ref->depth == 0) {
SRRCommand code = SRRExec;
int len = strlen(sql);
struct timeval tv;
size_t out;
ref->depth = 1;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
if (out!=-1) { out = write(ref->fd, &len, sizeof(len)); }
if (out!=-1) { out = write(ref->fd, sql, len); }
if (out==-1) {
fprintf(stderr, "Error writing exec to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(db);
}
} else {
ref->depth ++;
}
}
}
}
void SRRecExecEnd(sqlite3 *db) {
if (!srr_enabled) return;
if (db) {
SRRLogRef *ref = getLog(db);
if (ref) {
ref->depth --;
}
}
}
// prep-arg-data: <connection><len><statement-text><savesql><statement-ref>
void _SRRecPrepare(sqlite3 *db, const char *sql, int nBytes, int saveSql, sqlite3_stmt *pStmt) {
if (!srr_enabled) return;
if ((db!=NULL)&&(pStmt!=NULL)) {
SRRLogRef *ref = getLog(db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRPrepare;
struct timeval tv;
size_t out;
int sqlLen = nBytes;
if (sqlLen == -1) {
sqlLen = strlen(sql);
}
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
if (out!=-1) { out = write(ref->fd, &sqlLen, sizeof(sqlLen)); }
if (out!=-1) { out = write(ref->fd, sql, sqlLen); }
if (out!=-1) { out = write(ref->fd, &saveSql, sizeof(saveSql)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out==-1) {
fprintf(stderr, "Error writing prepare to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(db);
}
}
}
}
//step-arg-data: <statement-ref>
void SRRecStep(sqlite3_stmt *pStmt) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref) {
if (ref->depth == 0) {
SRRCommand code = SRRStep;
struct timeval tv;
size_t out;
ref->depth = 1;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out==-1) {
fprintf(stderr, "Error writing step to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
} else {
ref->depth ++;
}
}
}
}
void SRRecStepEnd(sqlite3_stmt *pStmt) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref) {
ref->depth --;
}
}
}
// reset-arg-data: <statement-ref>
void SRRecReset(sqlite3_stmt *pStmt) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRReset;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out==-1) {
fprintf(stderr, "Error writing reset to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// finalize-arg-data: <statement-ref>
void SRRecFinalize(sqlite3_stmt *pStmt) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRFinalize;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out==-1) {
fprintf(stderr, "Error writing finalize to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// bind-text-arg-data: <statement-ref><index><len><data>
void SRRecBindText(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRBindText;
struct timeval tv;
size_t out;
int64_t textLen = nData;
if (textLen == -1) {
textLen = strlen(zData);
}
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
if (out!=-1) { out = write(ref->fd, &textLen, sizeof(textLen)); }
if (out!=-1) { out = write(ref->fd, zData, textLen); }
if (out==-1) {
fprintf(stderr, "Error writing bind text to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// bind-blob-arg-data: <statement-ref><index><len>[<data>]
void SRRecBindBlob(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRBindBlob;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
if (zData == NULL) {
int64_t negNData = -nData;
if (out!=-1) { out = write(ref->fd, &negNData, sizeof(negNData)); }
} else {
if (out!=-1) { out = write(ref->fd, &nData, sizeof(nData)); }
if (out!=-1) { out = write(ref->fd, zData, nData); }
}
if (out==-1) {
fprintf(stderr, "Error writing bind blob to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// bind-double-arg-data: <statement-ref><index><data>
void SRRecBindDouble(sqlite3_stmt *pStmt, int i, double value) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRBindDouble;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
if (out!=-1) { out = write(ref->fd, &value, sizeof(value)); }
if (out==-1) {
fprintf(stderr, "Error writing bind double to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// bind-int-arg-data: <statement-ref><index><data>
void SRRecBindInt64(sqlite3_stmt *pStmt, int i, int64_t value) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRBindInt;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
if (out!=-1) { out = write(ref->fd, &value, sizeof(value)); }
if (out==-1) {
fprintf(stderr, "Error writing bind int to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// bind-null-arg-data: <statement-ref><index>
void SRRecBindNull(sqlite3_stmt *pStmt, int i) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRBindNull;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
if (out==-1) {
fprintf(stderr, "Error writing bind null to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
// bind-value-arg-data: <statement-ref><index><len><data> ???
void SRRecBindValue(sqlite3_stmt *pStmt, int i, const sqlite3_value *value) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
fprintf(stderr, "SRRecBindValue(sqlite3_bind_value) is not yet supported, closing [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
// bind-clear-arg-data: <statement-ref>
void SRRecClearBindings(sqlite3_stmt *pStmt) {
if (!srr_enabled) return;
if(pStmt!=NULL) {
Vdbe *v = (Vdbe *)pStmt;
SRRLogRef *ref = getLog(v->db);
if (ref && (ref->depth == 0)) {
SRRCommand code = SRRBindClear;
struct timeval tv;
size_t out;
gettimeofday(&tv, NULL);
out = write(ref->fd, &tv, sizeof(tv));
if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
if (out!=-1) {
int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
out = write(ref->fd, &stmtInt, sizeof(int64_t));
}
if (out==-1) {
fprintf(stderr, "Error writing clear bindings to log file [%s]: %s\n", ref->logPath, strerror(errno));
closeLog(ref->db);
}
}
}
}
#endif /* SQLITE_ENABLE_SQLRR */
+61
View File
@@ -0,0 +1,61 @@
/*
* sqlrr.h
*/
#ifndef _SQLRR_H_
#define _SQLRR_H_
/*
** Header constants
*/
#define SRR_FILE_SIGNATURE "SQLRR"
#define SRR_FILE_SIGNATURE_LEN 5
#define SRR_FILE_VERSION 0x1
#define SRR_FILE_VERSION_LEN 1
#if defined(SQLITE_ENABLE_SQLRR)
#include "sqlite3.h"
#include <sys/types.h>
#define SRRecOpen(A,B,C) if(!rc){_SRRecOpen(A,B,C);}
#define SRRecPrepare(A,B,C,D,E) if(!rc){_SRRecPrepare(A,B,C,D,E);}
typedef enum {
SRROpen = 0,
SRRClose = 1,
SRRExec = 8,
SRRBindText = 16,
SRRBindBlob = 17,
SRRBindDouble = 18,
SRRBindInt = 19,
SRRBindNull = 20,
SRRBindValue = 21,
SRRBindClear = 22,
SRRPrepare = 32,
SRRStep = 33,
SRRReset = 34,
SRRFinalize = 35
} SRRCommand;
extern void SQLiteReplayRecorder(int flag);
extern void _SRRecOpen(sqlite3 *db, const char *path, int flags);
extern void SRRecClose(sqlite3 *db);
extern void SRRecExec(sqlite3 *db, const char *sql);
extern void SRRecExecEnd(sqlite3 *db);
extern void _SRRecPrepare(sqlite3 *db, const char *sql, int nBytes, int saveSql, sqlite3_stmt *stmt);
extern void SRRecStep(sqlite3_stmt *pStmt);
extern void SRRecStepEnd(sqlite3_stmt *pStmt);
extern void SRRecReset(sqlite3_stmt *pStmt);
extern void SRRecFinalize(sqlite3_stmt *pStmt);
extern void SRRecBindText(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData);
extern void SRRecBindBlob(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData);
extern void SRRecBindDouble(sqlite3_stmt *pStmt, int i, double value);
extern void SRRecBindInt64(sqlite3_stmt *pStmt, int i, int64_t value);
extern void SRRecBindNull(sqlite3_stmt *pStmt, int i);
extern void SRRecBindValue(sqlite3_stmt *pStmt, int i, const sqlite3_value *value);
extern void SRRecClearBindings(sqlite3_stmt *pStmt);
#endif /* defined(SQLITE_ENABLE_SQLRR) */
#endif /* _SQLRR_H_ */
+6 -2
View File
@@ -204,6 +204,8 @@ SRC += \
SRC += \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
SRC += \
$(TOP)/ext/sqlrr/sqlrr.c
# Generated source code files
@@ -345,6 +347,8 @@ EXTHDR += \
$(TOP)/ext/rtree/rtree.h
EXTHDR += \
$(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
$(TOP)/ext/sqlrr/sqlrr.h
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -366,10 +370,10 @@ sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
# files are automatically generated. This target takes care of
# all that automatic generation.
#
target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl
target_source: $(SRC) $(EXTHDR) $(TOP)/tool/vdbe-compress.tcl
rm -rf tsrc
mkdir tsrc
cp -f $(SRC) tsrc
cp -f $(SRC) $(EXTHDR) tsrc
rm tsrc/sqlite.h.in tsrc/parse.y
tclsh $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
mv vdbe.new tsrc/vdbe.c
+70 -64
View File
@@ -1,7 +1,7 @@
C When\scommitting\sa\sWAL\stransaction,\smake\ssure\sat\sleast\sone\spage\sis\nwritten\sto\sthe\sWAL\sfile\sso\sthat\sthe\sWAL\ssubsystem\swill\shave\sa\spage\non\swhich\sto\sset\sthe\scommit\sflag.\nTicket\s[2d1a5c67dfc236].
D 2011-05-19T01:21:42.431
C Bring\sthe\sapple-wal-readonly\sbranch\sup\sto\sdate\swith\sthe\slatest\schanges\nin\sapple-osx,\sand\sespecially\sthe\sfix\sfor\sdisappearing\sWAL\stransactions.
D 2011-05-19T02:34:30.938
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
F Makefile.in a38f09acc876beec6b103a6e12a33795c6b1df9c
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
@@ -82,7 +82,7 @@ F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
F ext/icu/icu.c eb9ae1d79046bd7871aa97ee6da51eb770134b5a
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 2445bec932f58f8f4fe9de49a63bd6bf24db82d6
F ext/rtree/rtree.c d3741cde910b659fd66ca4289eed430e90bdbbb0
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 28e1b8da4da98093ce3210187434dd760a8d89d8
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -100,9 +100,12 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/sqlrr/README.txt 4239030e73023e72a2e727808cd433577d5bf730
F ext/sqlrr/sqlrr.c 8d1e6571cd6a6beabdb5bcdfe3a0e723b914db41
F ext/sqlrr/sqlrr.h 09e4f8929ad9bc2638732c0cc0db5eef8c417824
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F main.mk 6111163d4e9720e4212ef288e967b4aa2c2ce379
F main.mk 3c7e0f21e531b58cfe398964a464411543462eec
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@@ -117,13 +120,13 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
F src/attach.c a87bfb77a720f7aa02791434aacfd9bc8feb50cc
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 975ad691a57eb1fb60f1ec76ad0b6571eace62f9
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btree.h d796dc4030b3cce7f5a0cc4f2f986d2befa6b8ac
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
F src/build.c 0132bc6631fa617a1d28ef805921f6dbac18a514
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
@@ -134,20 +137,20 @@ F src/delete.c 7a24fcc9a31664d145acb97ce56b6d9f249a25e4
F src/expr.c e3cf0957c6b8faaaf7386a3bc69e53c0dc9705be
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
F src/func.c b9117e40975245b8504cf3625d7e321d8d4b63dc
F src/func.c c02fda657f2366c493198c3e480695fc69972c5f
F src/global.c 29bfb85611dd816b04f10fba0ca910366e128d38
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 3eea5a53d2644116fb865afaa4699fabe62b441c
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
F src/main.c 059daeed5876b3604f0192f838faf5f4db138901
F src/main.c 6dc61e8bf59098d1ec49b20760e91539997acaaf
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
F src/mem1.c 46095d62b241466ef51970e592aa3a7a87e443e1
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
@@ -163,30 +166,31 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
F src/os_unix.c 6d4a58d81ad4b782406519f3790202f330e89bb7
F src/os_unix.c d5feb6cbdbbeb1f2d3d8c816dc93da7c408468a8
F src/os_win.c 218b899469e570d46eb8147c2383075f7c026230
F src/pager.c 4b2358556c88660a94a4560de95dd728911e00fd
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
F src/pager.c 928d50d35d0167799ac77357e6c4966b3be93f9d
F src/pager.h 34c6b029446f06f40847746d22faac0d354dd909
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
F src/pragma.c 9e778decc3ee9bcaf88904b4a3b0a4360aaf0eab
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
F src/pragma.c 8756649386a4eb7192915fb44e177d30e19f723c
F src/prepare.c 9d7403fe75fefa134351b41400d09ba1b189134b
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
F src/shell.c decd04236a7ef26be5ef46d4ea963044bfad9a48
F src/sqlite.h.in 8bbf8d9bc5f1a9474a633a2de7014506f1f06b90
F src/sqlite.h.in 1c5172169121b89b2b08757acc57ec7a846f9c92
F src/sqlite3_private.h 2a814d17913732831acf13e7e87860105a3416e4
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h 771087591052966d36ac1fcd3c8bb7a8c6cf9a38
F src/sqliteInt.h 52b58043e97367686042345d2e581604e44a1cbf
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b
F src/test1.c 4a1171af201be90c21d64a872e686b1333d9a2cf
F src/test1.c acdf3394565b1669657ea175013f418adb8fae44
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
@@ -197,9 +201,9 @@ F src/test8.c 6b1d12912a04fe6fca8c45bb9c3ea022f4352228
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_backup.c 64fd6173ad99daade1227aa17c3ca0d18fa5e5fa
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
F src/test_config.c 9a6aa8301a56906612b5e70f5b38e80cfb8af8e7
F src/test_config.c 308a99163bd821efa84f0ada99bc61fbbf44b613
F src/test_demovfs.c 938d0f595f8bd310076e1c06cf7885a01ce7ce01
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
@@ -236,17 +240,17 @@ F src/update.c 5bcb56e5c7380a2eecb0e71891dbd4ad7437748f
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
F src/vdbe.c 343a068e8daeb8475e66776feb9f2974046e95c5
F src/vdbe.c f997c49fa6745bce83e23ae7863a328f8cb9d448
F src/vdbe.h 8a675fefdf7119441fe817c800a9a52440c2e797
F src/vdbeInt.h fe8f58d305e629fff02f61f655aca1d299f1f6ae
F src/vdbeapi.c e0e2672e0a96ae3f8575c8ecd02912a3e8a554a1
F src/vdbeapi.c 34b6686d9079264bc715f63e41bc2f0d9b98de89
F src/vdbeaux.c 535851211df61d83213c83d5ffd3c6ce9ecbdc18
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
F src/vtab.c 48dcef8bc757c2e7b488f68b5ddebb1650da2450
F src/wal.c de27c34c8016c00be348fc6bed588816557ceb66
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
F src/wal.c 11c17da2060683c9c0f3538f57e89643b0e2eb7e
F src/wal.h 0835021ae243c2f1119e997e8af5d8cc3b991de1
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199
@@ -270,7 +274,7 @@ F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test f3592d79c84d6e83a5f50d3fd500445f7d97dfdf
F test/attach.test 2bb09073d7d5499127db00f50780766dcea913e1
F test/attach.test e26b6c050d5b2ba0064288137bdd325370c11e65
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
F test/attach3.test bd9830bc3a0d22ed1310c9bff6896927937017dc
F test/attach4.test 31f9eb0ca7bdbc393cc4657b877903a226a83d4b
@@ -293,7 +297,7 @@ F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070
F test/bigfile.test a8ec8073a20207456dab01a29ad9cde42b0dd103
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
F test/bind.test 3c7b320969000c441a70952b0b15938fbb66237c
F test/bind.test 30af0fc61bc3836034215cdbdeca46113ca1b4a1
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
F test/blob.test e7ac6c7d3a985cc4678c64f325292529a69ae252
@@ -388,12 +392,12 @@ F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de
F test/eqp.test f14fadd76da53405e9885e2431cacf7191d83cdb
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
F test/exclusive.test 897074dc6706b0c4f3b1dc4580ffddffe2a79206
F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 5e2d64b4eb5a9d08876599bdae2e1213d2d12e2a
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
F test/fallocate.test a9927b638567e2e776c112f54d701402a0e74023
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
@@ -529,7 +533,7 @@ F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
F test/join6.test bf82cf3f979e9eade83ad0d056a66c5ed71d1901
F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
F test/journal2.test 50a3604768494d4a337f194f0a9480e7c57dcb72
F test/journal3.test ff175219be1b02d2f7e54297ad7e491b7533edb6
F test/journal3.test 7cfbd86429305c96c9d985665320db5364764d96
F test/jrnlmode.test e3fe6c4a2c3213d285650dc8e33aab7eaaa5ce53
F test/jrnlmode2.test a19e28de1a6ec898067e46a122f1b71c9323bf00
F test/jrnlmode3.test c6522b276ba315fd1416198de6fc1da9e72409fb
@@ -545,12 +549,13 @@ F test/lock.test db74fdf5a73bad29ab3d862ea78bf1068972cc1d
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
F test/lock4.test c82268c031d39345d05efa672f80b025481b3ae5
F test/lock5.test b2abb5e711bc59b0eae00f6c97a36ec9f458fada
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock5.test d0d313f059ae5661726d3f197ba6ed8f69257d8e
F test/lock6.test 83434ae8ca1d1c5e2eaf74d4e44aa24ab62b291c
F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
F test/lock_common.tcl d279887a0ab16cdb6d935c1203e64113c5a000e9
F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
F test/lock_proxy.test 95be9c32d79be25cf643b4e41a0aa0e53aa21621
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
F test/main.test 9d7bbfcc1b52c88ba7b2ba6554068ecf9939f252
F test/main.test 753e2b772c041bd8dbd17c7e4132b3981378eaab
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test e56c9c3358da2c18385aea15a42dc970913986c2
F test/malloc3.test 4128b1e6ffa506103b278ad97af89174f310c7ca
@@ -572,12 +577,12 @@ F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9
F test/malloc_common.tcl 50d0ed21eed0ae9548b58935bd29ac89a05a54fa
F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c
F test/malloc_common.tcl 228af61862dd3f61f09dab4251ce3c1660b8b878
F test/manydb.test 7faa0df55bbab2b14c25f323801db336c4e7ce3a
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test 708a028d6d373e5b3842e4bdc8ba80998c9a4da6
F test/memdb.test 4aa287fc0c18229086e7c286285d60773f0169c4
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 679db68394a5692791737b150852173b3e2fea10
F test/memsubsys1.test 7abc5c90b20e25040e2c800e3d95703d59d843a2
F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
@@ -604,7 +609,7 @@ F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c
F test/pager1.test 8baf4470b29511503abcaf1f17d16b16462e4d54
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test 9de4d3e0c59970b4c6cb8dac511fa242f335d8a7
F test/pagerfault.test bea066b9162e1ab6843c2c1524ebb0965715e956
F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401
F test/pagerfault3.test f16e2efcb5fc9996d1356f7cbc44c998318ae1d7
F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
@@ -612,7 +617,7 @@ F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6
F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
F test/pragma.test 88048136eed6baa2097dd7ab5145d3288128ca70
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
@@ -654,7 +659,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532
F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b
F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25
F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e
F test/shared.test e5ed27551ba06b28e851101683f0caef1445f4ac
F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c
F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962
F test/shared4.test d0fadacb50bb6981b2fb9dc6d1da30fa1edddf83
@@ -677,7 +682,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/sqllimits1.test e90a0ed94452076f6a10209d378e06b5f75ef0a0
F test/stat.test c7b20ea43003dc2dc33335e231c27be8284c4a2a
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/stmt.test 78a6764439cfa5abdcbf98d4d084739e81eeec4f
F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
@@ -688,10 +693,10 @@ F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
F test/table.test 04ba066432430657712d167ebf28080fe878d305
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/tempdb.test 3263e5c3f0604e54d307481e8587327c54544d18
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
F test/tester.tcl a791ee74cb6b8f8613079ccc018bf2c8b952a26c
F test/tester.tcl 51d761878d9934e19fc0eda3c9c5dbc39d02522d
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
@@ -782,7 +787,7 @@ F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
F test/tkt3442.test 0adb70e9fe9cb750a702065a68ad647409dbc158
F test/tkt3457.test edbf54b05cbe5165f00192becbd621038f1615e4
F test/tkt3457.test 8a8f29536bf65b994bef5dde881404530b61a62a
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
F test/tkt3508.test d75704db9501625c7f7deec119fcaf1696aefb7d
@@ -869,26 +874,27 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
F test/wal.test 5617ad308bfdb8a8885220d8a261a6096a8d7e57
F test/wal2.test aa0fb2314b3235be4503c06873e41ebfc0757782
F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd
F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
F test/wal.test 3ff610479cd005117f54a8c003a8d86432e6f2ac
F test/wal2.test 24239bb8cd8ca5e47c9ab4ac705f7343d2f9b5a2
F test/wal3.test 34c65b1cb78e1da5d24c9ab74534c376784f96ea
F test/wal4.test 6a68c45bc1ca24a3592ec449ddcb92b29d0e0e87
F test/wal5.test 1bbfaa316dc2a1d0d1fac3f4500c38a90055a41b
F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8
F test/wal7.test 09bc8de3d11949571d6f7a4188b308059cec27e5
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4
F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
F test/walcksum.test a37b36375c595e61bdb7e1ec49b5f0979b6fc7ce
F test/walcrash.test e763841551d6b23677ccb419797c1589dcbdbaf5
F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142
F test/walfault.test 58fce626359c9376fe35101b5c0f2df8040aa839
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test 22ddccd073c817ac9ead62b88ac446e8dedc7d2c
F test/walbak.test 767e1c9e0ea0cfb907873b332883e66e187fa4bc
F test/walbig.test 78ac493db2abdb65b9c6cace5b851cc32df1d449
F test/walcksum.test cf6787f2ee1a6a3da6f0c2b20b9ede5153e4e03f
F test/walcrash.test 80c1cc3173a0ef09d8303fa556cb0187a36d82ea
F test/walcrash2.test 929c99d14ee2e3e3ef82585058968a8b12f72706
F test/walfault.test 7db81f3dac64ce8897196f199c2909078bcabf8d
F test/walhook.test c934ac5219fee2b4e7653d291db9107b8dc73bba
F test/walmode.test feb39956ec6f415fbb9dcb12d91243391c2c4715
F test/walnoshm.test a074428046408f4eb5c6a00e09df8cc97ff93317
F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
F test/walro.test 1f15853383a976ff8bbec78dd44bc15c4e237392
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test 989854bc5c214700a9f2d545bb158643813b8881
F test/walthread.test e6e32e93ccebfa401dfc0dd930c79daa3472b0ae
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
F test/where3.test 8e1175c7ef710c70502858fc4fb08d784b3620b9
@@ -913,7 +919,7 @@ F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c.tcl 623e26cc8c83322e4151d3ad85ac69d41221bae8
F tool/mksqlite3c.tcl 98afd75c54489dd27b505fca45e3cc6943cb2409
F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl b1dd290c1596e0f31fd335160a74ec5dfea3df4a
@@ -938,7 +944,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P de58cb28387f44c35b1a81bdab853cafd938c1a6
R e623b89a5e0b9474dd0884ecf24382fc
P 97b980107676b2ea45a07c9c1a7de2e1ca74881f 8d1a6bb002a7817fa7df932f7cab7220c1d62c0e
R 55067a82132bcf8831d179c443db5e2f
U drh
Z 83669a82fd950b01af57955dbca1c918
Z 198f0d0d11e8401dbdcd4eff7ec30af8
+1 -1
View File
@@ -1 +1 @@
67bf1c9a888b0d84d252d6c4c754c2c51994d208
5791232778c825ec487a06c72b638dcb247cdd58
+4 -2
View File
@@ -76,6 +76,8 @@ static void attachFunc(
Db *aNew;
char *zErrDyn = 0;
sqlite3_vfs *pVfs;
const char *zVfs = db->pVfs->zName; /* Name of default (main) VFS */
int btflags = 0;
UNUSED_PARAMETER(NotUsed);
@@ -129,7 +131,7 @@ static void attachFunc(
** or may not be initialised.
*/
flags = db->openFlags;
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
rc = sqlite3ParseUri(zVfs, zFile, &flags, &btflags, &pVfs, &zPath, &zErr);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
sqlite3_result_error(context, zErr, -1);
@@ -138,7 +140,7 @@ static void attachFunc(
}
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, btflags, flags);
sqlite3_free( zPath );
db->nDb++;
if( rc==SQLITE_CONSTRAINT ){
+1
View File
@@ -61,6 +61,7 @@ int sqlite3BtreeOpen(
#define BTREE_MEMORY 4 /* This is an in-memory DB */
#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
#define BTREE_READONLYSHM 32 /* Read-only SHM access is acceptable */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
+3
View File
@@ -207,6 +207,9 @@ static void substrFunc(
}
}
}
#ifdef SQLITE_SUBSTR_COMPATIBILITY
if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */
#endif
if( argc==3 ){
p2 = sqlite3_value_int(argv[2]);
if( p2<0 ){
+9 -1
View File
@@ -16,6 +16,9 @@
*/
#include "sqliteInt.h"
#ifdef SQLITE_ENABLE_SQLRR
# include "sqlrr.h"
#endif
/*
** Execute SQL code. Return one of the SQLITE_ success/failure
@@ -43,7 +46,9 @@ int sqlite3_exec(
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
if( zSql==0 ) zSql = "";
#ifdef SQLITE_ENABLE_SQLRR
SRRecExec(db, zSql);
#endif
sqlite3_mutex_enter(db->mutex);
sqlite3Error(db, SQLITE_OK, 0);
while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
@@ -124,6 +129,9 @@ int sqlite3_exec(
exec_out:
if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
sqlite3DbFree(db, azCols);
#ifdef SQLITE_ENABLE_SQLRR
SRRecExecEnd(db);
#endif
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
+41 -2
View File
@@ -16,6 +16,9 @@
*/
#include "sqliteInt.h"
#ifdef SQLITE_ENABLE_SQLRR
# include "sqlrr.h"
#endif
#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
@@ -801,6 +804,10 @@ int sqlite3_close(sqlite3 *db){
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
#ifdef SQLITE_ENABLE_SQLRR
SRRecClose(db);
#endif
sqlite3_free(db);
return SQLITE_OK;
}
@@ -1789,6 +1796,12 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
}
return oldLimit; /* IMP: R-53341-35419 */
}
#if defined(SQLITE_ENABLE_AUTO_PROFILE)
static void profile_sql(void *aux, const char *sql, u64 ns) {
#pragma unused(aux)
fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
}
#endif
/*
** This function is used to parse both URIs and non-URI filenames passed by the
@@ -1803,6 +1816,11 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
** *pFlags may be updated before returning if the URI filename contains
** "cache=xxx" or "mode=xxx" query parameters.
**
** The third argument, pBtflags, points to an integer containing the flags
** that will be passed as the 5th argument to sqlite3BtreeOpen (BTREE_XXX
** flags). This value will be edited if the URI filename contains a
** "readonly_shm=1" or "readonly_shm=0" query parameter.
**
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
** the VFS that should be used to open the database file. *pzFile is set to
** point to a buffer containing the name of the file to open. It is the
@@ -1818,6 +1836,7 @@ int sqlite3ParseUri(
const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
const char *zUri, /* Nul-terminated URI to parse */
unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
int *pBtflags, /* IN/OUT: BTREE_XXX flags */
sqlite3_vfs **ppVfs, /* OUT: VFS to use */
char **pzFile, /* OUT: Filename component of URI */
char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
@@ -1933,6 +1952,12 @@ int sqlite3ParseUri(
if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
zVfs = zVal;
}else if( nOpt==12 && memcmp("readonly_shm", zOpt, 12)==0 ){
if( sqlite3Atoi(zVal) ){
*pBtflags |= BTREE_READONLYSHM;
}else{
*pBtflags &= ~BTREE_READONLYSHM;
}
}else{
struct OpenMode {
const char *z;
@@ -2036,6 +2061,7 @@ static int openDatabase(
int isThreadsafe; /* True for threadsafe connections */
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
int btflags = 0; /* Mask of BTREE_XXX flags */
*ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
@@ -2164,7 +2190,8 @@ static int openDatabase(
/* Parse the filename/URI argument. */
db->openFlags = flags;
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
rc = sqlite3ParseUri(
zVfs, zFilename, &flags, &btflags, &db->pVfs, &zOpen, &zErrMsg);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
@@ -2173,7 +2200,7 @@ static int openDatabase(
}
/* Open the backend database driver */
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, btflags,
flags | SQLITE_OPEN_MAIN_DB);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_IOERR_NOMEM ){
@@ -2278,7 +2305,19 @@ opendb_out:
}else if( rc!=SQLITE_OK ){
db->magic = SQLITE_MAGIC_SICK;
}
#if defined(SQLITE_ENABLE_AUTO_PROFILE)
if( db && !rc ){
char *envprofile = getenv("SQLITE_AUTO_PROFILE");
if( envprofile!=NULL ){
sqlite3_profile(db, profile_sql, NULL);
}
}
#endif
*ppDb = db;
#ifdef SQLITE_ENABLE_SQLRR
SRRecOpen(db, zFilename, flags);
#endif
return sqlite3ApiExit(0, rc);
}
+71 -3
View File
@@ -26,6 +26,28 @@
*/
#ifdef SQLITE_SYSTEM_MALLOC
#if (!defined(__APPLE__))
#define SQLITE_MALLOC(x) malloc(x)
#define SQLITE_FREE(x) free(x)
#define SQLITE_REALLOC(x,y) realloc((x),(y))
#else
#include <sys/sysctl.h>
#include <malloc/malloc.h>
#include <libkern/OSAtomic.h>
static malloc_zone_t* _sqliteZone_;
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
#endif
/*
** Like malloc(), but remember the size of the allocation
** so that we can find it later using sqlite3MemSize().
@@ -38,7 +60,7 @@ static void *sqlite3MemMalloc(int nByte){
sqlite3_int64 *p;
assert( nByte>0 );
nByte = ROUND8(nByte);
p = malloc( nByte+8 );
p = SQLITE_MALLOC( nByte+8 );
if( p ){
p[0] = nByte;
p++;
@@ -61,7 +83,7 @@ static void sqlite3MemFree(void *pPrior){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 );
p--;
free(p);
SQLITE_FREE(p);
}
/*
@@ -91,7 +113,7 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
assert( pPrior!=0 && nByte>0 );
assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
p--;
p = realloc(p, nByte+8 );
p = SQLITE_REALLOC(p, nByte+8 );
if( p ){
p[0] = nByte;
p++;
@@ -115,6 +137,37 @@ static int sqlite3MemRoundup(int n){
** Initialize this module.
*/
static int sqlite3MemInit(void *NotUsed){
#if defined(__APPLE__)
if (_sqliteZone_) {
return SQLITE_OK;
}
int cpuCount;
size_t len;
len = sizeof(cpuCount);
sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0); // one almost always wants to use "hw.activecpu" for MT decisions, but not here.
if (cpuCount > 1) {
// defer MT decisions to system malloc
_sqliteZone_ = malloc_default_zone();
} else {
// only 1 core, use our own zone to contention over global locks,
// e.g. we have our own dedicated locks
malloc_zone_t* newzone = malloc_create_zone(4096, 0);
malloc_set_zone_name(newzone, "Sqlite_Heap");
bool success;
do {
success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, (void * volatile *)&_sqliteZone_);
} while (!_sqliteZone_);
if (!success) {
// somebody registered a zone first
malloc_destroy_zone(newzone);
}
}
#endif
UNUSED_PARAMETER(NotUsed);
return SQLITE_OK;
}
@@ -123,6 +176,17 @@ static int sqlite3MemInit(void *NotUsed){
** Deinitialize this module.
*/
static void sqlite3MemShutdown(void *NotUsed){
#if (0 && defined(__APPLE__))
if (_sqliteZone_ && (_sqliteZone_ != malloc_default_zone())) {
malloc_zone_t* oldzone = _sqliteZone_;
bool success = OSAtomicCompareAndSwapPtrBarrier(oldzone, NULL, (void * volatile *)&_sqliteZone_);
if (success) {
malloc_destroy_zone(oldzone);
}
}
#endif
UNUSED_PARAMETER(NotUsed);
return;
}
@@ -147,4 +211,8 @@ void sqlite3MemSetDefault(void){
sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
}
#undef SQLITE_MALLOC
#undef SQLITE_FREE
#undef SQLITE_REALLOC
#endif /* SQLITE_SYSTEM_MALLOC */
+336 -22
View File
@@ -212,6 +212,7 @@ struct unixFile {
UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int readOnlyShm; /* True to open shared-memory read-only */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
@@ -3144,6 +3145,12 @@ int sqlite3_fullsync_count = 0;
# define HAVE_FULLFSYNC 0
#endif
#ifdef SQLITE_USE_REQUEST_FULLFSYNC
#import <notify.h>
#import <libkern/OSAtomic.h>
static OSSpinLock notify_lock = 0;
#define REQUEST_FULLSYNC_NOTIFICATION "com.apple.reqsync"
#endif
/*
** The fsync() system call does not work as advertised on many
@@ -3203,7 +3210,16 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
rc = SQLITE_OK;
#elif HAVE_FULLFSYNC
if( fullSync ){
#ifdef SQLITE_USE_REQUEST_FULLFSYNC
rc = osFsync(fd);
if (!rc) {
OSSpinLockLock(&notify_lock);
rc = notify_post(REQUEST_FULLSYNC_NOTIFICATION);
OSSpinLockUnlock(&notify_lock);
}
#else
rc = osFcntl(fd, F_FULLFSYNC, 0);
#endif
}else{
rc = 1;
}
@@ -3432,6 +3448,12 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
return SQLITE_OK;
}
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
#include "sqlite3_private.h"
#include <copyfile.h>
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath);
#endif
/*
** Information and control of an open file handle.
*/
@@ -3452,6 +3474,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
case SQLITE_FCNTL_SIZE_HINT: {
return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
}
case SQLITE_FCNTL_READONLY_SHM: {
((unixFile*)id)->readOnlyShm = (pArg!=0);
return SQLITE_OK;
}
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -3469,6 +3495,219 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
case SQLITE_TRUNCATE_DATABASE: {
unixFile *pFile = (unixFile*)id;
int trc = SQLITE_OK;
int eFileLock = pFile->eFileLock;
int rc = SQLITE_OK;
char jPath[MAXPATHLEN+9];
size_t jLen;
if( eFileLock<SQLITE_LOCK_SHARED ){
rc = pFile->pMethod->xLock(id, SQLITE_LOCK_SHARED);
}
if( !rc && eFileLock<SQLITE_LOCK_EXCLUSIVE ){
rc = pFile->pMethod->xLock(id, SQLITE_LOCK_EXCLUSIVE);
}
if( rc ){
if( pFile->eFileLock > eFileLock ){
pFile->pMethod->xUnlock(id, eFileLock);
}
return rc;
}
rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
if( !rc && (SQLITE_OK==getDbPathForUnixFile(pFile, jPath)) ){
jLen = strlcat(jPath, "-journal", MAXPATHLEN+9);
if( jLen < MAXPATHLEN+9 ){
int jfd = open(jPath, O_TRUNC);
if( (jfd == -1) ){
if ( errno!=ENOENT ){
perror(jPath);
}
} else {
fsync(jfd);
close(jfd);
}
}
}else{
trc=rc;
}
if( !trc ){
trc = pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
}
if( pFile->eFileLock > eFileLock ){
int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_SHARED);
if (!rc) rc = unlockRC;
}
if( pFile->eFileLock > eFileLock ){
int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_NONE);
if (!rc) rc = unlockRC;
}
if( trc ){
return trc;
}
return rc;
}
case SQLITE_REPLACE_DATABASE: {
unixFile *pFile = (unixFile*)id;
int trc = SQLITE_OK;
int eFileLock = pFile->eFileLock;
int rc = SQLITE_OK;
char jPath[MAXPATHLEN+9];
size_t jLen;
sqlite3 *srcdb = (sqlite3 *)pArg;
Btree *pSrcBtree = NULL;
int eSrcFileLock = SQLITE_LOCK_NONE;
int srcLockRC = -1;
sqlite3_file *src_file = NULL;
unixFile *pSrcFile = NULL;
if( !sqlite3SafetyCheckOk(srcdb) ){
return SQLITE_MISUSE;
}
if( eFileLock<SQLITE_LOCK_SHARED ){
rc = pFile->pMethod->xLock(id, SQLITE_LOCK_SHARED);
}
if( !rc && eFileLock<SQLITE_LOCK_EXCLUSIVE ){
rc = pFile->pMethod->xLock(id, SQLITE_LOCK_EXCLUSIVE);
}
if( !rc ){
/* get the src file descriptor adhering to the db struct access rules
** this code is modeled after sqlite3_file_control() in main.c
*/
sqlite3_mutex_enter(srcdb->mutex);
if( srcdb->nDb>0 ){
pSrcBtree = srcdb->aDb[0].pBt;
}
if( pSrcBtree ){
Pager *pSrcPager;
sqlite3BtreeEnter(pSrcBtree);
pSrcPager = sqlite3BtreePager(pSrcBtree);
assert( pSrcPager!=0 );
src_file = sqlite3PagerFile(pSrcPager);
assert( src_file!=0 );
if( src_file->pMethods ){
pSrcFile = (unixFile *)src_file;
eSrcFileLock = pSrcFile->eFileLock;
if( eSrcFileLock<SQLITE_LOCK_SHARED ){
rc = pSrcFile->pMethod->xLock(src_file, SQLITE_LOCK_SHARED);
srcLockRC = rc; /* SQLITE_OK means we need to unlock later */
} else if( eSrcFileLock==SQLITE_LOCK_EXCLUSIVE ){
/* if the src database has an exclusive lock, verify that the
** it doesn't have a journal file with open transactions
*/
if( getDbPathForUnixFile(pSrcFile, jPath) ){
rc = SQLITE_INTERNAL;
}else{
jLen = strlcat(jPath, "-journal", MAXPATHLEN+9);
if( jLen < MAXPATHLEN+9 ){
int jfd = open(jPath, O_RDONLY);
if( jfd==-1 ){
if( errno!=ENOENT ){
pFile->lastErrno = errno;
rc = SQLITE_IOERR;
}
}else{
/* if the journal exists ensure there's no pending
** transaction by checking the journal header */
char magic[8];
ssize_t rlen = pread(jfd, magic, 8, 0);
if( rlen<0 ){
pFile->lastErrno = errno;
rc = SQLITE_IOERR;
}else if( rlen==8 ){
char test[8] = {'\0','\0','\0','\0','\0','\0','\0','\0'};
if( memcmp(magic,test,8) ){
rc = SQLITE_LOCKED;
}
}else if( rlen!=0 ){
rc = SQLITE_INTERNAL;
}
close(jfd);
}
}
}
}
}else{
rc = SQLITE_MISUSE;
}
if( rc ){
if( srcLockRC==SQLITE_OK ){
pSrcFile->pMethod->xUnlock(src_file, eSrcFileLock);
}
sqlite3BtreeLeave(pSrcBtree);
}
}
if( pSrcFile==NULL || (pSrcFile->h<0) ){
rc = SQLITE_INTERNAL;
sqlite3_mutex_leave(srcdb->mutex);
}
}
if( rc ){
/* unroll state changes and return error code */
if( pFile->eFileLock > eFileLock ){
pFile->pMethod->xUnlock(id, eFileLock);
}
return rc;
}else{
/* both databases are locked appropriately, copy file data
** and then unroll the locks we added.
*/
copyfile_state_t s;
s = copyfile_state_alloc();
if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
switch(errno) {
case ENOMEM:
rc = SQLITE_NOMEM;
break;
default:
rc = SQLITE_INTERNAL;
}
}
copyfile_state_free(s);
if( srcLockRC==SQLITE_OK ){
pSrcFile->pMethod->xUnlock(src_file, eSrcFileLock);
}
sqlite3BtreeLeave(pSrcBtree);
sqlite3_mutex_leave(srcdb->mutex);
}
if( !rc && (SQLITE_OK==getDbPathForUnixFile(pFile, jPath)) ){
jLen = strlcat(jPath, "-journal", MAXPATHLEN+9);
if( jLen < MAXPATHLEN+9 ){
int jfd = open(jPath, O_TRUNC);
if( (jfd == -1) ){
if ( errno!=ENOENT ){
perror(jPath);
}
} else {
fsync(jfd);
close(jfd);
}
}
}else{
trc=rc;
}
if( !trc ){
trc = pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
}
if( pFile->eFileLock > eFileLock ){
int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_SHARED);
if (!rc) rc = unlockRC;
}
if( pFile->eFileLock > eFileLock ){
int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_NONE);
if (!rc) rc = unlockRC;
}
if( trc ){
return trc;
}
return rc;
}
#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
case SQLITE_FCNTL_SYNC_OMITTED: {
return SQLITE_OK; /* A no-op */
}
@@ -3541,6 +3780,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
u8 readOnly; /* True if this is a read-only mapping */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -3683,6 +3923,9 @@ static void unixShmPurge(unixFile *pFd){
}
}
static int isProxyLockingMode(unixFile *);
static const char *proxySharedMemoryBasePath(unixFile *);
/*
** Open a shared-memory area associated with open database file pDbFd.
** This particular implementation uses mmapped files.
@@ -3751,10 +3994,24 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
goto shm_open_err;
}
const char *zBasePath = pDbFd->zPath;
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/* If pDbFd is configured with proxy locking mode, use the local
** lock file path to determine the -shm file path
*/
if( isProxyLockingMode(pDbFd) ){
zBasePath = proxySharedMemoryBasePath(pDbFd);
if( !zBasePath ){
rc = SQLITE_CANTOPEN_BKPT;
goto shm_open_err;
}
}
#endif
#ifdef SQLITE_SHM_DIRECTORY
nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 30;
#else
nShmFilename = 5 + (int)strlen(pDbFd->zPath);
nShmFilename = 5 + (int)strlen(zBasePath);
#endif
pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
if( pShmNode==0 ){
@@ -3768,7 +4025,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
(u32)sStat.st_ino, (u32)sStat.st_dev);
#else
sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath);
sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
#endif
pShmNode->h = -1;
@@ -3781,29 +4038,48 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
}
if( pInode->bProcessLock==0 ){
pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
(sStat.st_mode & 0777));
int flags = (pDbFd->readOnlyShm ? O_RDONLY : O_RDWR|O_CREAT);
pShmNode->h = robust_open(zShmFilename, flags, (sStat.st_mode & 0777));
if( pShmNode->h<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
goto shm_open_err;
}
pShmNode->readOnly = pDbFd->readOnlyShm;
/* Check to see if another process is holding the dead-man switch.
** If not, truncate the file to zero length.
*/
rc = SQLITE_OK;
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( robust_ftruncate(pShmNode->h, 0) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
** If not, zero the first few bytes of the shared-memory file to make
** sure it is not mistaken for valid by code in wal.c. Except, if this
** is a read-only connection to the shared-memory then it is not possible
** to check check if another process is holding a read-lock on the DMS
** byte, as we cannot attempt a write-lock via a read-only file
** descriptor. So in this case, we just assume the shared-memory
** contents are Ok and proceed. */
if( pShmNode->readOnly==0 ){
rc = SQLITE_OK;
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( pDbFd->readOnlyShm ){
rc = SQLITE_IOERR_SHMOPEN;
}else if( 4!=osWrite(pShmNode->h, "\00\00\00\00", 4) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
}
}
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
}
/* If the unixShmNode is read-only, but SQLITE_FCNTL_READONLY_SHM has not
** been set for file-descriptor pDbFd, return an error. The wal.c module
** will then call this function again with SQLITE_FCNTL_READONLY_SHM set.
*/
else if( pShmNode->readOnly && !pDbFd->readOnlyShm ){
rc = SQLITE_IOERR_SHMOPEN;
goto shm_open_err;
}
/* Make the new connection a child of the unixShmNode */
p->pShmNode = pShmNode;
#ifdef SQLITE_DEBUG
@@ -3924,7 +4200,7 @@ static int unixShmMap(
while(pShmNode->nRegion<=iRegion){
void *pMem;
if( pShmNode->h>=0 ){
pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
pMem = mmap(0, szRegion, PROT_READ|(!pShmNode->readOnly?PROT_WRITE:0),
MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
);
if( pMem==MAP_FAILED ){
@@ -4292,7 +4568,7 @@ static int proxyCheckReservedLock(sqlite3_file*, int*);
IOMETHODS(
proxyIoFinder, /* Finder function name */
proxyIoMethods, /* sqlite3_io_methods object name */
1, /* shared memory is disabled */
2, /* shared memory is enabled */
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
@@ -5050,6 +5326,9 @@ static int unixOpen(
if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
}
if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
}
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
@@ -5088,13 +5367,19 @@ static int unixOpen(
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
isDelete, isReadonly);
if( rc==SQLITE_OK ){
/* cache the pMethod in case the transform fails */
const struct sqlite3_io_methods *pMethod = pFile->pMethods;
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
if( rc!=SQLITE_OK ){
/* Use unixClose to clean up the resources added in fillInUnixFile
** and clear all the structure's references. Specifically,
** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
*/
unixClose(pFile);
if( pMethod!=NULL ){
pMethod->xClose(pFile);
}else{
unixClose(pFile);
}
return rc;
}
}
@@ -5690,6 +5975,28 @@ static int proxyCreateLockPath(const char *lockPath){
return 0;
}
static int isProxyLockingMode(unixFile *pFile) {
return (pFile->pMethod == &proxyIoMethods) ? 1 : 0;
}
/*
** Return the shared memory base path based on the lock proxy file if the
** lock proxy file is hosted on a shared memory compatible FS
*/
static const char *proxySharedMemoryBasePath(unixFile *pFile) {
proxyLockingContext *pCtx;
unixFile *pLockFile;
assert(pFile!=NULL && pFile->lockingContext!=NULL);
assert(pFile->pMethod == &proxyIoMethods);
pCtx = ((proxyLockingContext *)(pFile->lockingContext));
pLockFile = pCtx->lockProxy;
if( pLockFile->pMethod->iVersion>=2 && pLockFile->pMethod->xShmMap!=0 ){
return pCtx->lockProxyPath;
}
return NULL;
}
/*
** Create a new VFS file descriptor (stored in memory obtained from
** sqlite3_malloc) and open the file named "path" in the file descriptor.
@@ -5741,6 +6048,7 @@ static int proxyCreateUnixFile(
terrno = errno;
}
if( fd<0 ){
sqlite3_free(pUnused);
if( islockfile ){
return SQLITE_BUSY;
}
@@ -6293,7 +6601,7 @@ static int switchLockProxyPath(unixFile *pFile, const char *path) {
** This routine find the filename associated with pFile and writes it
** int dbPath.
*/
static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__APPLE__)
if( pFile->pMethod == &afpIoMethods ){
/* afp style keeps a reference to the db path in the filePath field
@@ -6332,7 +6640,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
if( pFile->eFileLock!=NO_LOCK ){
return SQLITE_BUSY;
}
proxyGetDbPathForUnixFile(pFile, dbPath);
getDbPathForUnixFile(pFile, dbPath);
if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
lockPath=NULL;
}else{
@@ -6375,6 +6683,9 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
}
if( rc==SQLITE_OK && lockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
if( pCtx->lockProxyPath==NULL ){
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
@@ -6414,7 +6725,7 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
switch( op ){
case SQLITE_GET_LOCKPROXYFILE: {
unixFile *pFile = (unixFile*)id;
if( pFile->pMethod == &proxyIoMethods ){
if( isProxyLockingMode(pFile) ){
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
proxyTakeConch(pFile);
if( pCtx->lockProxyPath ){
@@ -6430,10 +6741,13 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
case SQLITE_SET_LOCKPROXYFILE: {
unixFile *pFile = (unixFile*)id;
int rc = SQLITE_OK;
int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
int isProxyStyle = isProxyLockingMode(pFile);
if( pArg==NULL || (const char *)pArg==0 ){
if( isProxyStyle ){
/* turn off proxy locking - not supported */
/* turn off proxy locking - not supported. If support is added for
** switching proxy locking mode off then it will need to fail if
** the journal mode is WAL mode.
*/
rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
}else{
/* turn off proxy locking - already off - NOOP */
+5 -2
View File
@@ -620,6 +620,7 @@ struct Pager {
u8 tempFile; /* zFilename is a temporary file */
u8 readOnly; /* True for a read-only database */
u8 memDb; /* True to inhibit all file I/O */
u8 readOnlyShm; /* True if read-only shm access is Ok */
/**************************************************************************
** The following block contains those class members that change during
@@ -3017,6 +3018,7 @@ static int pagerWalFrames(
static int pagerBeginReadTransaction(Pager *pPager){
int rc; /* Return code */
int changed = 0; /* True if cache must be reset */
Wal *pWal = pPager->pWal;
assert( pagerUseWal(pPager) );
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
@@ -3026,9 +3028,9 @@ static int pagerBeginReadTransaction(Pager *pPager){
** are in locking_mode=NORMAL and EndRead() was previously called,
** the duplicate call is harmless.
*/
sqlite3WalEndReadTransaction(pPager->pWal);
sqlite3WalEndReadTransaction(pWal);
rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
rc = sqlite3WalBeginReadTransaction(pWal, pPager->readOnlyShm, &changed);
if( rc!=SQLITE_OK || changed ){
pager_reset(pPager);
}
@@ -4416,6 +4418,7 @@ int sqlite3PagerOpen(
}
pPager->pVfs = pVfs;
pPager->vfsFlags = vfsFlags;
pPager->readOnlyShm = (flags & PAGER_READONLYSHM)!=0;
/* Open the pager file.
*/
+1
View File
@@ -60,6 +60,7 @@ typedef struct PgHdr DbPage;
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
#define PAGER_MEMORY 0x0004 /* In-memory database */
#define PAGER_READONLYSHM 0x0020 /* Read-only SHM access is acceptable */
/*
** Valid values for the second argument to sqlite3PagerLockingMode().
+23 -17
View File
@@ -142,12 +142,12 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
/*
** Generate code to return a single integer value.
*/
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 *pValue){
Vdbe *v = sqlite3GetVdbe(pParse);
int mem = ++pParse->nMem;
i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(*pValue));
if( pI64 ){
memcpy(pI64, &value, sizeof(value));
memcpy(pI64, pValue, sizeof(*pValue));
}
sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
sqlite3VdbeSetNumCols(v, 1);
@@ -210,7 +210,8 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
assert( v!=0 ); /* Already allocated by sqlite3Pragma() */
if( ALWAYS(v) ){
if( zRight==0 ){
returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
i64 value = ((db->flags & p->mask)!=0 ? 1 : 0);
returnSingleInt(pParse, p->zName, &value);
}else{
int mask = p->mask; /* Mask of bits to set or clear. */
if( db->autoCommit==0 ){
@@ -407,8 +408,8 @@ void sqlite3Pragma(
Btree *pBt = pDb->pBt;
assert( pBt!=0 );
if( !zRight ){
int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
returnSingleInt(pParse, "page_size", size);
i64 size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
returnSingleInt(pParse, "page_size", &size);
}else{
/* Malloc may fail when setting the page-size, as there is an internal
** buffer that the pager module resizes using sqlite3_realloc().
@@ -430,7 +431,7 @@ void sqlite3Pragma(
*/
if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
Btree *pBt = pDb->pBt;
int b = -1;
sqlite3_int64 b = -1;
assert( pBt!=0 );
if( zRight ){
b = sqlite3GetBoolean(zRight);
@@ -442,7 +443,7 @@ void sqlite3Pragma(
}
}
b = sqlite3BtreeSecureDelete(pBt, b);
returnSingleInt(pParse, "secure_delete", b);
returnSingleInt(pParse, "secure_delete", &b);
}else
/*
@@ -584,7 +585,7 @@ void sqlite3Pragma(
if( iLimit<-1 ) iLimit = -1;
}
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
returnSingleInt(pParse, "journal_size_limit", iLimit);
returnSingleInt(pParse, "journal_size_limit", &iLimit);
}else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
@@ -604,13 +605,13 @@ void sqlite3Pragma(
goto pragma_out;
}
if( !zRight ){
int auto_vacuum;
i64 auto_vacuum;
if( ALWAYS(pBt) ){
auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
}else{
auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
}
returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
returnSingleInt(pParse, "auto_vacuum", &auto_vacuum);
}else{
int eAuto = getAutoVacuum(zRight);
assert( eAuto>=0 && eAuto<=2 );
@@ -693,7 +694,8 @@ void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
i64 cacheSize = pDb->pSchema->cache_size;
returnSingleInt(pParse, "cache_size", &cacheSize);
}else{
int size = sqlite3AbsInt32(sqlite3Atoi(zRight));
pDb->pSchema->cache_size = size;
@@ -714,7 +716,8 @@ void sqlite3Pragma(
*/
if( sqlite3StrICmp(zLeft, "temp_store")==0 ){
if( !zRight ){
returnSingleInt(pParse, "temp_store", db->temp_store);
i64 tempStore = db->temp_store;
returnSingleInt(pParse, "temp_store", &tempStore);
}else{
changeTempStorage(pParse, zRight);
}
@@ -828,7 +831,8 @@ void sqlite3Pragma(
if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
if( !zRight ){
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
i64 safetyLevel = pDb->safety_level-1;
returnSingleInt(pParse, "synchronous", &safetyLevel);
}else{
if( !db->autoCommit ){
sqlite3ErrorMsg(pParse,
@@ -1421,12 +1425,14 @@ void sqlite3Pragma(
** of N.
*/
if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
i64 walArg = 0;
if( zRight ){
sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
}
returnSingleInt(pParse, "wal_autocheckpoint",
db->xWalCallback==sqlite3WalDefaultHook ?
SQLITE_PTR_TO_INT(db->pWalArg) : 0);
if( db->xWalCallback==sqlite3WalDefaultHook ){
walArg = SQLITE_PTR_TO_INT(db->pWalArg);
}
returnSingleInt(pParse, "wal_autocheckpoint", &walArg);
}else
#endif
+12 -1
View File
@@ -14,6 +14,9 @@
** from disk.
*/
#include "sqliteInt.h"
#ifdef SQLITE_ENABLE_SQLRR
# include "sqlrr.h"
#endif
/*
** Fill the InitData structure with an error message that indicates
@@ -759,6 +762,9 @@ int sqlite3_prepare(
){
int rc;
rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail);
#ifdef SQLITE_ENABLE_SQLRR
SRRecPrepare(db, zSql, nBytes, 0, *ppStmt);
#endif
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
@@ -771,6 +777,9 @@ int sqlite3_prepare_v2(
){
int rc;
rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail);
#ifdef SQLITE_ENABLE_SQLRR
SRRecPrepare(db, zSql, nBytes, 1, *ppStmt);
#endif
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
@@ -806,7 +815,9 @@ static int sqlite3Prepare16(
if( zSql8 ){
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
}
#ifdef SQLITE_ENABLE_SQLRR
SRRecPrepare(db, zSql8, -1, 1, *ppStmt);
#endif
if( zTail8 && pzTail ){
/* If sqlite3_prepare returns a tail pointer, we calculate the
** equivalent pointer into the UTF-16 string by counting the unicode
+42 -1
View File
@@ -455,6 +455,9 @@ int sqlite3_exec(
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
/*
** CAPI3REF: Flags For File Open Operations
**
@@ -734,6 +737,27 @@ struct sqlite3_io_methods {
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.
**
** The [SQLITE_FCNTL_READONLY_SHM] may be generated internally by SQLite if
** the "readonly_shm=1" URI option is specified when the database is opened.
** The fourth argument passed to the VFS xFileControl methods is a pointer
** to a variable of type "int" containing the value 1 or 0. If the variable
** contains the value 1, then this indicates to the VFS that a read-only
** mapping of the shared-memory region is acceptable. If it is set to 0, then
** this indicates that a read-write mapping is required (as normal). If
** a read-only mapping is returned, then the VFS may also return read-only
** mappings for any subsequent requests via the same file-descriptor -
** regardless of the value most recently configured using
** SQLITE_FCNTL_READONLY_SHM.
**
** In practice, if "readonly_shm=1" is specified and the first attempt to
** map a shared-memory region fails, then this file-control is invoked with
** the argument variable set to 1 and a second attempt to map the shared-memory
** region is made. If this mapping succeeds, then the connection continues
** with the read-only mapping. Otherwise, if it fails, SQLITE_CANTOPEN is
** returned to the caller. Whether or not the second (read-only) mapping
** attempt succeeds, the file-control is invoked again with the argument
** variable set to 0.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2
@@ -743,6 +767,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7
#define SQLITE_FCNTL_SYNC_OMITTED 8
#define SQLITE_FCNTL_READONLY_SHM 9
/*
@@ -2456,7 +2481,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** [[core URI query parameters]]
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [VFS | custom VFS implementation].
** SQLite interprets the following three query parameters:
** SQLite interprets the following four query parameters:
**
** <ul>
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
@@ -2488,6 +2513,22 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behaviour requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>readonly_shm</b>: ^The readonly_shm parameter may be set to
** either "1" or "0". Setting it to "1" indicates that if the database
** is in WAL mode and read-write access to the associated shared
** memory region cannot be obtained, then an attempt should be made to open
** the shared-memory in read-only mode instead. If there exist one or
** more other database clients that have read-write connections to the
** database shared-memory, then a read-only shared-memory connection works
** fine. However, if there exist no clients with read-write connections
** to the shared-memory and the most recent such crashed or was interrupted
** by a power failure, then it is possible for a database client using a
** read-only connection to return incorrect data, incorrectly report
** database corruption, or return an SQLITE_READONLY error. Or if the
** most recent read-write connection shut down cleanly, it may not be
** possible to open the shared-memory in read-only mode at all, and SQLite
** will return SQLITE_CANTOPEN.
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
+21
View File
@@ -0,0 +1,21 @@
/*
* sqlite3_private.h
*/
#ifndef _SQLITE3_PRIVATE_H
#define _SQLITE3_PRIVATE_H
/*
** Pass the SQLITE_TRUNCATE_DATABASE operation code to sqlite3_file_control()
** to truncate a database and its associated journal file to zero length.
*/
#define SQLITE_TRUNCATE_DATABASE 101
/*
** Pass the SQLITE_REPLACE_DATABASE operation code to sqlite3_file_control()
** and a sqlite3 pointer to another open database file to safely copy the
** contents of that database file into the receiving database.
*/
#define SQLITE_REPLACE_DATABASE 102
#endif
+1 -1
View File
@@ -2673,7 +2673,7 @@ void sqlite3AddColumnType(Parse*,Token*);
void sqlite3AddDefaultValue(Parse*,ExprSpan*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
int sqlite3ParseUri(const char*,const char*,unsigned int*,int*,
sqlite3_vfs**,char**,char **);
Bitvec *sqlite3BitvecCreate(u32);
+114 -1
View File
@@ -163,8 +163,9 @@ const char *sqlite3TestErrorName(int rc){
case SQLITE_IOERR_CHECKRESERVEDLOCK:
zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
default: zName = "SQLITE_Unknown"; break;
}
return zName;
@@ -3407,6 +3408,24 @@ static int test_clear_bindings(
return TCL_OK;
}
/*
** Usage: sqlite3_clear_bindings STMT
**
*/
static int test_clear_bindings_null(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
if( objc!=1 ){
return TCL_ERROR;
}
/* test for handling NULL <rdar://problem/6646331> */
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(0)));
return TCL_OK;
}
/*
** Usage: sqlite3_sleep MILLISECONDS
*/
@@ -5095,6 +5114,97 @@ static int file_control_lockproxy_test(
return TCL_OK;
}
#ifdef __APPLE__
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/errno.h>
#endif
/*
** tclcmd: path_is_local PWD
*/
static int path_is_local(
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;
const char *zPath;
int nPath;
if( objc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetStringFromObj(objv[0], 0), " PATH", 0);
return TCL_ERROR;
}
zPath = Tcl_GetStringFromObj(objv[1], &nPath);
#ifdef __APPLE__
{
struct statfs fsInfo;
if( statfs(zPath, &fsInfo) == -1 ){
int err = errno;
Tcl_AppendResult(interp, "Error calling statfs on path",
Tcl_NewIntObj(err), 0);
return TCL_ERROR;
}
if( fsInfo.f_flags&MNT_LOCAL ){
Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
} else {
Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
}
}
#else
Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
#endif
return TCL_OK;
}
/*
** tclcmd: path_is_dos PWD
*/
static int path_is_dos(
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;
const char *zPath;
int nPath;
if( objc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetStringFromObj(objv[0], 0), " PATH", 0);
return TCL_ERROR;
}
zPath = Tcl_GetStringFromObj(objv[1], &nPath);
#ifdef __APPLE__
{
struct statfs fsInfo;
if( statfs(zPath, &fsInfo) == -1 ){
int err = errno;
Tcl_AppendResult(interp, "Error calling statfs on path",
Tcl_NewIntObj(err), 0);
return TCL_ERROR;
}
if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
} else if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
} else {
Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
}
}
#else
Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
#endif
return TCL_OK;
}
/*
** tclcmd: sqlite3_vfs_list
@@ -5658,6 +5768,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
{ "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
{ "sqlite3_clear_bindings", test_clear_bindings, 0},
{ "sqlite3_clear_bindings_null", test_clear_bindings_null, 0},
{ "sqlite3_sleep", test_sleep, 0},
{ "sqlite3_errcode", test_errcode ,0 },
{ "sqlite3_extended_errcode", test_ex_errcode ,0 },
@@ -5750,6 +5861,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
{ "path_is_local", path_is_local, 0 },
{ "path_is_dos", path_is_dos, 0 },
/* Functions from os.h */
#ifndef SQLITE_OMIT_UTF16
+1 -1
View File
@@ -14,7 +14,7 @@
*/
#include "tcl.h"
#include <sqlite3.h>
#include "sqlite3.h"
#include <assert.h>
/* These functions are implemented in test1.c. */
+16
View File
@@ -552,6 +552,22 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
#else
Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef __APPLE__
# if defined(__ppc__)
Tcl_SetVar2(interp, "os_options", "arch", "ppc", TCL_GLOBAL_ONLY);
# elif defined(__i386__)
Tcl_SetVar2(interp, "os_options", "arch", "i386", TCL_GLOBAL_ONLY);
# elif defined(__x86_64__)
Tcl_SetVar2(interp, "os_options", "arch", "x86_64", TCL_GLOBAL_ONLY);
# elif defined(__arm__)
Tcl_SetVar2(interp, "os_options", "arch", "arm", TCL_GLOBAL_ONLY);
# else
# error Unrecognized architecture for exec_options
# endif
#else
Tcl_SetVar2(interp, "os_options", "arch", "unknown", TCL_GLOBAL_ONLY);
#endif
#define LINKVAR(x) { \
static const int cv_ ## x = SQLITE_ ## x; \
+1 -1
View File
@@ -578,7 +578,7 @@ int sqlite3VdbeExec(
** sqlite3_column_text16() failed. */
goto no_mem;
}
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || ((p->rc&0xFF) == SQLITE_LOCKED));
p->rc = SQLITE_OK;
assert( p->explain==0 );
p->pResultSet = 0;
+46 -2
View File
@@ -15,6 +15,9 @@
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#ifdef SQLITE_ENABLE_SQLRR
# include "sqlrr.h"
#endif
#ifndef SQLITE_OMIT_DEPRECATED
/*
@@ -37,7 +40,8 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
** invalid). Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
if( p->db==0 ){
sqlite3* db = p->db;
if((db==0) || (db->magic != SQLITE_MAGIC_OPEN) || ((p->magic != VDBE_MAGIC_RUN) && (p->magic != VDBE_MAGIC_HALT))){
sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
return 1;
}else{
@@ -70,6 +74,9 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
#ifdef SQLITE_ENABLE_SQLRR
SRRecFinalize(pStmt);
#endif
sqlite3 *db = v->db;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex;
@@ -100,6 +107,9 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
#ifdef SQLITE_ENABLE_SQLRR
SRRecReset(pStmt);
#endif
sqlite3_mutex_enter(v->db->mutex);
rc = sqlite3VdbeReset(v);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0);
@@ -118,7 +128,14 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
sqlite3_mutex *mutex=NULL;
#endif
if( NULL==pStmt ){ return SQLITE_OK; } /* <rdar://problem/6646331> */
#ifdef SQLITE_ENABLE_SQLRR
SRRecClearBindings(pStmt);
#endif
#if SQLITE_THREADSAFE
mutex = ((Vdbe*)pStmt)->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
for(i=0; i<p->nVar; i++){
@@ -1062,11 +1079,17 @@ int sqlite3_bind_blob(
int nData,
void (*xDel)(void*)
){
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindBlob(pStmt, i, zData, nData);
#endif
return bindText(pStmt, i, zData, nData, xDel, 0);
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindDouble(pStmt, i, rValue);
#endif
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
@@ -1075,11 +1098,17 @@ int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
return rc;
}
int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindInt64(p, i, (i64)iValue);
#endif
return sqlite3_bind_int64(p, i, (i64)iValue);
}
int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindInt64(pStmt, i, iValue);
#endif
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
@@ -1090,6 +1119,9 @@ int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
int rc;
Vdbe *p = (Vdbe*)pStmt;
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindNull(pStmt, i);
#endif
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3_mutex_leave(p->db->mutex);
@@ -1103,6 +1135,9 @@ int sqlite3_bind_text(
int nData,
void (*xDel)(void*)
){
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindText(pStmt, i, zData, nData);
#endif
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
@@ -1113,6 +1148,9 @@ int sqlite3_bind_text16(
int nData,
void (*xDel)(void*)
){
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindText(pStmt, i, zData, nData);
#endif
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
}
#endif /* SQLITE_OMIT_UTF16 */
@@ -1136,6 +1174,9 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
break;
}
case SQLITE_TEXT: {
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindText(pStmt, i, pValue->z, pValue->n);
#endif
rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT,
pValue->enc);
break;
@@ -1150,6 +1191,9 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
#ifdef SQLITE_ENABLE_SQLRR
SRRecBindBlob(pStmt, i, NULL, n);
#endif
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
+61 -18
View File
@@ -406,6 +406,14 @@ struct WalCkptInfo {
/*
** An open write-ahead log file is represented by an instance of the
** following object.
**
** The readOnlyShm variable is normally set to 0. If it is set to 1, then
** the connection to shared-memory is read-only. This means it cannot
** be written at all (even when read-locking the database). If it is set
** to 2, then the shared-memory region is not yet open, but a read-only
** connection is acceptable. In this case when the shared-memory is opened
** (see function walIndexPage()), readOnlyShm is set to either 0 or 1 as
** appropriate.
*/
struct Wal {
sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
@@ -421,6 +429,7 @@ struct Wal {
u8 writeLock; /* True if in a write transaction */
u8 ckptLock; /* True if holding a checkpoint lock */
u8 readOnly; /* True if the WAL file is open read-only */
u8 readOnlyShm; /* True if the SHM file is open read-only */
WalIndexHdr hdr; /* Wal-index header for current transaction */
const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
@@ -529,11 +538,23 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
if( rc==SQLITE_CANTOPEN && pWal->readOnlyShm>1 ){
assert( iPage==0 );
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)1);
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
if( rc==SQLITE_OK ){
pWal->readOnly = pWal->readOnlyShm = 1;
}
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)0);
}
}
}
*ppPage = pWal->apWiData[iPage];
assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
if( pWal->readOnlyShm>1 ) pWal->readOnlyShm = 0;
return rc;
}
@@ -773,6 +794,7 @@ static void walUnlockShared(Wal *pWal, int lockIdx){
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
int rc;
assert( pWal->readOnlyShm==0 );
if( pWal->exclusiveMode ) return SQLITE_OK;
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
@@ -782,6 +804,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
assert( pWal->readOnlyShm==0 );
if( pWal->exclusiveMode ) return;
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
@@ -1057,6 +1080,7 @@ static int walIndexRecover(Wal *pWal){
assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
assert( pWal->writeLock );
assert( pWal->readOnlyShm==0 );
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
nLock = SQLITE_SHM_NLOCK - iLock;
rc = walLockExclusive(pWal, iLock, nLock);
@@ -1905,6 +1929,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
return rc;
};
assert( page0 || pWal->writeLock==0 );
assert( pWal->readOnlyShm==0 || pWal->readOnlyShm==1 );
/* If the first page of the wal-index has been mapped, try to read the
** wal-index header immediately, without holding any lock. This usually
@@ -1914,24 +1939,31 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
/* If the first attempt failed, it might have been due to a race
** with a writer. So get a WRITE lock and try again.
** with a writer. So lock the WAL_WRITE_LOCK byte and try again.
*/
assert( badHdr==0 || pWal->writeLock==0 );
if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
*/
rc = walIndexRecover(pWal);
*pChanged = 1;
if( badHdr ){
if( pWal->readOnlyShm ){
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
}else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
*/
rc = walIndexRecover(pWal);
*pChanged = 1;
}
}
pWal->writeLock = 0;
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
}
pWal->writeLock = 0;
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
}
/* If the header is read successfully, check the version number to make
@@ -2118,7 +2150,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
/* There was once an "if" here. The extra "{" is to preserve indentation. */
{
if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
if( pWal->readOnlyShm==0 && (mxReadMark < pWal->hdr.mxFrame || mxI==0) ){
for(i=1; i<WAL_NREADER; i++){
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
@@ -2133,7 +2165,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
if( mxI==0 ){
assert( rc==SQLITE_BUSY );
return WAL_RETRY;
assert( rc==SQLITE_BUSY || (pWal->readOnlyShm && rc==SQLITE_OK) );
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
}
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
@@ -2188,13 +2221,18 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** Pager layer will use this to know that is cache is stale and
** needs to be flushed.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int sqlite3WalBeginReadTransaction(Wal *pWal, int readOnlyShm, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
if( pWal->nWiData==0 || pWal->apWiData[0]==0 ){
assert( readOnlyShm==0 || readOnlyShm==1 );
pWal->readOnlyShm = readOnlyShm*2;
}
do{
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
}while( rc==WAL_RETRY );
assert( rc || pWal->readOnlyShm==0 || (readOnlyShm && pWal->readOnlyShm==1) );
testcase( (rc&0xff)==SQLITE_BUSY );
testcase( (rc&0xff)==SQLITE_IOERR );
testcase( rc==SQLITE_PROTOCOL );
@@ -2369,6 +2407,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
if( pWal->readOnly ){
return SQLITE_READONLY;
}
assert( pWal->readOnlyShm==0 );
/* Only one writer allowed at a time. Get the write lock. Return
** SQLITE_BUSY if unable.
@@ -2774,6 +2813,10 @@ int sqlite3WalCheckpoint(
assert( pWal->writeLock==0 );
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
if( pWal->readOnlyShm ){
return SQLITE_READONLY;
}
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
if( rc ){
/* Usually this is SQLITE_BUSY meaning that another thread or process
+2 -2
View File
@@ -23,7 +23,7 @@
# define sqlite3WalOpen(x,y,z) 0
# define sqlite3WalLimit(x,y)
# define sqlite3WalClose(w,x,y,z) 0
# define sqlite3WalBeginReadTransaction(y,z) 0
# define sqlite3WalBeginReadTransaction(x,y,z) 0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalRead(v,w,x,y,z) 0
# define sqlite3WalDbsize(y) 0
@@ -60,7 +60,7 @@ void sqlite3WalLimit(Wal*, i64);
** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
int sqlite3WalBeginReadTransaction(Wal *pWal, int, int *);
void sqlite3WalEndReadTransaction(Wal *pWal);
/* Read a page from the write-ahead log, if it is present. */
+18 -17
View File
@@ -718,23 +718,24 @@ do_test attach-6.1 {
}
} {0 {}}
if {$tcl_platform(platform)=="unix"} {
do_test attach-6.2 {
sqlite3 dbx cannot-read
dbx eval {CREATE TABLE t1(a,b,c)}
dbx close
file attributes cannot-read -permission 0000
if {[file writable cannot-read]} {
puts "\n**** Tests do not work when run as root ****"
file delete -force cannot-read
exit 1
}
catchsql {
ATTACH DATABASE 'cannot-read' AS noread;
}
} {1 {unable to open database: cannot-read}}
do_test attach-6.2.2 {
db errorcode
} {14}
sqlite3 dbx cannot-read
dbx eval {CREATE TABLE t1(a,b,c)}
dbx close
file attributes cannot-read -permission 0000
if {[file writable cannot-read]} {
#puts "\n**** Tests do not work when run as root ****"
file delete -force cannot-read
#exit 1
} else {
do_test attach-6.2 {
catchsql {
ATTACH DATABASE 'cannot-read' AS noread;
}
} {1 {unable to open database: cannot-read}}
do_test attach-6.2.2 {
db errorcode
} {14}
}
file delete -force cannot-read
}
+3
View File
@@ -656,6 +656,9 @@ do_test bind-13.4 {
[sqlite3_column_type $VM 2]
} {NULL NULL NULL}
sqlite3_finalize $VM
do_test bind-13.5 {
sqlite3_clear_bindings_null
} {0}
#--------------------------------------------------------------------
# These tests attempt to reproduce bug #3463.
+1 -5
View File
@@ -401,12 +401,8 @@ sqlite3 db test.db
# if we're using proxy locks, we use 3 filedescriptors for a db
# that is open but NOT writing changes, normally
# sqlite uses 1 (proxy locking adds the conch and the local lock)
set using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
set using_proxy $value
}
set extrafds 0
if {$using_proxy!=0} {
if {[forced_proxy_locking]} {
set extrafds 2
}
+1
View File
@@ -76,6 +76,7 @@ set skipwaltests [expr {
[permutation]=="journaltest" || [permutation]=="inmemory_journal"
}]
ifcapable !wal { set skipwaltests 1 }
if {![wal_is_ok]} { set skipwaltests 1 }
if {!$skipwaltests} {
db close
+1 -1
View File
@@ -20,7 +20,7 @@ source $testdir/malloc_common.tcl
# If a connection is required to create a journal file, it creates it with
# the same file-system permissions as the database file itself. Test this.
#
if {$::tcl_platform(platform) == "unix"} {
if {$::tcl_platform(platform) == "unix" && ![path_is_dos "."]} {
set umask [exec /bin/sh -c umask]
faultsim_delete_and_reopen
+73 -69
View File
@@ -106,87 +106,91 @@ if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} {
return
}
do_test lock5-flock.1 {
sqlite3 db test.db -vfs unix-flock
execsql {
CREATE TABLE t1(a, b);
BEGIN;
INSERT INTO t1 VALUES(1, 2);
}
} {}
# Only run the flock tests on a local file system
if { [path_is_local "."] } {
# Make sure we are not accidentally using the dotfile locking scheme.
do_test lock5-flock.2 {
file exists test.db.lock
} {0}
do_test lock5-flock.1 {
sqlite3 db test.db -vfs unix-flock
execsql {
CREATE TABLE t1(a, b);
BEGIN;
INSERT INTO t1 VALUES(1, 2);
}
} {}
do_test lock5-flock.3 {
catch { sqlite3 db2 test.db -vfs unix-flock }
catchsql { SELECT * FROM t1 } db2
} {1 {database is locked}}
# Make sure we are not accidentally using the dotfile locking scheme.
do_test lock5-flock.2 {
file exists test.db.lock
} {0}
do_test lock5-flock.4 {
execsql COMMIT
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
do_test lock5-flock.3 {
catch { sqlite3 db2 test.db -vfs unix-flock }
catchsql { SELECT * FROM t1 } db2
} {1 {database is locked}}
do_test lock5-flock.5 {
execsql BEGIN
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
do_test lock5-flock.4 {
execsql COMMIT
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
do_test lock5-flock.6 {
execsql {SELECT * FROM t1}
catchsql { SELECT * FROM t1 } db2
} {1 {database is locked}}
do_test lock5-flock.5 {
execsql BEGIN
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
do_test lock5-flock.7 {
db close
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
do_test lock5-flock.6 {
execsql {SELECT * FROM t1}
catchsql { SELECT * FROM t1 } db2
} {1 {database is locked}}
do_test lock5-flock.8 {
db2 close
} {}
do_test lock5-flock.7 {
db close
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
#####################################################################
do_test lock5-flock.8 {
db2 close
} {}
do_test lock5-none.1 {
sqlite3 db test.db -vfs unix-none
sqlite3 db2 test.db -vfs unix-none
execsql {
BEGIN;
INSERT INTO t1 VALUES(3, 4);
}
} {}
do_test lock5-none.2 {
execsql { SELECT * FROM t1 }
} {1 2 3 4}
do_test lock5-flock.3 {
execsql { SELECT * FROM t1 } db2
} {1 2}
do_test lock5-none.4 {
execsql {
BEGIN;
SELECT * FROM t1;
} db2
} {1 2}
do_test lock5-none.5 {
execsql COMMIT
execsql {SELECT * FROM t1} db2
} {1 2}
#####################################################################
ifcapable memorymanage {
do_test lock5-none.6 {
sqlite3_release_memory 1000000
execsql {SELECT * FROM t1} db2
do_test lock5-none.1 {
sqlite3 db test.db -vfs unix-none
sqlite3 db2 test.db -vfs unix-none
execsql {
BEGIN;
INSERT INTO t1 VALUES(3, 4);
}
} {}
do_test lock5-none.2 {
execsql { SELECT * FROM t1 }
} {1 2 3 4}
}
do_test lock5-flock.3 {
execsql { SELECT * FROM t1 } db2
} {1 2}
do_test lock5-none.4 {
execsql {
BEGIN;
SELECT * FROM t1;
} db2
} {1 2}
do_test lock5-none.5 {
execsql COMMIT
execsql {SELECT * FROM t1} db2
} {1 2}
do_test lock5-flock.X {
db close
db2 close
} {}
ifcapable memorymanage {
do_test lock5-none.6 {
sqlite3_release_memory 1000000
execsql {SELECT * FROM t1} db2
} {1 2 3 4}
}
do_test lock5-flock.X {
db close
db2 close
} {}
}
ifcapable lock_proxy_pragmas {
set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
+5 -3
View File
@@ -126,9 +126,10 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
set lockpath
} {{:auto: (not held)}}
set lpp [exec mktemp -t fail]
do_test lock6-1.4.1 {
execsql "PRAGMA lock_proxy_file='$lpp'"
catchsql {
PRAGMA lock_proxy_file="notmine";
select * from sqlite_master;
} db
} {1 {database is locked}}
@@ -137,7 +138,7 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
execsql {
PRAGMA lock_proxy_file;
} db
} {notmine}
} $lpp
do_test lock6-1.5 {
testfixture $::tf1 {
@@ -150,9 +151,10 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
catch {testfixture $::tf1 {db close}}
set lpp [exec mktemp -t ok]
do_test lock6-1.6 {
execsql "PRAGMA lock_proxy_file='$lpp'"
execsql {
PRAGMA lock_proxy_file="mine";
select * from sqlite_master;
} db
} {}
+2 -2
View File
@@ -55,8 +55,8 @@ proc do_multiclient_test {varname script} {
uplevel set $varname $tn
uplevel $script
code2 { db2 close }
code3 { db3 close }
catch { code2 { db2 close } }
catch { code3 { db3 close } }
catch { close $::code2_chan }
catch { close $::code3_chan }
catch { db close }
+142
View File
@@ -0,0 +1,142 @@
# 2008 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 script is database proxy locks.
#
# $Id$
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# This file is only run if using the unix backend compiled with the
# SQLITE_ENABLE_LOCKING_STYLE macro.
db close
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
finish_test
return
}
db close
file delete -force test.db.lock
#####################################################################
ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
set ::using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
set ::using_proxy $value
}
# enable the proxy locking for these tests
set env(SQLITE_FORCE_PROXY_LOCKING) "1"
# test conch file creation
#
catch { file delete lock_proxy_test.db }
catch { file delete .lock_proxy_test.db-conch }
# test that proxy locking mode creates conch files
do_test lock_proxy1.0 {
sqlite3 db2 lock_proxy_test.db
catchsql {
create table x(y);
} db2
file exists .lock_proxy_test.db-conch
} {1}
catch { db2 close }
# test proxy locking readonly file system handling
#
if {[file exists /usr/bin/hdiutil]} {
puts "Creating readonly file system for proxy locking tests..."
if {[file exists /Volumes/readonly]} {
exec hdiutil detach /Volumes/readonly
}
if {[file exists readonly.dmg]} {
file delete readonly.dmg
}
exec hdiutil create -megabytes 1 -fs HFS+ readonly.dmg -volname readonly
exec hdiutil attach readonly.dmg
# create test1.db and a .test1.db-conch for host4
set sqlite_hostid_num 4
sqlite3 db2 /Volumes/readonly/test1.db
execsql {
create table x(y);
} db2
db2 close
# create test2.db and a .test2.db-conch for host5
set sqlite_hostid_num 5
sqlite3 db2 /Volumes/readonly/test2.db
execsql {
create table x(y);
} db2
db2 close
# create test3.db without a conch file
set env(SQLITE_FORCE_PROXY_LOCKING) "0"
sqlite3 db2 /Volumes/readonly/test3.db
execsql {
create table x(y);
} db2
db2 close
exec hdiutil detach /Volumes/readonly
exec hdiutil attach -readonly readonly.dmg
# test that an unwritable, host-mismatched conch file prevents
# read only proxy-locking mode database access
set env(SQLITE_FORCE_PROXY_LOCKING) "1"
do_test lock_proxy2.0 {
sqlite3 db2 /Volumes/readonly/test1.db
catchsql {
select * from sqlite_master;
} db2
} {1 {database is locked}}
catch { db2 close }
# test that an unwritable, host-matching conch file allows
# read only proxy-locking mode database access
do_test lock_proxy2.1 {
sqlite3 db2 /Volumes/readonly/test2.db
catchsql {
select * from sqlite_master;
} db2
} {0 {table x x 2 {CREATE TABLE x(y)}}}
catch { db2 close }
# test that an unwritable, nonexistant conch file allows
# read only proxy-locking mode database access
do_test lock_proxy2.2 {
sqlite3 db2 /Volumes/readonly/test3.db
catchsql {
select * from sqlite_master;
} db2
} {0 {table x x 2 {CREATE TABLE x(y)}}}
catch { db2 close }
exec hdiutil detach /Volumes/readonly
file delete readonly.dmg
}
set env(SQLITE_FORCE_PROXY_LOCKING) "0"
set sqlite_hostid_num 0
}
#####################################################################
file delete -force test.db
ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
}
finish_test
+3 -3
View File
@@ -314,7 +314,7 @@ if {[permutation] == ""} {
#
do_test main-3.1 {
catch {db close}
foreach f [glob -nocomplain testdb/*] {file delete -force $f}
catch {foreach f [glob -nocomplain testdb/*] {file delete -force $f}}
file delete -force testdb
sqlite3 db testdb
set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
@@ -322,7 +322,7 @@ do_test main-3.1 {
} {1 {unrecognized token: "!!"}}
do_test main-3.2 {
catch {db close}
foreach f [glob -nocomplain testdb/*] {file delete -force $f}
catch {foreach f [glob -nocomplain testdb/*] {file delete -force $f}}
file delete -force testdb
sqlite3 db testdb
set v [catch {execsql {SELECT * from T1 where ^x}} msg]
@@ -442,7 +442,7 @@ do_test main-3.2.30 {
do_test main-3.3 {
catch {db close}
foreach f [glob -nocomplain testdb/*] {file delete -force $f}
catch {foreach f [glob -nocomplain testdb/*] {file delete -force $f}}
file delete -force testdb
sqlite3 db testdb
execsql {
+1 -1
View File
@@ -408,7 +408,7 @@ proc do_malloc_test {tn args} {
set zRepeat "transient"
if {$::iRepeat} {set zRepeat "persistent"}
restore_prng_state
foreach file [glob -nocomplain test.db-mj*] {file delete -force $file}
catch {foreach file [glob -nocomplain test.db-mj*] {file delete -force $file}}
do_test ${tn}.${zRepeat}.${::n} {
+1 -5
View File
@@ -22,12 +22,8 @@ set N 300
# if we're using proxy locks, we use 5 filedescriptors for a db
# that is open and in the middle of writing changes, normally
# sqlite uses 3 (proxy locking adds the conch and the local lock)
set using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
set using_proxy value
}
set num_fd_per_openwrite_db 3
if {$using_proxy>0} {
if {[forced_proxy_locking]} {
set num_fd_per_openwrite_db 5
}
+21 -18
View File
@@ -407,24 +407,27 @@ do_test memdb-8.2 {
# Test that auto-vacuum works with in-memory databases.
#
ifcapable autovacuum {
do_test memdb-9.1 {
db close
sqlite3 db test.db
db cache size 0
execsql {
PRAGMA auto_vacuum = full;
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(randstr(1000,1000));
INSERT INTO t1 VALUES(randstr(1000,1000));
INSERT INTO t1 VALUES(randstr(1000,1000));
}
set memused [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
set pgovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 1]
execsql { DELETE FROM t1 }
set memused2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
expr {($memused2 + 2048 < $memused) || $pgovfl==0}
} {1}
set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
if {[lindex $msize 2]!=0} {
ifcapable autovacuum {
do_test memdb-9.1 {
db close
sqlite3 db test.db
db cache size 0
execsql {
PRAGMA auto_vacuum = full;
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(randstr(1000,1000));
INSERT INTO t1 VALUES(randstr(1000,1000));
INSERT INTO t1 VALUES(randstr(1000,1000));
}
set memused [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
set pgovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 1]
execsql { DELETE FROM t1 }
set memused2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
expr {($memused2 + 2048 < $memused) || $pgovfl==0}
} {1}
}
}
} ;# ifcapable memorydb
+29 -24
View File
@@ -182,17 +182,20 @@ build_test_db memsubsys1-5 {PRAGMA page_size=4096}
do_test memsubsys1-5.3 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 24
do_test memsubsys1-5.4 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
expr {$maxreq>4096}
} 1
do_test memsubsys1-5.5 {
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0
do_test memsubsys1-5.6 {
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
expr {$s_ovfl>6000}
} 1
set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
if {[lindex $msize 2]!=0} {
do_test memsubsys1-5.4 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
expr {$maxreq>4096}
} 1
do_test memsubsys1-5.5 {
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0
do_test memsubsys1-5.6 {
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
expr {$s_ovfl>6000}
} 1
}
# Test 6: Activate both PAGECACHE and SCRATCH with a 4k page size.
# Make it so that SCRATCH is large enough
@@ -268,19 +271,21 @@ do_test memsubsys1-8.1 {
do_test memsubsys1-8.2 {
set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
} 0
do_test memsubsys1-8.3 {
sqlite3 db :memory:
db eval {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(400));
INSERT INTO t1 VALUES(zeroblob(400));
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
}
expr {[lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]>0}
} 1
db close
if {[lindex $msize 2]!=0} {
do_test memsubsys1-8.3 {
sqlite3 db :memory:
db eval {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(400));
INSERT INTO t1 VALUES(zeroblob(400));
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
}
expr {[lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]>0}
} 1
db close
}
sqlite3_shutdown
sqlite3_config_memstatus 0
sqlite3_initialize
+33
View File
@@ -1055,6 +1055,39 @@ ifcapable crashtest {
}
#-------------------------------------------------------------------------
# When a 3.7.0 client opens a write-transaction on a database file that
# has been appended to or truncated by a pre-370 client, it updates
# the db-size in the file header immediately. This test case provokes
# errors during that operation.
#
do_test pagerfault-22-pre1 {
faultsim_delete_and_reopen
db func a_string a_string
execsql {
PRAGMA page_size = 1024;
PRAGMA auto_vacuum = 0;
CREATE TABLE t1(a);
CREATE INDEX i1 ON t1(a);
INSERT INTO t1 VALUES(a_string(3000));
CREATE TABLE t2(a);
INSERT INTO t2 VALUES(1);
}
db close
sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
faultsim_save_and_close
} {}
do_faultsim_test pagerfault-22 -prep {
faultsim_restore_and_reopen
} -body {
execsql { INSERT INTO t2 VALUES(2) }
execsql { SELECT * FROM t2 }
} -test {
faultsim_test_result {0 {1 2}}
faultsim_integrity_check
}
#-------------------------------------------------------------------------
# When a 3.7.0 client opens a write-transaction on a database file that
# has been appended to or truncated by a pre-370 client, it updates
+137 -32
View File
@@ -1292,7 +1292,12 @@ sqlite3 dbX :memory:
dbX eval {PRAGMA temp_store_directory = ""}
dbX close
ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
set skip_lock_proxy_tests [path_is_dos "."]
ifcapable !(lock_proxy_pragmas&&prefer_proxy_locking) {
set skip_lock_proxy_tests 1
}
if !$skip_lock_proxy_tests {
set sqlite_hostid_num 1
set using_proxy 0
@@ -1306,67 +1311,67 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
set env(SQLITE_FORCE_PROXY_LOCKING) "0"
sqlite3 db test.db
# set lock proxy name and then query it via pragma interface
set lpp [exec mktemp -t 'proxy1']
do_test pragma-16.1 {
execsql {
PRAGMA lock_proxy_file="mylittleproxy";
select * from sqlite_master;
}
execsql {
PRAGMA lock_proxy_file;
}
} {mylittleproxy}
execsql "PRAGMA lock_proxy_file='$lpp'"
execsql "select * from sqlite_master"
execsql "PRAGMA lock_proxy_file"
} $lpp
# 2 database connections can share a lock proxy file
do_test pragma-16.2 {
sqlite3 db2 test.db
execsql {
PRAGMA lock_proxy_file="mylittleproxy";
} db2
execsql "PRAGMA lock_proxy_file='$lpp'" db2
} {}
db2 close
# 2nd database connection should auto-name an existing lock proxy file
do_test pragma-16.2.1 {
sqlite3 db2 test.db
execsql {
PRAGMA lock_proxy_file=":auto:";
select * from sqlite_master;
} db2
execsql {
PRAGMA lock_proxy_file;
} db2
} {mylittleproxy}
execsql "PRAGMA lock_proxy_file" db2
} $lpp
db2 close
set lpp2 [exec mktemp -t 'proxy2']
# 2nd database connection cannot override the lock proxy file
do_test pragma-16.3 {
sqlite3 db2 test.db
execsql {
PRAGMA lock_proxy_file="myotherproxy";
} db2
execsql "PRAGMA lock_proxy_file='$lpp2'" db2
catchsql {
select * from sqlite_master;
} db2
} {1 {database is locked}}
set lpp3 [exec mktemp -t 'proxy3']
# lock proxy file can be renamed if no other connections are active
do_test pragma-16.4 {
db2 close
db close
sqlite3 db2 test.db
execsql {
PRAGMA lock_proxy_file="myoriginalproxy";
PRAGMA lock_proxy_file="myotherproxy";
PRAGMA lock_proxy_file;
} db2
} {myotherproxy}
execsql "PRAGMA lock_proxy_file='$lpp3'" db2
execsql "PRAGMA lock_proxy_file='$lpp2'" db2
execsql "PRAGMA lock_proxy_file" db2
} $lpp2
db2 close
set env(SQLITE_FORCE_PROXY_LOCKING) "1"
# auto-naming should reuse the last proxy name when available
do_test pragma-16.5 {
sqlite3 db2 test.db
execsql {
PRAGMA lock_proxy_file=":auto:";
PRAGMA lock_proxy_file;
} db2
} {myotherproxy}
} $lpp2
# auto-naming a new proxy should use a predictable & unique name
do_test pragma-16.6 {
db2 close
sqlite3 db2 test2.db
@@ -1378,6 +1383,7 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
} {1}
set sqlite_hostid_num 2
# db access should be limited to one host at a time (simulate 2nd host id)
do_test pragma-16.7 {
list [catch {
sqlite3 db test2.db
@@ -1389,6 +1395,7 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
} {1 {database is locked}}
db close
# default to using proxy locking (simulate network file system detection)
do_test pragma-16.8 {
list [catch {
sqlite3 db test2.db
@@ -1397,19 +1404,25 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
} {1 {database is locked}}
db2 close
set lpp4 [exec mktemp -t 'proxy4']
# check that db is unlocked after first host connection closes
do_test pragma-16.8.1 {
execsql {
PRAGMA lock_proxy_file="yetanotherproxy";
PRAGMA lock_proxy_file;
}
} {yetanotherproxy}
execsql "PRAGMA lock_proxy_file='$lpp4'"
execsql "select * from sqlite_master"
execsql "PRAGMA lock_proxy_file"
} $lpp4
do_test pragma-16.8.2 {
execsql {
create table mine(x);
create table if not exists mine(x);
insert into mine values (1);
}
} {}
db close
file delete -force proxytest.db
file delete -force .proxytest.db-conch
do_test pragma-16.9 {
sqlite3 db proxytest.db
set lockpath2 [execsql {
@@ -1419,6 +1432,98 @@ ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
string match "*proxytest.db:auto:" $lockpath2
} {1}
# ensure creating directories for a lock proxy file works
set lpp5 [exec mktemp -d -t "proxy5"]/sub/dir/lock
db close
file delete -force proxytest
do_test pragma-16.10.1 {
sqlite3 db proxytest.db
execsql "PRAGMA lock_proxy_file='$lpp5'"
set lockpath2 [execsql {
PRAGMA lock_proxy_file;
} db]
string match "*sub/dir/lock" $lockpath2
} {1}
# ensure that after deleting the path, setting ":auto:" works correctly
db close
file delete -force proxytest
do_test pragma-16.10.2 {
sqlite3 db proxytest.db
set lockpath3 [execsql {
PRAGMA lock_proxy_file=":auto:";
create table if not exists pt(y);
PRAGMA lock_proxy_file;
} db]
string match "*sub/dir/lock" $lockpath3
} {1}
# ensure that if the path can not be created (file instead of dir)
# setting :auto: deals with it by creating a new autonamed lock file
db close
file delete -force proxytest
close [open "proxytest" a]
do_test pragma-16.10.3 {
sqlite3 db proxytest.db
set lockpath2 [execsql {
PRAGMA lock_proxy_file=":auto:";
create table if not exists zz(y);
PRAGMA lock_proxy_file;
} db]
string match "*proxytest.db:auto:" $lockpath2
} {1}
# make sure we can deal with ugly file paths correctly
set lpp6 [exec mktemp -d -t "proxy6"]/./././////./proxytest/../proxytest/sub/dir/lock
db close
file delete -force proxytest
do_test pragma-16.10.4 {
sqlite3 db proxytest.db
execsql "PRAGMA lock_proxy_file='$lpp6'"
set lockpath4 [execsql {
create table if not exists aa(bb);
PRAGMA lock_proxy_file;
} db]
string match "*proxytest/sub/dir/lock" $lockpath4
} {1}
# ensure that if the path can not be created (perm), setting :auto: deals
db close
file delete -force proxytest
do_test pragma-16.10.5 {
sqlite3 db proxytest.db
execsql "PRAGMA lock_proxy_file='$lpp5'"
execsql {
create table if not exists bb(bb);
}
db close
file delete -force proxytest
file mkdir proxytest
file attributes proxytest -permission 0000
sqlite3 db proxytest.db
set lockpath5 [execsql {
PRAGMA lock_proxy_file=":auto:";
create table if not exists cc(bb);
PRAGMA lock_proxy_file;
} db]
string match "*proxytest.db:auto:" $lockpath5
} {1}
# ensure that if the path can not be created, locking fails
db close
do_test pragma-16.10.6 {
sqlite3 db proxytest.db
execsql "PRAGMA lock_proxy_file='$lpp5'"
catchsql {
create table if not exists faily(y);
PRAGMA lock_proxy_file;
} db
} {1 {database is locked}}
db close
file attributes proxytest -permission 0777
file delete -force proxytest
set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy
set sqlite_hostid_num 0
}
+1 -5
View File
@@ -45,13 +45,9 @@ ifcapable autovacuum {
# if we're using proxy locks, we use 2 filedescriptors for a db
# that is open but NOT yet locked, after a lock is taken we'll have 3,
# normally sqlite uses 1 (proxy locking adds the conch and the local lock)
set using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
set using_proxy $value
}
set extrafds_prelock 0
set extrafds_postlock 0
if {$using_proxy>0} {
if {[forced_proxy_locking]} {
set extrafds_prelock 1
set extrafds_postlock 2
}
+24 -7
View File
@@ -30,8 +30,19 @@ if {$::TEMP_STORE==3} {
finish_test
return
}
# if we're using proxy locks, we use 3 filedescriptors for a db
# that is open but NOT writing changes, normally
# sqlite uses 1 (proxy locking adds the conch and the local lock)
set extrafds 0
if {[forced_proxy_locking]} {
set extrafds 2
}
do_test stmt-1.2 {
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {1}
do_test stmt-1.3 {
execsql {
@@ -40,16 +51,19 @@ do_test stmt-1.3 {
INSERT INTO t1 VALUES(1, 1);
}
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {2}
do_test stmt-1.4 {
execsql {
INSERT INTO t1 SELECT a+1, b+1 FROM t1;
}
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {3}
do_test stmt-1.5 {
execsql COMMIT
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {1}
do_test stmt-1.6.1 {
execsql {
@@ -57,34 +71,37 @@ do_test stmt-1.6.1 {
INSERT INTO t1 SELECT a+2, b+2 FROM t1;
}
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {2}
do_test stmt-1.6.2 {
execsql { INSERT INTO t1 SELECT a+4, b+4 FROM t1 }
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {3}
do_test stmt-1.7 {
execsql COMMIT
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} {1}
proc filecount {testname sql expected} {
proc filecount {testname sql expected extrafds} {
uplevel [list do_test $testname [subst -nocommand {
execsql BEGIN
execsql { $sql }
set ret [set sqlite_open_file_count]
execsql ROLLBACK
set ret
}] $expected]
}] [ expr $expected+$extrafds ] ]
}
filecount stmt-2.1 { INSERT INTO t1 VALUES(9, 9) } 2
filecount stmt-2.2 { REPLACE INTO t1 VALUES(9, 9) } 2
filecount stmt-2.3 { INSERT INTO t1 SELECT 9, 9 } 2
filecount stmt-2.1 { INSERT INTO t1 VALUES(9, 9) } 2 $extrafds
filecount stmt-2.2 { REPLACE INTO t1 VALUES(9, 9) } 2 $extrafds
filecount stmt-2.3 { INSERT INTO t1 SELECT 9, 9 } 2 $extrafds
filecount stmt-2.4 {
INSERT INTO t1 SELECT 9, 9;
INSERT INTO t1 SELECT 10, 10;
} 3
} 3 $extrafds
do_test stmt-2.5 {
execsql { CREATE INDEX i1 ON t1(b) }
@@ -92,6 +109,6 @@ do_test stmt-2.5 {
filecount stmt-2.6 {
REPLACE INTO t1 VALUES(5, 5);
REPLACE INTO t1 VALUES(5, 5);
} 3
} 3 $extrafds
finish_test
+7 -2
View File
@@ -52,6 +52,11 @@ do_test tempdb-1.2 {
}
} {}
set extrafds 0
if {[forced_proxy_locking]} {
set extrafds 2
}
do_test tempdb-2.1 {
# Set $::jrnl_in_memory if the journal file is expected to be in-memory.
# Similarly, set $::subj_in_memory if the sub-journal file is expected
@@ -76,7 +81,7 @@ do_test tempdb-2.2 {
}
catchsql { INSERT INTO t1 SELECT * FROM t2 }
set sqlite_open_file_count
} [expr 1 + (0==$jrnl_in_memory) + (0==$subj_in_memory)]
} [expr 1 + $extrafds + (0==$jrnl_in_memory) + (0==$subj_in_memory)]
do_test tempdb-2.3 {
execsql {
PRAGMA temp_store = 'memory';
@@ -88,6 +93,6 @@ do_test tempdb-2.3 {
}
catchsql { INSERT INTO t1 SELECT * FROM t2 }
set sqlite_open_file_count
} [expr 1 + (0==$jrnl_in_memory)]
} [expr 1 + $extrafds + (0==$jrnl_in_memory)]
finish_test
+37 -4
View File
@@ -605,11 +605,15 @@ proc finalize_testing {} {
memdebug_log_sql leaks.sql
}
}
foreach f [glob -nocomplain test.db-*-journal] {
file delete -force $f
catch {
foreach f [glob -nocomplain test.db-*-journal] {
file delete -force $f
}
}
foreach f [glob -nocomplain test.db-mj*] {
file delete -force $f
catch {
foreach f [glob -nocomplain test.db-mj*] {
file delete -force $f
}
}
exit [expr {$nErr>0}]
}
@@ -1314,6 +1318,35 @@ proc presql {} {
set presql
}
proc forced_proxy_locking {} {
ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
set force_proxy_value 0
set force_key "SQLITE_FORCE_PROXY_LOCKING="
foreach {env_pair} [exec env] {
if { [string first $force_key $env_pair] == 0} {
set force_proxy_value [string range $env_pair [string length $force_key] end]
}
}
if { "$force_proxy_value " == "1 " } {
return 1
}
}
return 0
}
proc wal_is_ok {} {
if { [forced_proxy_locking] } {
return 1
}
if { ![path_is_local "."] } {
return 0
}
if { [path_is_dos "."] } {
return 0
}
return 1
}
#-------------------------------------------------------------------------
#
proc slave_test_script {script} {
+22 -20
View File
@@ -62,26 +62,28 @@ do_test tkt3457-1.1 {
execsql COMMIT
} {}
do_test tkt3457-1.2 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions ---------
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.3 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions -w--w--w-
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.4 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions r--r--r--
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
if { ![path_is_dos "."] } {
do_test tkt3457-1.2 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions ---------
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.3 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions -w--w--w-
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.4 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions r--r--r--
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.5 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions rw-rw-rw-
catchsql { SELECT * FROM t1 }
} {0 {1 2 3 4 5 6}}
do_test tkt3457-1.5 {
file copy -force bak.db-journal test.db-journal
file attributes test.db-journal -permissions rw-rw-rw-
catchsql { SELECT * FROM t1 }
} {0 {1 2 3 4 5 6}}
}
finish_test
+4
View File
@@ -22,6 +22,10 @@ source $testdir/wal_common.tcl
set testprefix wal
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
proc reopen_db {} {
catch { db close }
+4
View File
@@ -22,6 +22,10 @@ source $testdir/wal_common.tcl
set testprefix wal2
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] || [path_is_dos "."]} {
finish_test
return
}
set sqlite_sync_count 0
proc cond_incr_sync_count {adj} {
+5 -1
View File
@@ -19,6 +19,10 @@ source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
set a_string_counter 1
proc a_string {n} {
@@ -615,7 +619,7 @@ T delete
#-------------------------------------------------------------------------
#
do_test wal3-8.1 {
file delete -force test.db test.db-journal test.db wal
file delete -force test.db test.db-journal test.db wal .test.db-conch
sqlite3 db test.db
sqlite3 db2 test.db
execsql {
+4
View File
@@ -16,6 +16,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] || [path_is_dos "."]} {
finish_test
return
}
do_test wal4-1.1 {
execsql {
+4
View File
@@ -21,6 +21,10 @@ source $testdir/malloc_common.tcl
do_not_use_codec
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
# Test organization:
+4
View File
@@ -27,6 +27,10 @@ ifcapable !lfs {
finish_test
return
}
if { ![wal_is_ok] } {
finish_test
return
}
set a_string_counter 1
proc a_string {n} {
+4
View File
@@ -16,6 +16,10 @@ source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
# Read and return the contents of file $filename. Treat the content as
# binary data.
+4
View File
@@ -28,6 +28,10 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
db close
+4
View File
@@ -16,6 +16,10 @@ source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
#-------------------------------------------------------------------------
+4
View File
@@ -19,6 +19,10 @@ source $testdir/malloc_common.tcl
source $testdir/lock_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
#-------------------------------------------------------------------------
# This test case, walfault-1-*, simulates faults while executing a
+4
View File
@@ -22,6 +22,10 @@ source $testdir/tester.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
set ::wal_hook [list]
proc wal_hook {zDb nEntry} {
+14
View File
@@ -35,6 +35,20 @@ ifcapable !wal {
finish_test
return
}
if { ![wal_is_ok] && ![path_is_dos "."]} {
do_test walmode-0.1 {
execsql { PRAGMA journal_mode = wal }
} {delete}
do_test walmode-0.2 {
execsql { PRAGMA main.journal_mode = wal }
} {delete}
do_test walmode-0.3 {
execsql { PRAGMA main.journal_mode }
} {delete}
finish_test
return
}
do_test walmode-1.1 {
set sqlite_sync_count 0
+159
View File
@@ -0,0 +1,159 @@
# 2011 May 09
#
# 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 contains tests for using WAL databases in read-only mode.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix walro
do_multiclient_test tn {
# These tests are only going to work on unix.
#
if {$tcl_platform(platform) != "unix"} continue
# Do not run tests with the connections in the same process.
#
if {$tn==2} continue
# Close all connections and delete the database.
#
code1 { db close }
code2 { db2 close }
code3 { db3 close }
forcedelete test.db
forcedelete walro
foreach c {code1 code2 code3} {
$c {
sqlite3_shutdown
sqlite3_config_uri 1
}
}
file mkdir walro
do_test 1.1.1 {
code2 { sqlite3 db2 test.db }
sql2 {
PRAGMA journal_mode = WAL;
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES('a', 'b');
}
file exists test.db-shm
} {1}
do_test 1.1.2 {
file attributes test.db-shm -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
} {}
do_test 1.1.3 { sql1 "SELECT * FROM t1" } {a b}
do_test 1.1.4 { sql2 "INSERT INTO t1 VALUES('c', 'd')" } {}
do_test 1.1.5 { sql1 "SELECT * FROM t1" } {a b c d}
# Check that the read-only connection cannot write or checkpoint the db.
#
do_test 1.1.6 {
csql1 "INSERT INTO t1 VALUES('e', 'f')"
} {1 {attempt to write a readonly database}}
do_test 1.1.7 {
csql1 "PRAGMA wal_checkpoint"
} {1 {attempt to write a readonly database}}
do_test 1.1.9 { sql2 "INSERT INTO t1 VALUES('e', 'f')" } {}
do_test 1.1.10 { sql1 "SELECT * FROM t1" } {a b c d e f}
do_test 1.1.11 {
sql2 {
INSERT INTO t1 VALUES('g', 'h');
PRAGMA wal_checkpoint;
}
set {} {}
} {}
do_test 1.1.12 { sql1 "SELECT * FROM t1" } {a b c d e f g h}
do_test 1.1.13 { sql2 "INSERT INTO t1 VALUES('i', 'j')" } {}
do_test 1.2.1 {
code2 { db2 close }
code1 { db close }
list [file exists test.db-wal] [file exists test.db-shm]
} {1 1}
do_test 1.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
sql1 { SELECT * FROM t1 }
} {a b c d e f g h i j}
do_test 1.2.3 {
code1 { db close }
file attributes test.db-shm -permissions rw-r--r--
hexio_write test.db-shm 0 01020304
file attributes test.db-shm -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
csql1 { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
do_test 1.2.4 {
code1 { sqlite3_extended_errcode db }
} {SQLITE_READONLY_RECOVERY}
do_test 1.2.5 {
file attributes test.db-shm -permissions rw-r--r--
code2 { sqlite3 db2 test.db }
sql2 "SELECT * FROM t1"
} {a b c d e f g h i j}
file attributes test.db-shm -permissions r--r--r--
do_test 1.2.6 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j}
do_test 1.2.7 {
sql2 {
PRAGMA wal_checkpoint;
INSERT INTO t1 VALUES('k', 'l');
}
set {} {}
} {}
do_test 1.2.8 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j k l}
# Now check that if the readonly_shm option is not supplied, or if it
# is set to zero, it is not possible to connect to the database without
# read-write access to the shm.
do_test 1.3.1 {
code1 { db close }
code1 { sqlite3 db test.db }
csql1 { SELECT * FROM t1 }
} {1 {unable to open database file}}
# Also test that if the -shm file can be opened for read/write access,
# it is, even if readonly_shm=1 is present in the URI.
do_test 1.3.2.1 {
code1 { db close }
code2 { db2 close }
file exists test.db-shm
} {0}
do_test 1.3.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
sql1 { SELECT * FROM t1 }
} {a b c d e f g h i j k l}
do_test 1.3.2.3 {
code1 { db close }
close [open test.db-shm w]
file attributes test.db-shm -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
csql1 { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
do_test 1.3.2.4 {
code1 { sqlite3_extended_errcode db }
} {SQLITE_READONLY_RECOVERY}
}
finish_test
-1
View File
@@ -60,4 +60,3 @@ do_test walshared-1.4 {
sqlite3_enable_shared_cache $::enable_shared_cache
finish_test
+4
View File
@@ -18,6 +18,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
proc reopen_db {} {
catch { db close }
+4
View File
@@ -19,6 +19,10 @@ source $testdir/tester.tcl
source $testdir/lock_common.tcl
if {[run_thread_tests]==0} { finish_test ; return }
ifcapable !wal { finish_test ; return }
if { ![wal_is_ok] } {
finish_test
return
}
set sqlite_walsummary_mmap_incr 64
+2
View File
@@ -107,6 +107,7 @@ foreach hdr {
sqliteicu.h
sqliteInt.h
sqliteLimit.h
sqlrr.h
vdbe.h
vdbeInt.h
wal.h
@@ -306,6 +307,7 @@ foreach file {
rtree.c
icu.c
fts3_icu.c
sqlrr.c
} {
copy_file tsrc/$file
}