Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0cefa2b39b | |||
| aec336af26 | |||
| d74c576ee6 | |||
| 027200ec51 | |||
| d819aea05f | |||
| e96ab66f34 | |||
| 2e4491d4b1 | |||
| 1b2327c509 | |||
| 66f6ad7b94 | |||
| b5f87f4394 | |||
| fbea85d6cd | |||
| b09945e64c | |||
| c3835e0208 | |||
| d736884f3d | |||
| 283f9e7ee6 | |||
| fa64665a49 | |||
| e127a2ea9f | |||
| 5be1b1f262 | |||
| 25d2380356 | |||
| 69d67f5412 | |||
| 6f7fe3ef3e | |||
| e3a4e11bcc | |||
| 67d225da53 | |||
| 5a5ced7da9 | |||
| 985be1bce6 | |||
| 99f24349ea | |||
| 890b69fb83 | |||
| f5d6f1e0c5 | |||
| 5ec0cfe070 | |||
| 3b3b1a538d | |||
| b0fa210aa3 | |||
| 801829c812 | |||
| 9b3c15e860 | |||
| 61d3bfb78b | |||
| 45d55a254b | |||
| 51e5db70b6 | |||
| f219bba933 | |||
| a0166e1873 | |||
| aff0449d8f | |||
| c55e9b815f | |||
| 03ba419b3c | |||
| c4098a3d9f | |||
| 21ce77989a | |||
| 91973abb4b | |||
| 722db051c6 | |||
| 87dd60cd8d | |||
| 7244fdc446 | |||
| 4f7e8fcded | |||
| 95063a5774 | |||
| ad7c2a87f5 | |||
| cc3ec7cb2b | |||
| 3942b4b147 | |||
| 9aa0012a08 | |||
| efd8e3b33d | |||
| 0b90b2209f | |||
| 9782039bde | |||
| 332aa832ce | |||
| bf4cad1e4c | |||
| b0c5edcd06 | |||
| 2250799f0c | |||
| ca071dfd75 | |||
| ac0c39980a | |||
| 04d4227255 | |||
| e6c3c72c1b |
+14
@@ -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
|
||||
@@ -471,6 +474,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.
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
#include "sqlite3rtree.h"
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -346,6 +348,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.
|
||||
@@ -367,10 +371,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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
C Add\sa\sbit\sto\sthe\sSQLITE_TESTCTRL_OPTIMIZATIONS\ssetting\sthat\swill\sdisable\naffinity\swhen\swriting\sto\sany\sindex,\sregardless\sof\swhether\sor\snot\sthe\sindex\nis\son\sa\smanifestation\sof\sa\sview.\s\sThis\sallows\sbetter\stesting\sof\sthe\sfix\nfor\sticket\s[91e2e8ba6ff2e2].
|
||||
D 2011-06-23T17:29:33.244
|
||||
C Patches\sto\sthe\sapple-osx-377\sbranch\sso\sthat\sit\swill\scompile\sand\srun\son\s\nnon-Mac\sunix\splatforms.
|
||||
D 2011-10-11T00:09:13.879
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e
|
||||
F Makefile.in 8410b02448997eb43bdf0ffa482c9bc2d2624e45
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 11082f65b452b908d93013292c17850378c39284
|
||||
F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
|
||||
@@ -84,7 +84,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 b431c54d1ed05f04f2987e8a4fbb931acb40c312
|
||||
F ext/rtree/rtree.c c64b78b1995fdbde9af7d2b910f8c9d9d908f583
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 28e1b8da4da98093ce3210187434dd760a8d89d8
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
@@ -102,9 +102,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 d799fb600383cee11fed58876a7cccb749dd2614
|
||||
F main.mk b2f00a81c37fbce7098d77c58eb816d9bd94d3d3
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
@@ -121,10 +124,10 @@ F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5
|
||||
F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
|
||||
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
|
||||
F src/backup.c 1cf56cc81b035e0a9884ddac13442edefcb0cb46
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 8c46f0ab69ad9549c75a3a91fed87abdaa743e2f
|
||||
F src/btree.c 1870b70e376c5c9ff31e1235e4e4434212709265
|
||||
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
|
||||
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
||||
F src/build.c 5a428625d21ad409514afb40ad083bee25dd957a
|
||||
@@ -136,20 +139,20 @@ F src/delete.c 4925f9121525fc871f5d8d13c1f7dcc91abb38bb
|
||||
F src/expr.c ab46ab0f0c44979a8164ca31728d7d10ae5e8106
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 9fabba17a4d4778dc660f0cb9d781fc86d7b9d41
|
||||
F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7
|
||||
F src/func.c 1b9d471b632d8529e0f86b7bd2b918dcc2cb1097
|
||||
F src/global.c c70a46f28680f8d7c097dbc0430ccf3b932e90b0
|
||||
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 fa654e1802e14a5f6c09c37971c3b69c1001d9c8
|
||||
F src/main.c f3d35af74fdccb20f7edb31d842006d99887cf2e
|
||||
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
|
||||
F src/mem1.c c390a8fce10912a770ebe6fa031f5f463649e7ae
|
||||
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
|
||||
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
|
||||
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
|
||||
@@ -161,34 +164,35 @@ F src/mutex_os2.c 882d735098c07c8c6a5472b8dd66e19675fe117f
|
||||
F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
|
||||
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
|
||||
F src/os.c 1663f3754a3da185369a121a4f417762f77880b6
|
||||
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
|
||||
F src/os_unix.c 07acbb3e074e52b48a4248c06f66c9a91db1a0ce
|
||||
F src/os_win.c eafcd6b91cf204a7ef29ac1ef2a1b7132e132e58
|
||||
F src/pager.c 120550e7ef01dafaa2cbb4a0528c0d87c8f12b41
|
||||
F src/os_unix.c c936dcabe90f688c59c91f26df79ea56ba4f156a
|
||||
F src/os_win.c daa67fe04bd162fbcc387214e9614a7faa6b90b1
|
||||
F src/pager.c 4bee5b51c33855cd8de4094709912b000f2bccff
|
||||
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
|
||||
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
||||
F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce
|
||||
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
||||
F src/pcache1.c 912bd5687d6df344698d8e69560f347b6e21c18a
|
||||
F src/pragma.c ebcd20f1e654f5cb3aeef864ed69c4697719fbaa
|
||||
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
|
||||
F src/pragma.c 66661dbe8428dd3215bd4c8f8a43dd3326e0bf6f
|
||||
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/select.c 75b7dd8c6a5ff9b8ec3f7ed51d31af8b30f114bc
|
||||
F src/shell.c 0e0173b3e79d956368013e759f084caa7995ecb1
|
||||
F src/sqlite.h.in 4b7255c10d39c5faf089dbd29cde7c367ff39f1f
|
||||
F src/sqlite.h.in 05e72174ea58476dc71db4bb6816f5b79a100f76
|
||||
F src/sqlite3_private.h e3b586e0aa329075d99be7198df9bc80c5b19e2d
|
||||
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
||||
F src/sqliteInt.h 7b72f7c6929757c0678d94524dbc7e7e3d6dc398
|
||||
F src/sqliteInt.h 2f4919d0105a821f04433a181f877c8a70201f9a
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c 5db825be61708b1a2b3f8f6e185e9b753829acef
|
||||
F src/test1.c 8eef932f1024f1076a8adb8a6f5d9c5267c9e969
|
||||
F src/test1.c 411093e4d82ddd7202f23e2222d7f039e2432a3d
|
||||
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
||||
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
|
||||
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
|
||||
@@ -199,9 +203,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 791a9acbf9a695cf9c12ff6bbe874dfde9a8c5f3
|
||||
F src/test_config.c 90707f2dd59c01f11bbbbb168833fdef73f1e5de
|
||||
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
|
||||
@@ -220,11 +224,11 @@ F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
|
||||
F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32
|
||||
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
|
||||
F src/test_quota.c cc4f67e12558a252ea4a11720be268348f4b1595
|
||||
F src/test_rtree.c 30c981837445a4e187ee850a49c4760d9642f7c3
|
||||
F src/test_rtree.c af76d5a2ead69280ba33d318263167ad9e674bb0
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
|
||||
F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
|
||||
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_superlock.c 12e2bc484c6c2ba837327d37f2e6a6fd9d1464f8
|
||||
F src/test_syscall.c 162c4ec0137a549c009bb9ecab550527743cfc5d
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c fe9a7803fc1d69cccb60f016f28c1cedf2d9fcfa
|
||||
@@ -238,17 +242,17 @@ F src/update.c 80d77311d91ebc06b27149e75701f1b3e9356622
|
||||
F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
|
||||
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
|
||||
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
||||
F src/vdbe.c 50b5b4ef29d928a4f60905f820ee1ab2f8ced29f
|
||||
F src/vdbe.c 80d511d7096918f4f6be6a63988a885c54dd1048
|
||||
F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1
|
||||
F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45
|
||||
F src/vdbeapi.c 2f908c65337b16c6249ab378d477e74492cf759b
|
||||
F src/vdbeaux.c 0b2e2880f13af400a27c92a7673287c3eaec8b21
|
||||
F src/vdbeapi.c 7f01db7d26758b2be316116f8325a0b9f0d8edd6
|
||||
F src/vdbeaux.c cfb5207d13d0bc3d2753bba67900c462b60ecb08
|
||||
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
|
||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
|
||||
F src/vdbetrace.c 4b92fe7355f682368203d29b2be7125cbab85e79
|
||||
F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
|
||||
F src/wal.c 0c70ad7b1cac6005fa5e2cbefd23ee05e391c290
|
||||
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
|
||||
F src/wal.c eea77c324942f7e31ce9c3a5e6e86c4a0424fa09
|
||||
F src/wal.h e75d87752bd5df3dc4152ee2cb3b0dcd0b309e5e
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
|
||||
F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199
|
||||
@@ -272,7 +276,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
|
||||
@@ -295,7 +299,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
|
||||
@@ -390,12 +394,12 @@ F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
|
||||
F test/enc4.test b145fa25feb56ea1d51a5bc43ca268c0cf691a67
|
||||
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 95a45d7a705ab985a62ceed8ac7b145fcb61154e
|
||||
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
|
||||
F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
|
||||
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
|
||||
@@ -500,11 +504,11 @@ F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
|
||||
F test/incrblob.test 76e787ca3301d9bfa6906031c626d26f8dd707de
|
||||
F test/incrblob2.test edc3a96e557bd61fb39acc8d2edd43371fbbaa19
|
||||
F test/incrblob3.test aedbb35ea1b6450c33b98f2b6ed98e5020be8dc7
|
||||
F test/incrblob3.test 086482e7937202be9f8cf327117a042d8628fe7d
|
||||
F test/incrblob_err.test c577c91d4ed9e8336cdb188b15d6ee2a6fe9604e
|
||||
F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0
|
||||
F test/incrvacuum.test 453d1e490d8f5ad2c9b3a54282a0690d6ae56462
|
||||
F test/incrvacuum2.test ae04573b73ad52179f56e194fff0fbe43b509d23
|
||||
F test/incrvacuum2.test 08b23884a3acc8f5027385adafede3a0b044e3f9
|
||||
F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
|
||||
F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
@@ -533,7 +537,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
|
||||
@@ -549,12 +553,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 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 76017be66cec4375a4b4ea5c71245e27a9fe2d0b
|
||||
F test/malloc3.test 4128b1e6ffa506103b278ad97af89174f310c7ca
|
||||
@@ -576,12 +581,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
|
||||
@@ -594,7 +599,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3
|
||||
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
|
||||
F test/multiplex.test 555080c87abfc72ba68e2f3df01d4a9a7a4fdf58
|
||||
F test/multiplex.test afd41c4fcf132a8940761c7852b427c37705e4bb
|
||||
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test dc212a22b36109fd1ae37154292444ef249c5ec2
|
||||
@@ -605,10 +610,10 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
|
||||
F test/oserror.test 3fe52e0bd2891a9bf7cdeb639554992453d46301
|
||||
F test/pager1.test 228a831060dab96bc91b03ba2a85cedefd1ab38a
|
||||
F test/pager1.test 52725f1e15e02ec651921a7cd1083c3d0052a9c4
|
||||
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pagerfault.test 4194b8ea2a5da7958cd155556605ff554e1b065a
|
||||
F test/pagerfault.test b0a275779f0b0233809d2644dec94d689357e00a
|
||||
F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401
|
||||
F test/pagerfault3.test f16e2efcb5fc9996d1356f7cbc44c998318ae1d7
|
||||
F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
|
||||
@@ -616,7 +621,7 @@ F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
|
||||
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
|
||||
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
|
||||
F test/permutations.test 1e8892ebf1bd6e9e8036f4841c72a91bf72da74a
|
||||
F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
|
||||
F test/pragma.test 6c4b98a9f5e3fbc23631fcbfa53b095f3955ca72
|
||||
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
|
||||
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
|
||||
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
|
||||
@@ -658,7 +663,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
|
||||
@@ -681,21 +686,21 @@ 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
|
||||
F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082
|
||||
F test/superlock.test b68339e473d26cdeabe784ef14d7522334ec22c3
|
||||
F test/sync.test 2bd73b585089c99e76b3e1796c42059b7d89d872
|
||||
F test/syscall.test 707c95e4ab7863e13f1293c6b0c76bead30249b3
|
||||
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 7d3d17914ca5397a82f801db733b81d4a82f50c3
|
||||
F test/tester.tcl be83dc1662e7bce357d53f7ff9cecdc16a7046eb
|
||||
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
|
||||
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
|
||||
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
|
||||
@@ -788,7 +793,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
|
||||
@@ -875,27 +880,28 @@ 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/wal5.test f06a0427e06db00347e32eb9fa99d6a5c0f2d088
|
||||
F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8
|
||||
F test/wal.test c2df96d6f209076fe0571054eedfc4879d1c8a3a
|
||||
F test/wal2.test aaeac9c0f901cb3a779a49a5100decc615f04d76
|
||||
F test/wal3.test a4670279d6ed3fc4e0355d0e77882f7f46d54bbc
|
||||
F test/wal4.test 6a68c45bc1ca24a3592ec449ddcb92b29d0e0e87
|
||||
F test/wal5.test ad9865a6e39bfcf62c96f075e4c31838295b6509
|
||||
F test/wal6.test 8df39843b1471dc02993d173937b2c6589e2cb59
|
||||
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
|
||||
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/wal_common.tcl 15f152fd55703975878741beca6cfa4209d5b3b3
|
||||
F test/walbak.test 767e1c9e0ea0cfb907873b332883e66e187fa4bc
|
||||
F test/walbig.test 78ac493db2abdb65b9c6cace5b851cc32df1d449
|
||||
F test/walcksum.test cf6787f2ee1a6a3da6f0c2b20b9ede5153e4e03f
|
||||
F test/walcrash.test 80c1cc3173a0ef09d8303fa556cb0187a36d82ea
|
||||
F test/walcrash2.test c032d0040374ae28b41f99fc0cc290b4e2e34f17
|
||||
F test/walfault.test 7db81f3dac64ce8897196f199c2909078bcabf8d
|
||||
F test/walhook.test c934ac5219fee2b4e7653d291db9107b8dc73bba
|
||||
F test/walmode.test 8fe643a94841a1f95186e91e220181429f1188c1
|
||||
F test/walnoshm.test a074428046408f4eb5c6a00e09df8cc97ff93317
|
||||
F test/walro.test 2d5d69e2e99da19ce6faab340330234fc4ca0720
|
||||
F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
|
||||
F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
|
||||
F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
|
||||
F test/walpersist.test 45fb0c94fb63908e2d66b1d99ce4645bfce0fa1e
|
||||
F test/walro.test 05769ae10ddce1b6ad41bdd5326ab7ef951c8278
|
||||
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
|
||||
@@ -921,7 +927,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 1fa0ed9cfdc768bf5de7e65fda8d97a46dd2a7e6
|
||||
F tool/mksqlite3c.tcl d99ceeda7010ce4bc47666f51d47edac57f24bb7
|
||||
F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8
|
||||
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
|
||||
F tool/omittest.tcl 8086c014cbae90f1f2b564d59d05a5e4ac1783c9
|
||||
@@ -949,7 +955,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00
|
||||
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d
|
||||
P c271f7e88fc081a460dd3f4afb24aa9fb7fa2917
|
||||
R 5805b6f3882ce897a61c4ce87076bc70
|
||||
P db5b7b778c09c57501cb8266895a0ea4f2de7649
|
||||
R f5591d41a3ef2a2d817d7a74a89f31ff
|
||||
U drh
|
||||
Z 83d974f3e6b84b4810ac6511db96428d
|
||||
Z 315988c25345647ead14743334f970a8
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
b61a76a53af04f731fe7617f7b6b4fb2aef6587b
|
||||
b431a63437a81214d69c523d76241e6d4127ee0f
|
||||
@@ -417,6 +417,15 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
if( p->pDestDb ){
|
||||
sqlite3ResetInternalSchema(p->pDestDb, -1);
|
||||
}
|
||||
|
||||
if( destMode==PAGER_JOURNALMODE_WAL ){
|
||||
/* This call cannot fail. The success of the BtreeUpdateMeta()
|
||||
** method above indicates that a write transaction has been opened
|
||||
** and page 1 is already dirty. Therefore this always succeeds.
|
||||
*/
|
||||
TESTONLY(int rc2 =) sqlite3BtreeSetVersion(p->pDest, 2);
|
||||
assert( rc2==SQLITE_OK );
|
||||
}
|
||||
|
||||
/* Set nDestTruncate to the final number of pages in the destination
|
||||
|
||||
+27
-1
@@ -68,8 +68,14 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
|
||||
** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
|
||||
*/
|
||||
int sqlite3_enable_shared_cache(int enable){
|
||||
#if defined(__APPLE__) && !defined(SQLITE_TEST) && !defined(TH3_COMPATIBILITY)
|
||||
/* Enable global shared cache function for debugging and unit tests,
|
||||
** but not for release */
|
||||
return SQLITE_MISUSE;
|
||||
#else
|
||||
sqlite3GlobalConfig.sharedCacheEnabled = enable;
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2350,6 +2356,27 @@ static int lockBtree(BtShared *pBt){
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto page1_init_failed;
|
||||
}else if( isOpen==0 ){
|
||||
#ifdef SQLITE_DEFAULT_WAL_SAFETYLEVEL
|
||||
/* Default to specified safety_level for WAL mode */
|
||||
if( pBt->db!=0 && pBt->db->aDb!=0 ){
|
||||
int iDb;
|
||||
sqlite3 *db = pBt->db;
|
||||
Db *aDb = db->aDb;
|
||||
u8 level = 0;
|
||||
for(iDb=0; iDb<db->nDb; iDb++){
|
||||
if( aDb[iDb].pBt && aDb[iDb].pBt->pBt==pBt ) break;
|
||||
}
|
||||
assert( iDb<db->nDb );
|
||||
level = db->aDb[iDb].safety_level;
|
||||
if( !SQLITE_DbSafetyLevelIsFixed(level) &&
|
||||
(SQLITE_DbSafetyLevelValue(level) != SQLITE_DEFAULT_WAL_SAFETYLEVEL) ){
|
||||
aDb[iDb].safety_level = SQLITE_DEFAULT_WAL_SAFETYLEVEL;
|
||||
sqlite3PagerSetSafetyLevel(pBt->pPager, SQLITE_DEFAULT_WAL_SAFETYLEVEL,
|
||||
(db->flags&SQLITE_FullFSync)!=0,
|
||||
(db->flags&SQLITE_CkptFullFSync)!=0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
releasePage(pPage1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -8142,7 +8169,6 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
|
||||
BtShared *pBt = pBtree->pBt;
|
||||
int rc; /* Return code */
|
||||
|
||||
assert( pBtree->inTrans==TRANS_NONE );
|
||||
assert( iVersion==1 || iVersion==2 );
|
||||
|
||||
/* If setting the version fields to 1, do not automatically open the
|
||||
|
||||
@@ -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
@@ -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 ){
|
||||
|
||||
+61
@@ -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,17 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
}
|
||||
return oldLimit; /* IMP: R-53341-35419 */
|
||||
}
|
||||
#if defined(SQLITE_ENABLE_AUTO_PROFILE)
|
||||
void _sqlite_auto_profile(void *aux, const char *sql, u64 ns);
|
||||
void _sqlite_auto_trace(void *aux, const char *sql);
|
||||
void _sqlite_auto_profile(void *aux, const char *sql, u64 ns) {
|
||||
#pragma unused(aux)
|
||||
fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
|
||||
}
|
||||
void _sqlite_auto_trace(void *aux, const char *sql) {
|
||||
fprintf(stderr, "TraceSQL(%p): %s\n", aux, sql);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function is used to parse both URIs and non-URI filenames passed by the
|
||||
@@ -2122,6 +2140,9 @@ static int openDatabase(
|
||||
db->nextAutovac = -1;
|
||||
db->nextPagesize = 0;
|
||||
db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
|
||||
#if SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
| SQLITE_CkptFullFSync
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_FILE_FORMAT<4
|
||||
| SQLITE_LegacyFileFmt
|
||||
#endif
|
||||
@@ -2278,7 +2299,23 @@ 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");
|
||||
char *envtrace = getenv("SQLITE_AUTO_TRACE");
|
||||
|
||||
if( envprofile!=NULL ){
|
||||
sqlite3_profile(db, _sqlite_auto_profile, db);
|
||||
}
|
||||
if( envtrace!=NULL ){
|
||||
sqlite3_trace(db, _sqlite_auto_trace, db);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*ppDb = db;
|
||||
#ifdef SQLITE_ENABLE_SQLRR
|
||||
SRRecOpen(db, zFilename, flags);
|
||||
#endif
|
||||
return sqlite3ApiExit(0, rc);
|
||||
}
|
||||
|
||||
@@ -2941,3 +2978,27 @@ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
|
||||
|
||||
#include "sqlite3_private.h"
|
||||
|
||||
/*
|
||||
** Testing a file path for sqlite locks held by a process ID.
|
||||
** Returns SQLITE_LOCKSTATE_ON if locks are present on path
|
||||
** that would prevent writing to the database.
|
||||
*/
|
||||
int _sqlite3_lockstate(const char *path, pid_t pid){
|
||||
sqlite3 *db = NULL;
|
||||
|
||||
if( sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK ){
|
||||
LockstatePID lockstate = {pid, -1};
|
||||
sqlite3_file_control(db, NULL, SQLITE_FCNTL_LOCKSTATE_PID, &lockstate);
|
||||
sqlite3_close(db);
|
||||
int state = lockstate.state;
|
||||
return state;
|
||||
}
|
||||
return SQLITE_LOCKSTATE_ERROR;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_APPLE_SPI */
|
||||
|
||||
+95
-3
@@ -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))
|
||||
#define SQLITE_MALLOCSIZE(x) (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Like malloc(), but remember the size of the allocation
|
||||
** so that we can find it later using sqlite3MemSize().
|
||||
@@ -38,7 +60,8 @@ static void *sqlite3MemMalloc(int nByte){
|
||||
sqlite3_int64 *p;
|
||||
assert( nByte>0 );
|
||||
nByte = ROUND8(nByte);
|
||||
p = malloc( nByte+8 );
|
||||
#ifndef SQLITE_MALLOCSIZE
|
||||
p = SQLITE_MALLOC( nByte + 8 );
|
||||
if( p ){
|
||||
p[0] = nByte;
|
||||
p++;
|
||||
@@ -46,6 +69,13 @@ static void *sqlite3MemMalloc(int nByte){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
||||
}
|
||||
#else
|
||||
p = SQLITE_MALLOC( nByte );
|
||||
if( !p ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
||||
}
|
||||
#endif
|
||||
return (void *)p;
|
||||
}
|
||||
|
||||
@@ -60,8 +90,10 @@ static void *sqlite3MemMalloc(int nByte){
|
||||
static void sqlite3MemFree(void *pPrior){
|
||||
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
|
||||
assert( pPrior!=0 );
|
||||
#ifndef SQLITE_MALLOCSIZE
|
||||
p--;
|
||||
free(p);
|
||||
#endif
|
||||
SQLITE_FREE(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -69,11 +101,15 @@ static void sqlite3MemFree(void *pPrior){
|
||||
** or xRealloc().
|
||||
*/
|
||||
static int sqlite3MemSize(void *pPrior){
|
||||
#ifndef SQLITE_MALLOCSIZE
|
||||
sqlite3_int64 *p;
|
||||
if( pPrior==0 ) return 0;
|
||||
p = (sqlite3_int64*)pPrior;
|
||||
p--;
|
||||
return (int)p[0];
|
||||
#else
|
||||
return (int)SQLITE_MALLOCSIZE(pPrior);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -90,17 +126,27 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
|
||||
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
|
||||
assert( pPrior!=0 && nByte>0 );
|
||||
assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
|
||||
#ifndef SQLITE_MALLOCSIZE
|
||||
p--;
|
||||
p = realloc(p, nByte+8 );
|
||||
p = SQLITE_REALLOC(p, nByte+8 );
|
||||
if( p ){
|
||||
p[0] = nByte;
|
||||
p++;
|
||||
}else{
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM,
|
||||
"failed memory resize %u to %u bytes",
|
||||
sqlite3MemSize(pPrior), nByte);
|
||||
}
|
||||
#else
|
||||
p = SQLITE_REALLOC(p, nByte );
|
||||
if( !p ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM,
|
||||
"failed memory resize %u to %u bytes",
|
||||
sqlite3MemSize(pPrior), nByte);
|
||||
}
|
||||
#endif
|
||||
return (void*)p;
|
||||
}
|
||||
|
||||
@@ -115,6 +161,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 +200,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 +235,8 @@ void sqlite3MemSetDefault(void){
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
|
||||
}
|
||||
|
||||
#undef SQLITE_MALLOC
|
||||
#undef SQLITE_FREE
|
||||
#undef SQLITE_REALLOC
|
||||
|
||||
#endif /* SQLITE_SYSTEM_MALLOC */
|
||||
|
||||
@@ -131,12 +131,18 @@ int sqlite3OsOpen(
|
||||
int *pFlagsOut
|
||||
){
|
||||
int rc;
|
||||
int openFlags;
|
||||
DO_OS_MALLOC_TEST(0);
|
||||
/* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
|
||||
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
|
||||
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
|
||||
** reaching the VFS. */
|
||||
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut);
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
openFlags = flags & (0x87f3f | SQLITE_OPEN_FILEPROTECTION_MASK);
|
||||
#else
|
||||
openFlags = flags & 0x87f3f;
|
||||
#endif
|
||||
rc = pVfs->xOpen(pVfs, zPath, pFile, openFlags, pFlagsOut);
|
||||
assert( rc==SQLITE_OK || pFile->pMethods==0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
+1068
-66
File diff suppressed because it is too large
Load Diff
+15
-4
@@ -102,8 +102,9 @@ struct winFile {
|
||||
const sqlite3_io_methods *pMethod; /*** Must be first ***/
|
||||
sqlite3_vfs *pVfs; /* The VFS used to open this file */
|
||||
HANDLE h; /* Handle for accessing the file */
|
||||
unsigned char locktype; /* Type of lock currently held on this file */
|
||||
u8 locktype; /* Type of lock currently held on this file */
|
||||
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
|
||||
u8 bPersistWal; /* True to persist WAL files */
|
||||
DWORD lastErrno; /* The Windows errno from the last I/O error */
|
||||
DWORD sectorSize; /* Sector size of the device file is on */
|
||||
winShm *pShm; /* Instance of shared memory on this file */
|
||||
@@ -1276,17 +1277,18 @@ static int winUnlock(sqlite3_file *id, int locktype){
|
||||
** Control and query of the open file handle.
|
||||
*/
|
||||
static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
winFile *pFile = (winFile*)id;
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_LOCKSTATE: {
|
||||
*(int*)pArg = ((winFile*)id)->locktype;
|
||||
*(int*)pArg = pFile->locktype;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_LAST_ERRNO: {
|
||||
*(int*)pArg = (int)((winFile*)id)->lastErrno;
|
||||
*(int*)pArg = (int)pFile->lastErrno;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_CHUNK_SIZE: {
|
||||
((winFile*)id)->szChunk = *(int *)pArg;
|
||||
pFile->szChunk = *(int *)pArg;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_SIZE_HINT: {
|
||||
@@ -1296,6 +1298,15 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
SimulateIOErrorBenign(0);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_PERSIST_WAL: {
|
||||
int bPersist = *(int*)pArg;
|
||||
if( bPersist<0 ){
|
||||
*(int*)pArg = pFile->bPersistWal;
|
||||
}else{
|
||||
pFile->bPersistWal = bPersist!=0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_SYNC_OMITTED: {
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+40
-9
@@ -2377,7 +2377,11 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
||||
if( !pMaster ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
|
||||
const int flags =
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
(pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)|
|
||||
#endif
|
||||
(SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
|
||||
rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||
@@ -2413,7 +2417,11 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
||||
** so, return without deleting the master journal file.
|
||||
*/
|
||||
int c;
|
||||
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
|
||||
int flags =
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
(pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)|
|
||||
#endif
|
||||
(SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
|
||||
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto delmaster_out;
|
||||
@@ -3398,7 +3406,11 @@ static int pagerOpentemp(
|
||||
sqlite3_opentemp_count++; /* Used for testing and analysis only */
|
||||
#endif
|
||||
|
||||
vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
||||
vfsFlags |=
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
(pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)|
|
||||
#endif
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
||||
SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
|
||||
rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
|
||||
assert( rc!=SQLITE_OK || isOpen(pFile) );
|
||||
@@ -4527,7 +4539,11 @@ int sqlite3PagerOpen(
|
||||
pPager->noSync = pPager->tempFile;
|
||||
pPager->fullSync = pPager->noSync ?0:1;
|
||||
pPager->syncFlags = pPager->noSync ? 0 : SQLITE_SYNC_NORMAL;
|
||||
#if SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
pPager->ckptSyncFlags = pPager->noSync ? 0 : SQLITE_SYNC_FULL;
|
||||
#else
|
||||
pPager->ckptSyncFlags = pPager->syncFlags;
|
||||
#endif
|
||||
/* pPager->pFirst = 0; */
|
||||
/* pPager->pFirstSynced = 0; */
|
||||
/* pPager->pLast = 0; */
|
||||
@@ -4638,7 +4654,11 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
** it can be ignored.
|
||||
*/
|
||||
if( !jrnlOpen ){
|
||||
int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
|
||||
int f =
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
(pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)|
|
||||
#endif
|
||||
SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -4776,7 +4796,11 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
|
||||
if( rc==SQLITE_OK && bExists ){
|
||||
int fout = 0;
|
||||
int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
|
||||
int f =
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
(pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)|
|
||||
#endif
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
|
||||
assert( !pPager->tempFile );
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
|
||||
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
|
||||
@@ -5152,6 +5176,9 @@ static int pager_open_journal(Pager *pPager){
|
||||
sqlite3MemJournalOpen(pPager->jfd);
|
||||
}else{
|
||||
const int flags = /* VFS flags to open journal file */
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
(pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)|
|
||||
#endif
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
|
||||
(pPager->tempFile ?
|
||||
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
|
||||
@@ -6710,10 +6737,14 @@ static int pagerOpenWal(Pager *pPager){
|
||||
** (e.g. due to malloc() failure), return an error code.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3WalOpen(pPager->pVfs,
|
||||
pPager->fd, pPager->zWal, pPager->exclusiveMode,
|
||||
pPager->journalSizeLimit, &pPager->pWal
|
||||
);
|
||||
#if SQLITE_ENABLE_DATA_PROTECTION
|
||||
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode,
|
||||
pPager->journalSizeLimit, (pPager->vfsFlags & (SQLITE_OPEN_FILEPROTECTION_MASK | SQLITE_OPEN_READONLY)),
|
||||
&pPager->pWal);
|
||||
#else
|
||||
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode,
|
||||
pPager->journalSizeLimit, (pPager->vfsFlags & SQLITE_OPEN_READONLY), &pPager->pWal);
|
||||
#endif
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
+43
-21
@@ -144,12 +144,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);
|
||||
@@ -212,7 +212,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 ){
|
||||
@@ -409,8 +410,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().
|
||||
@@ -432,7 +433,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);
|
||||
@@ -440,11 +441,11 @@ void sqlite3Pragma(
|
||||
if( pId2->n==0 && b>=0 ){
|
||||
int ii;
|
||||
for(ii=0; ii<db->nDb; ii++){
|
||||
sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
|
||||
sqlite3BtreeSecureDelete(db->aDb[ii].pBt, (int)b);
|
||||
}
|
||||
}
|
||||
b = sqlite3BtreeSecureDelete(pBt, b);
|
||||
returnSingleInt(pParse, "secure_delete", b);
|
||||
b = (int)sqlite3BtreeSecureDelete(pBt, (int)b);
|
||||
returnSingleInt(pParse, "secure_delete", &b);
|
||||
}else
|
||||
|
||||
/*
|
||||
@@ -563,6 +564,20 @@ void sqlite3Pragma(
|
||||
iDb = 0;
|
||||
pId2->n = 1;
|
||||
}
|
||||
#ifdef SQLITE_DEFAULT_WAL_SAFETYLEVEL
|
||||
if( ! SQLITE_DbSafetyLevelIsFixed(pDb->safety_level) ){
|
||||
if( eMode == PAGER_JOURNALMODE_WAL ){
|
||||
/* when entering wal mode, immediately switch the safety_level
|
||||
** so that a query to pragma synchronous returns the correct value */
|
||||
|
||||
pDb->safety_level = SQLITE_DEFAULT_WAL_SAFETYLEVEL;
|
||||
}else{
|
||||
/* If the user hasn't overridden the synchronous setting, use the
|
||||
** default for non-wal databases */
|
||||
pDb->safety_level = 3;
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_DEFAULT_WAL_SAFETYLEVEL */
|
||||
for(ii=db->nDb-1; ii>=0; ii--){
|
||||
if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
|
||||
sqlite3VdbeUsesBtree(v, ii);
|
||||
@@ -586,7 +601,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 */
|
||||
@@ -606,13 +621,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 );
|
||||
@@ -695,7 +710,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;
|
||||
@@ -716,7 +732,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);
|
||||
}
|
||||
@@ -830,13 +847,16 @@ void sqlite3Pragma(
|
||||
if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
if( !zRight ){
|
||||
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
|
||||
u8 level = pDb->safety_level;
|
||||
i64 safetyLevel = (i64)(SQLITE_DbSafetyLevelValue(level)-1);
|
||||
returnSingleInt(pParse, "synchronous", &safetyLevel);
|
||||
}else{
|
||||
if( !db->autoCommit ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"Safety level may not be changed inside a transaction");
|
||||
}else{
|
||||
pDb->safety_level = getSafetyLevel(zRight)+1;
|
||||
u8 level = getSafetyLevel(zRight)+1;
|
||||
pDb->safety_level = (level | SQLITE_SAFETYLEVEL_FIXED);
|
||||
}
|
||||
}
|
||||
}else
|
||||
@@ -1423,12 +1443,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
|
||||
|
||||
@@ -1513,7 +1535,7 @@ void sqlite3Pragma(
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
if( db->autoCommit ){
|
||||
sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
|
||||
sqlite3BtreeSetSafetyLevel(pDb->pBt, SQLITE_DbSafetyLevelValue(pDb->safety_level),
|
||||
(db->flags&SQLITE_FullFSync)!=0,
|
||||
(db->flags&SQLITE_CkptFullFSync)!=0);
|
||||
}
|
||||
|
||||
+12
-1
@@ -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
|
||||
|
||||
@@ -4371,6 +4371,9 @@ select_end:
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG)
|
||||
void sqlite3PrintExpr(Expr *p);
|
||||
void sqlite3PrintExprList(ExprList *pList);
|
||||
void sqlite3PrintSelect(Select *p, int indent);
|
||||
/*
|
||||
*******************************************************************************
|
||||
** The following code is used for testing and debugging only. The code
|
||||
|
||||
+40
-9
@@ -483,6 +483,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
||||
#define SQLITE_OPEN_FILEPROTECTION_MASK 0x00700000
|
||||
|
||||
/* Reserved: 0x00F00000 */
|
||||
|
||||
@@ -736,16 +737,35 @@ 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_PERSIST_WAL] opcode is used to set or query the
|
||||
** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
|
||||
** write ahead log and shared memory files used for transaction control
|
||||
** are automatically deleted when the latest connection to the database
|
||||
** closes. Setting persistent WAL mode causes those files to persist after
|
||||
** close. Persisting the files is useful when other processes that do not
|
||||
** have write permission on the directory containing the database file want
|
||||
** to read the database file, as the WAL and shared memory files must exist
|
||||
** in order for the database to be readable. The fourth parameter to
|
||||
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
|
||||
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
|
||||
** WAL mode. If the integer is -1, then it is overwritten with the current
|
||||
** WAL persistence setting.
|
||||
**
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_GET_LOCKPROXYFILE 2
|
||||
#define SQLITE_SET_LOCKPROXYFILE 3
|
||||
#define SQLITE_LAST_ERRNO 4
|
||||
#define SQLITE_FCNTL_SIZE_HINT 5
|
||||
#define SQLITE_FCNTL_CHUNK_SIZE 6
|
||||
#define SQLITE_FCNTL_FILE_POINTER 7
|
||||
#define SQLITE_FCNTL_SYNC_OMITTED 8
|
||||
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
|
||||
#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3
|
||||
#define SQLITE_FCNTL_LAST_ERRNO 4
|
||||
#define SQLITE_FCNTL_SIZE_HINT 5
|
||||
#define SQLITE_FCNTL_CHUNK_SIZE 6
|
||||
#define SQLITE_FCNTL_FILE_POINTER 7
|
||||
#define SQLITE_FCNTL_SYNC_OMITTED 8
|
||||
#define SQLITE_FCNTL_PERSIST_WAL 10
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
|
||||
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@@ -3322,6 +3342,12 @@ int sqlite3_step(sqlite3_stmt*);
|
||||
** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
|
||||
** interfaces) then sqlite3_data_count(P) returns 0.
|
||||
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
|
||||
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
|
||||
** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
|
||||
** will return non-zero if previous call to [sqlite3_step](P) returned
|
||||
** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
|
||||
** where it always returns zero since each step of that multi-step
|
||||
** pragma returns 0 columns of data.
|
||||
**
|
||||
** See also: [sqlite3_column_count()]
|
||||
*/
|
||||
@@ -4455,6 +4481,11 @@ void *sqlite3_update_hook(
|
||||
** future releases of SQLite. Applications that care about shared
|
||||
** cache setting should set it explicitly.
|
||||
**
|
||||
** ^Note: This method is deprecated on MacOS X 10.7 and iOS version 5.0
|
||||
** and will always return SQLITE_MISUSE, instead of calling this function
|
||||
** shared cache mode should be enabled per-database connection via
|
||||
** sqlite3_open_v2 with SQLITE_OPEN_SHAREDCACHE instead.
|
||||
**
|
||||
** See Also: [SQLite Shared-Cache Mode]
|
||||
*/
|
||||
int sqlite3_enable_shared_cache(int);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* sqlite3_private.h
|
||||
*/
|
||||
|
||||
#ifndef _SQLITE3_PRIVATE_H
|
||||
#define _SQLITE3_PRIVATE_H
|
||||
|
||||
#define SQLITE_LOCKSTATE_OFF 0
|
||||
#define SQLITE_LOCKSTATE_ON 1
|
||||
#define SQLITE_LOCKSTATE_NOTADB 2
|
||||
#define SQLITE_LOCKSTATE_ERROR -1
|
||||
|
||||
#define SQLITE_LOCKSTATE_ANYPID -1
|
||||
|
||||
/*
|
||||
** Test a file path for sqlite locks held by a process ID (-1 = any PID).
|
||||
** Returns one of the following integer codes:
|
||||
**
|
||||
** SQLITE_LOCKSTATE_OFF no active sqlite file locks match the specified pid
|
||||
** SQLITE_LOCKSTATE_ON active sqlite file locks match the specified pid
|
||||
** SQLITE_LOCKSTATE_NOTADB path points to a file that is not an sqlite db file
|
||||
** SQLITE_LOCKSTATE_ERROR path was not vaild or was unreadable
|
||||
**
|
||||
** There is no support for identifying db files encrypted via SEE encryption
|
||||
** currently. Zero byte files are tested for sqlite locks, but if no sqlite
|
||||
** locks are present then SQLITE_LOCKSTATE_NOTADB is returned.
|
||||
*/
|
||||
extern int _sqlite3_lockstate(const char *path, pid_t pid);
|
||||
|
||||
/*
|
||||
** Test an open database connection for sqlite locks held by a process ID,
|
||||
** if a process has an open database connection this will avoid trashing file
|
||||
** locks by re-using open file descriptors for the database file and support
|
||||
** files (-shm)
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE_PID 103
|
||||
|
||||
/*
|
||||
** 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_FCNTL_TRUNCATE_DATABASE 101
|
||||
#define SQLITE_TRUNCATE_DATABASE SQLITE_FCNTL_TRUNCATE_DATABASE
|
||||
|
||||
/*
|
||||
** 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_FCNTL_REPLACE_DATABASE 102
|
||||
#define SQLITE_REPLACE_DATABASE SQLITE_FCNTL_REPLACE_DATABASE
|
||||
|
||||
#endif
|
||||
@@ -651,6 +651,16 @@ typedef struct WhereLevel WhereLevel;
|
||||
#include "os.h"
|
||||
#include "mutex.h"
|
||||
|
||||
/* When using a default wal safety level, the safety level should only
|
||||
** change with the journal mode if the user hasn't manually specified
|
||||
** pragma synchronous, if they have the defaults shouldn't be applied.
|
||||
** The SQLITE_SAFETYLEVEL_FIXED value is ORed into the Db->safety_level
|
||||
** field when the user has specified a synchronous setting via pragma.
|
||||
*/
|
||||
#define SQLITE_SAFETYLEVEL_FIXED 0x10
|
||||
#define SQLITE_SAFETYLEVEL_VALUE_MASK 0x03
|
||||
#define SQLITE_DbSafetyLevelValue(level) (level&SQLITE_SAFETYLEVEL_VALUE_MASK)
|
||||
#define SQLITE_DbSafetyLevelIsFixed(level) (level&SQLITE_SAFETYLEVEL_FIXED)
|
||||
|
||||
/*
|
||||
** Each database file to be accessed by the system is an instance
|
||||
@@ -3240,4 +3250,29 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
|
||||
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
|
||||
#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
|
||||
|
||||
|
||||
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
|
||||
|
||||
/*
|
||||
** An instance of the following structure is used to hold the process ID
|
||||
** and return-by-reference lockstate value. The SQLITE_FCNTL_LOCKSTATE_PID
|
||||
** requires the 4th argument to sqlite3_file_control to be a pointer to an
|
||||
** instance of LockstatePID initialized with a LockstatePID.pid value equal
|
||||
** to a process ID to be tested, or the special value SQLITE_LOCKSTATE_ANYPID
|
||||
** The Lockstate.state value is always set to one of the following values
|
||||
** when sqlite3_file_control returns:
|
||||
**
|
||||
** SQLITE_LOCKSTATE_OFF no active sqlite file locks match the specified pid
|
||||
** SQLITE_LOCKSTATE_ON active sqlite file locks match the specified pid
|
||||
** SQLITE_LOCKSTATE_NOTADB path points to a file that is not an sqlite db file
|
||||
** SQLITE_LOCKSTATE_ERROR path was not vaild or was unreadable
|
||||
*/
|
||||
typedef struct LockstatePID LockstatePID;
|
||||
struct LockstatePID {
|
||||
pid_t pid; /* Process ID to test */
|
||||
int state; /* The state of the lock (return value) */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITEINT_H_ */
|
||||
|
||||
+229
@@ -3408,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
|
||||
*/
|
||||
@@ -4950,6 +4968,87 @@ static int file_control_lasterrno_test(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* From sqlite3_priavet.h */
|
||||
# ifndef SQLITE_TRUNCATE_DATABASE
|
||||
# define SQLITE_TRUNCATE_DATABASE 101
|
||||
# endif
|
||||
# ifndef SQLITE_REPLACE_DATABASE
|
||||
# define SQLITE_REPLACE_DATABASE 102
|
||||
# endif
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_truncate_test DB
|
||||
**
|
||||
** This TCL command runs the sqlite3_file_control interface and
|
||||
** verifies correct operation of the SQLITE_TRUNCATE_DATABASE verb.
|
||||
*/
|
||||
static int file_control_truncate_test(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
int flags;
|
||||
int rc;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " DB FLAGS", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &flags) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_file_control(db, NULL, SQLITE_TRUNCATE_DATABASE, &flags);
|
||||
if( rc ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_replace_test DB
|
||||
**
|
||||
** This TCL command runs the sqlite3_file_control interface and
|
||||
** verifies correct operation of the SQLITE_REPLACE_DATABASE verb.
|
||||
*/
|
||||
static int file_control_replace_test(
|
||||
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 */
|
||||
){
|
||||
int iArg = 0;
|
||||
sqlite3 *src_db;
|
||||
sqlite3 *dst_db;
|
||||
int rc;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " DST_DB SRC_DB", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &dst_db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[2]), &src_db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_file_control(dst_db, NULL, SQLITE_REPLACE_DATABASE, src_db);
|
||||
if( rc ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_chunksize_test DB DBNAME SIZE
|
||||
**
|
||||
@@ -5096,6 +5195,128 @@ 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 */
|
||||
){
|
||||
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 */
|
||||
){
|
||||
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: file_control_persist_wal DB PERSIST-FLAG
|
||||
**
|
||||
** This TCL command runs the sqlite3_file_control interface with
|
||||
** the SQLITE_FCNTL_PERSIST_WAL opcode.
|
||||
*/
|
||||
static int file_control_persist_wal(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
int bPersist;
|
||||
char z[100];
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
|
||||
rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
|
||||
sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
|
||||
Tcl_AppendResult(interp, z, (char*)0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** tclcmd: sqlite3_vfs_list
|
||||
@@ -5713,6 +5934,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 },
|
||||
@@ -5801,10 +6023,17 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "file_control_test", file_control_test, 0 },
|
||||
{ "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
|
||||
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
|
||||
#ifdef __APPLE__
|
||||
{ "file_control_truncate_test", file_control_truncate_test, 0 },
|
||||
{ "file_control_replace_test", file_control_replace_test, 0 },
|
||||
#endif
|
||||
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
|
||||
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
||||
{ "file_control_persist_wal", file_control_persist_wal, 0 },
|
||||
{ "sqlite3_vfs_list", vfs_list, 0 },
|
||||
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
|
||||
{ "path_is_local", path_is_local, 0 },
|
||||
{ "path_is_dos", path_is_dos, 0 },
|
||||
|
||||
/* Functions from os.h */
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "tcl.h"
|
||||
#include <sqlite3.h>
|
||||
#include "sqlite3.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* These functions are implemented in test1.c. */
|
||||
|
||||
+27
-1
@@ -435,7 +435,17 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
|
||||
#else
|
||||
Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","0",TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#if SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
Tcl_SetVar2(interp,"sqlite_options","default_ckptfullfsync","1",TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp,"sqlite_options","default_ckptfullfsync","0",TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_WAL_SAFETYLEVEL
|
||||
Tcl_SetVar2(interp,"sqlite_options","default_wal_safetylevel",
|
||||
STRINGVALUE(SQLITE_DEFAULT_WAL_SAFETYLEVEL),TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp,"sqlite_options","default_wal_safetylevel","0",TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
|
||||
@@ -548,6 +558,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
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library.
|
||||
*/
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/* Solely for the UNUSED_PARAMETER() macro. */
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
** sqlite3demo_superunlock()
|
||||
*/
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include "sqlite3.h"
|
||||
#include <string.h> /* memset(), strlen() */
|
||||
#include <assert.h> /* assert() */
|
||||
|
||||
@@ -148,7 +148,7 @@ static int superlockWalLock(
|
||||
** this function must have been obtained from a successful call to
|
||||
** sqlite3demo_superlock().
|
||||
*/
|
||||
void sqlite3demo_superunlock(void *pLock){
|
||||
static void sqlite3demo_superunlock(void *pLock){
|
||||
Superlock *p = (Superlock *)pLock;
|
||||
if( p->bWal ){
|
||||
int rc; /* Return code */
|
||||
@@ -179,9 +179,10 @@ void sqlite3demo_superunlock(void *pLock){
|
||||
** until either the lock can be obtained or the busy-handler function returns
|
||||
** 0 (indicating "give up").
|
||||
*/
|
||||
int sqlite3demo_superlock(
|
||||
static int sqlite3demo_superlock(
|
||||
const char *zPath, /* Path to database file to lock */
|
||||
const char *zVfs, /* VFS to use to access database file */
|
||||
int flags, /* Additional flags to pass to sqlite3_open_v2 */
|
||||
int (*xBusy)(void*,int), /* Busy handler callback */
|
||||
void *pBusyArg, /* Context arg for busy handler */
|
||||
void **ppLock /* OUT: Context to pass to superunlock() */
|
||||
@@ -196,7 +197,7 @@ int sqlite3demo_superlock(
|
||||
|
||||
/* Open a database handle on the file to superlock. */
|
||||
rc = sqlite3_open_v2(
|
||||
zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs
|
||||
zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|flags, zVfs
|
||||
);
|
||||
|
||||
/* Install a busy-handler and execute a BEGIN EXCLUSIVE. If this is not
|
||||
@@ -331,7 +332,7 @@ static int superlock_cmd(
|
||||
xBusy = superlock_busy;
|
||||
}
|
||||
|
||||
rc = sqlite3demo_superlock(zPath, zVfs, xBusy, &busy, &pLock);
|
||||
rc = sqlite3demo_superlock(zPath, zVfs, 0, xBusy, &busy, &pLock);
|
||||
assert( rc==SQLITE_OK || pLock==0 );
|
||||
assert( rc!=SQLITE_OK || pLock!=0 );
|
||||
|
||||
|
||||
+1
-1
@@ -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
@@ -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);
|
||||
sqlite3VdbeRewind(v);
|
||||
@@ -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++){
|
||||
@@ -1070,11 +1087,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);
|
||||
@@ -1083,11 +1106,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);
|
||||
@@ -1098,6 +1127,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);
|
||||
@@ -1111,6 +1143,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
|
||||
@@ -1121,6 +1156,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 */
|
||||
@@ -1144,6 +1182,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;
|
||||
@@ -1158,6 +1199,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);
|
||||
|
||||
+5
-1
@@ -1138,7 +1138,7 @@ int sqlite3VdbeList(
|
||||
sqlite3 *db = p->db; /* The database connection */
|
||||
int i; /* Loop counter */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */
|
||||
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
|
||||
|
||||
assert( p->explain );
|
||||
assert( p->magic==VDBE_MAGIC_RUN );
|
||||
@@ -1149,6 +1149,7 @@ int sqlite3VdbeList(
|
||||
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
|
||||
*/
|
||||
releaseMemArray(pMem, 8);
|
||||
p->pResultSet = 0;
|
||||
|
||||
if( p->rc==SQLITE_NOMEM ){
|
||||
/* This happens if a malloc() inside a call to sqlite3_column_text() or
|
||||
@@ -1303,6 +1304,7 @@ int sqlite3VdbeList(
|
||||
}
|
||||
|
||||
p->nResColumn = 8 - 4*(p->explain-1);
|
||||
p->pResultSet = &p->aMem[1];
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_ROW;
|
||||
}
|
||||
@@ -1506,6 +1508,8 @@ void sqlite3VdbeMakeReady(
|
||||
zCsr += (zCsr - (u8*)0)&7;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
||||
|
||||
p->expired = 0;
|
||||
|
||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
||||
** passes. On the first pass, we try to reuse unused space at the
|
||||
** end of the opcode array. If we are unable to satisfy all memory
|
||||
|
||||
+4
-1
@@ -83,9 +83,12 @@ char *sqlite3VdbeExpandSql(
|
||||
if( db->vdbeExecCnt>1 ){
|
||||
while( *zRawSql ){
|
||||
const char *zStart = zRawSql;
|
||||
sqlite_int64 iStart = SQLITE_PTR_TO_INT(zRawSql);
|
||||
sqlite_int64 iCurrent;
|
||||
while( *(zRawSql++)!='\n' && *zRawSql );
|
||||
sqlite3StrAccumAppend(&out, "-- ", 3);
|
||||
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
|
||||
iCurrent = SQLITE_PTR_TO_INT(zRawSql);
|
||||
sqlite3StrAccumAppend(&out, zStart, (int)(iCurrent-iStart));
|
||||
}
|
||||
}else{
|
||||
while( zRawSql[0] ){
|
||||
|
||||
@@ -1247,11 +1247,12 @@ int sqlite3WalOpen(
|
||||
const char *zWalName, /* Name of the WAL file */
|
||||
int bNoShm, /* True to run in heap-memory mode */
|
||||
i64 mxWalSize, /* Truncate WAL to this size on reset */
|
||||
int flags, /* VFS file protection flags */
|
||||
Wal **ppWal /* OUT: Allocated Wal handle */
|
||||
){
|
||||
int rc; /* Return Code */
|
||||
Wal *pRet; /* Object to allocate and return */
|
||||
int flags; /* Flags passed to OsOpen() */
|
||||
int vfsFlags; /* Flags passed to OsOpen() */
|
||||
|
||||
assert( zWalName && zWalName[0] );
|
||||
assert( pDbFd );
|
||||
@@ -1284,9 +1285,13 @@ int sqlite3WalOpen(
|
||||
pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
|
||||
|
||||
/* Open file handle on the write-ahead log file. */
|
||||
flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
|
||||
rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
|
||||
if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
|
||||
if( flags&SQLITE_OPEN_READONLY ){
|
||||
vfsFlags = flags | SQLITE_OPEN_WAL;
|
||||
} else {
|
||||
vfsFlags = flags | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
|
||||
}
|
||||
rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, vfsFlags, &vfsFlags);
|
||||
if( rc==SQLITE_OK && vfsFlags&SQLITE_OPEN_READONLY ){
|
||||
pRet->readOnly = WAL_RDONLY;
|
||||
}
|
||||
|
||||
@@ -1804,13 +1809,15 @@ int sqlite3WalClose(
|
||||
*/
|
||||
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
|
||||
if( rc==SQLITE_OK ){
|
||||
int bPersistWal = -1;
|
||||
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
|
||||
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
|
||||
}
|
||||
rc = sqlite3WalCheckpoint(
|
||||
pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
|
||||
if( rc==SQLITE_OK && bPersistWal!=1 ){
|
||||
isDelete = 1;
|
||||
}
|
||||
}
|
||||
@@ -1863,6 +1870,9 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
|
||||
** reordering the reads and writes.
|
||||
*/
|
||||
aHdr = walIndexHdr(pWal);
|
||||
if( aHdr==NULL ){
|
||||
return 1; /* Shouldn't be getting NULL from walIndexHdr, but we are */
|
||||
}
|
||||
memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
|
||||
walShmBarrier(pWal);
|
||||
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
|
||||
@@ -2047,7 +2057,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
*/
|
||||
if( cnt>5 ){
|
||||
int nDelay = 1; /* Pause time in microseconds */
|
||||
if( cnt>100 ){
|
||||
if( cnt>500 ){
|
||||
VVA_ONLY( pWal->lockError = 1; )
|
||||
return SQLITE_PROTOCOL;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
typedef struct Wal Wal;
|
||||
|
||||
/* Open and close a connection to a write-ahead log. */
|
||||
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
|
||||
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, int, Wal**);
|
||||
int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
|
||||
|
||||
/* Set the limiting size of a WAL file. */
|
||||
|
||||
+18
-17
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -76,10 +76,12 @@ set skipwaltests [expr {
|
||||
[permutation]=="journaltest" || [permutation]=="inmemory_journal"
|
||||
}]
|
||||
ifcapable !wal { set skipwaltests 1 }
|
||||
if {![wal_is_ok]} { set skipwaltests 1 }
|
||||
|
||||
if {!$skipwaltests} {
|
||||
db close
|
||||
file delete -force test.db
|
||||
if {[forced_proxy_locking]} { file delete -force .test.db-conch }
|
||||
sqlite3 db test.db
|
||||
file_control_chunksize_test db main [expr 32*1024]
|
||||
|
||||
|
||||
+11
-6
@@ -260,12 +260,17 @@ proc access_method {args} {
|
||||
return ""
|
||||
}
|
||||
|
||||
do_test incrblob3-7.2 {
|
||||
sqlite3 db test.db
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
list [catch {db incrblob blobs v 1} msg] $msg
|
||||
} {1 {database schema has changed}}
|
||||
db close
|
||||
#set sqlite_os_trace 1
|
||||
# AFP asserts because the "db incrblob blobs v 1" clears the file locks and the unlock fails (HFS doesn't care about a failed unlock)
|
||||
if {[path_is_local "."]} {
|
||||
|
||||
do_test incrblob3-7.2 {
|
||||
sqlite3 db test.db
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
list [catch {db incrblob blobs v 1} msg] $msg
|
||||
} {1 {database schema has changed}}
|
||||
db close
|
||||
}
|
||||
tvfs delete
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
# If this build of the library does not support auto-vacuum, omit this
|
||||
# whole file.
|
||||
@@ -188,10 +189,12 @@ ifcapable wal {
|
||||
execsql {
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA incremental_vacuum(1);
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
} {wal}
|
||||
do_test 4.2.1 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
file size test.db-wal
|
||||
} {1640}
|
||||
} [wal_file_size [wal_frames db 2 1] 512]
|
||||
|
||||
do_test 4.3 {
|
||||
db close
|
||||
@@ -205,7 +208,7 @@ ifcapable wal {
|
||||
if {$newsz>$maxsz} {set maxsz $newsz}
|
||||
}
|
||||
set maxsz
|
||||
} {2176}
|
||||
} [wal_file_size [wal_frames db 3 1] 512]
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -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
@@ -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
@@ -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
|
||||
} {}
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -14,6 +14,12 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# AFP doesn't like multiplex db tests
|
||||
if { ![path_is_local "."] } {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ]
|
||||
set g_max_chunks 32
|
||||
|
||||
|
||||
+13
-5
@@ -534,6 +534,8 @@ proc copy_on_mj_delete {method filename args} {
|
||||
}
|
||||
|
||||
set pwd [pwd]
|
||||
if {![forced_proxy_locking]} {
|
||||
# proxy locking uses can't deal with auto proxy file paths longer than MAXPATHLEN
|
||||
foreach {tn1 tcl} {
|
||||
1 { set prefix "test.db" }
|
||||
2 {
|
||||
@@ -665,6 +667,7 @@ foreach {tn1 tcl} {
|
||||
db close
|
||||
tv delete
|
||||
file delete -force $dirname
|
||||
}
|
||||
|
||||
|
||||
# Set up a VFS to make a copy of the file-system just before deleting a
|
||||
@@ -2005,18 +2008,23 @@ do_test pager1-22.2.1 {
|
||||
tv filter xSync
|
||||
tv script xSyncCb
|
||||
proc xSyncCb {args} {incr ::synccount}
|
||||
set ::synccount 0
|
||||
sqlite3 db test.db
|
||||
|
||||
# Switch the db to WAL mode. And then execute a SELECT to make sure
|
||||
# that the WAL file is open. Note that this may change the synchronous
|
||||
# setting if DEFAULT_WAL_SAFETYLEVEL is defined.
|
||||
execsql { PRAGMA journal_mode = WAL ; SELECT * FROM ko }
|
||||
|
||||
# Set synchronous=OFF. Insert some data and run a checkpoint. Since
|
||||
# sync=off, this should not cause any calls to the xSync() method.
|
||||
set ::synccount 0
|
||||
execsql {
|
||||
PRAGMA synchronous = off;
|
||||
PRAGMA journal_mode = WAL;
|
||||
INSERT INTO ko DEFAULT VALUES;
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
set synccount
|
||||
} {0}
|
||||
db close
|
||||
tv delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Tests for changing journal mode.
|
||||
|
||||
@@ -1060,6 +1060,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
@@ -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 lpp5d [exec mktemp -d -t "proxy5"]
|
||||
set lpp5 $lpp5d/sub/dir/lock
|
||||
db close
|
||||
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 $lpp5d
|
||||
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 $lpp5d
|
||||
close [open "$lpp5d" 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
|
||||
db close
|
||||
file delete -force $lpp5d
|
||||
set lpp6 [exec mktemp -d -t "proxy6"]/./././////./proxytest/../proxytest/sub/dir/lock
|
||||
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 $lpp5d
|
||||
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 $lpp5d
|
||||
file mkdir $lpp5d
|
||||
file attributes $lpp5d -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 $lpp5d -permission 0777
|
||||
file delete -force $lpp5d
|
||||
|
||||
set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy
|
||||
set sqlite_hostid_num 0
|
||||
}
|
||||
|
||||
+1
-5
@@ -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
@@ -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
|
||||
|
||||
+10
-1
@@ -13,6 +13,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
set testprefix superlock
|
||||
|
||||
@@ -52,6 +53,12 @@ do_test 1.2 { sqlite3demo_superlock unlock test.db } {unlock}
|
||||
do_catchsql_test 1.3 { SELECT * FROM t1 } {1 {database is locked}}
|
||||
do_test 1.4 { unlock } {}
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
if { ![wal_is_ok] } {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
PRAGMA journal_mode = WAL;
|
||||
@@ -71,7 +78,9 @@ do_catchsql_test 3.4 { INSERT INTO t1 VALUES(5, 6)} {1 {database is locked}}
|
||||
do_catchsql_test 3.5 { PRAGMA wal_checkpoint } {0 {1 -1 -1}}
|
||||
do_test 3.6 { unlock } {}
|
||||
|
||||
do_execsql_test 4.1 { PRAGMA wal_checkpoint } {0 2 2}
|
||||
do_execsql_test 4.1 { PRAGMA wal_checkpoint } [
|
||||
list 0 [wal_frames db 1 1] [wal_frames db 1 1]
|
||||
]
|
||||
|
||||
do_test 4.2 { sqlite3demo_superlock unlock test.db } {unlock}
|
||||
do_catchsql_test 4.3 { SELECT * FROM t1 } {1 {database is locked}}
|
||||
|
||||
+7
-2
@@ -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
|
||||
|
||||
+46
-4
@@ -242,6 +242,23 @@ if {[info exists cmdlinearg]==0} {
|
||||
#
|
||||
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
|
||||
|
||||
proc forced_proxy_locking {} {
|
||||
if $::sqlite_options(lock_proxy_pragmas)&&$::sqlite_options(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
|
||||
}
|
||||
|
||||
|
||||
# Create a test database
|
||||
#
|
||||
proc reset_db {} {
|
||||
@@ -249,6 +266,14 @@ proc reset_db {} {
|
||||
file delete -force test.db
|
||||
file delete -force test.db-journal
|
||||
file delete -force test.db-wal
|
||||
if {[forced_proxy_locking]} {
|
||||
sqlite3 db ./test.db
|
||||
set lock_proxy_path [db eval "PRAGMA lock_proxy_file;"]
|
||||
catch {db close}
|
||||
# puts "deleting $lock_proxy_path"
|
||||
file delete -force $lock_proxy_path
|
||||
file delete -force test.db
|
||||
}
|
||||
sqlite3 db ./test.db
|
||||
set ::DB [sqlite3_connection_pointer db]
|
||||
if {[info exists ::SETUP_SQL]} {
|
||||
@@ -621,11 +646,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}]
|
||||
}
|
||||
@@ -1330,6 +1359,19 @@ proc presql {} {
|
||||
set presql
|
||||
}
|
||||
|
||||
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
@@ -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
|
||||
|
||||
+25
-17
@@ -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 }
|
||||
@@ -544,8 +548,9 @@ do_multiclient_test tn {
|
||||
sql2 { BEGIN; SELECT * FROM t1 }
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
do_test wal-10.$tn.12 {
|
||||
catchsql { PRAGMA wal_checkpoint }
|
||||
} {0 {0 13 13}} ;# Reader no longer block checkpoints
|
||||
# Reader no longer blocks checkpoint:
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} [list 0 [wal_frames db 8 5] [wal_frames db 8 5]]
|
||||
do_test wal-10.$tn.13 {
|
||||
execsql { INSERT INTO t1 VALUES(11, 12) }
|
||||
sql2 {SELECT * FROM t1}
|
||||
@@ -554,8 +559,8 @@ do_multiclient_test tn {
|
||||
# Writers do not block checkpoints any more either.
|
||||
#
|
||||
do_test wal-10.$tn.14 {
|
||||
catchsql { PRAGMA wal_checkpoint }
|
||||
} {0 {0 15 13}}
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} [list 0 [wal_frames db 9 6] [wal_frames db 8 5]]
|
||||
|
||||
# The following series of test cases used to verify another blocking
|
||||
# case in WAL - a case which no longer blocks.
|
||||
@@ -564,11 +569,11 @@ do_multiclient_test tn {
|
||||
sql2 { COMMIT; BEGIN; SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12}
|
||||
do_test wal-10.$tn.16 {
|
||||
catchsql { PRAGMA wal_checkpoint }
|
||||
} {0 {0 15 15}}
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} [list 0 [wal_frames db 9 6] [wal_frames db 9 6]]
|
||||
do_test wal-10.$tn.17 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 15 15}
|
||||
} [list 0 [wal_frames db 9 6] [wal_frames db 9 6]]
|
||||
do_test wal-10.$tn.18 {
|
||||
sql3 { BEGIN; SELECT * FROM t1 }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12}
|
||||
@@ -591,13 +596,13 @@ do_multiclient_test tn {
|
||||
#
|
||||
do_test wal-10.$tn.23 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 17 17}
|
||||
} [list 0 [wal_frames db 10 7] [wal_frames db 10 7]]
|
||||
do_test wal-10.$tn.24 {
|
||||
sql2 { BEGIN; SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
|
||||
do_test wal-10.$tn.25 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 17 17}
|
||||
} [list 0 [wal_frames db 10 7] [wal_frames db 10 7]]
|
||||
do_test wal-10.$tn.26 {
|
||||
catchsql { INSERT INTO t1 VALUES(15, 16) }
|
||||
} {0 {}}
|
||||
@@ -613,12 +618,12 @@ do_multiclient_test tn {
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}
|
||||
do_test wal-10.$tn.29 {
|
||||
execsql { INSERT INTO t1 VALUES(19, 20) }
|
||||
catchsql { PRAGMA wal_checkpoint }
|
||||
} {0 {0 6 0}}
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} [list 0 [wal_frames db 4 2] 0]
|
||||
do_test wal-10.$tn.30 {
|
||||
code3 { sqlite3_finalize $::STMT }
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 6 0}
|
||||
} [list 0 [wal_frames db 4 2] 0]
|
||||
|
||||
# At one point, if a reader failed to upgrade to a writer because it
|
||||
# was reading an old snapshot, the write-locks were not being released.
|
||||
@@ -656,8 +661,8 @@ do_multiclient_test tn {
|
||||
}
|
||||
} {a b c d}
|
||||
do_test wal-10.$tn.36 {
|
||||
catchsql { PRAGMA wal_checkpoint }
|
||||
} {0 {0 16 16}}
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} [list 0 [wal_frames db 11 5] [wal_frames db 11 5]]
|
||||
do_test wal-10.$tn.36 {
|
||||
sql3 { INSERT INTO t1 VALUES('e', 'f') }
|
||||
sql2 { SELECT * FROM t1 }
|
||||
@@ -665,7 +670,7 @@ do_multiclient_test tn {
|
||||
do_test wal-10.$tn.37 {
|
||||
sql2 COMMIT
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 18 18}
|
||||
} [list 0 [wal_frames db 13 5] [wal_frames db 13 5]]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -1053,9 +1058,11 @@ foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
|
||||
PRAGMA aux.auto_vacuum = 0;
|
||||
PRAGMA main.journal_mode = WAL;
|
||||
PRAGMA aux.journal_mode = WAL;
|
||||
SELECT count(*) FROM main.sqlite_master, aux.sqlite_master;
|
||||
PRAGMA synchronous = NORMAL;
|
||||
PRAGMA aux.synchronous = FULL;
|
||||
}
|
||||
} {wal wal}
|
||||
} {wal wal 0}
|
||||
|
||||
do_test wal-16.$tn.2 {
|
||||
execsql {
|
||||
@@ -1125,6 +1132,7 @@ foreach {tn sectorsize logsize} "
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA page_size = 512;
|
||||
PRAGMA journal_mode = WAL;
|
||||
SELECT * FROM sqlite_master;
|
||||
PRAGMA synchronous = FULL;
|
||||
}
|
||||
execsql {
|
||||
@@ -1552,7 +1560,7 @@ ifcapable autovacuum {
|
||||
} [expr 3 * 1024]
|
||||
do_test 24.5 {
|
||||
file size test.db-wal
|
||||
} 2128
|
||||
} [wal_file_size [wal_frames db 1 1] 1024]
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
+74
-26
@@ -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} {
|
||||
@@ -352,16 +356,20 @@ file delete -force test.db test.db-wal test.db-journal
|
||||
# Test that a database connection using a VFS that does not support the
|
||||
# xShmXXX interfaces cannot open a WAL database.
|
||||
#
|
||||
do_test wal2-4.1 {
|
||||
do_test wal2-4.1.1 {
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE data(x);
|
||||
INSERT INTO data VALUES('need xShmOpen to see this');
|
||||
}
|
||||
} {wal}
|
||||
do_test wal2-4.1.2 {
|
||||
execsql {
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
} {wal 0 5 5}
|
||||
} [list 0 [wal_frames db 3 2] [wal_frames db 3 2]]
|
||||
do_test wal2-4.2 {
|
||||
db close
|
||||
testvfs tvfs -noshm 1
|
||||
@@ -718,18 +726,22 @@ foreach {tn sql res expected_locks} {
|
||||
db close
|
||||
tvfs delete
|
||||
|
||||
do_test wal2-6.5.1 {
|
||||
do_test wal2-6.5.1.1 {
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA journal_mode = wal;
|
||||
PRAGMA locking_mode = exclusive;
|
||||
CREATE TABLE t2(a, b);
|
||||
}
|
||||
} {wal exclusive}
|
||||
do_test wal2-6.5.1.2 {
|
||||
execsql {
|
||||
PRAGMA wal_checkpoint;
|
||||
INSERT INTO t2 VALUES('I', 'II');
|
||||
PRAGMA journal_mode;
|
||||
}
|
||||
} {wal exclusive 0 3 3 wal}
|
||||
} [list 0 [wal_frames db 2 1] [wal_frames db 2 1] wal]
|
||||
do_test wal2-6.5.2 {
|
||||
execsql {
|
||||
PRAGMA locking_mode = normal;
|
||||
@@ -740,7 +752,7 @@ do_test wal2-6.5.2 {
|
||||
} {normal exclusive I II III IV}
|
||||
do_test wal2-6.5.3 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 4 4}
|
||||
} [list 0 [wal_frames db 2 2] [wal_frames db 2 2]]
|
||||
db close
|
||||
|
||||
proc lock_control {method filename handle spec} {
|
||||
@@ -1174,22 +1186,34 @@ if {$::tcl_platform(platform) == "unix"} {
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that "PRAGMA checkpoint_fullsync" appears to be working.
|
||||
#
|
||||
foreach {tn sql reslist} {
|
||||
1 { } {8 0 3 0 5 0}
|
||||
2 { PRAGMA checkpoint_fullfsync = 1 } {8 4 3 2 5 2}
|
||||
3 { PRAGMA checkpoint_fullfsync = 0 } {8 0 3 0 5 0}
|
||||
foreach {tn sql} {
|
||||
1 { }
|
||||
2 { PRAGMA checkpoint_fullfsync = 1 }
|
||||
3 { PRAGMA checkpoint_fullfsync = 0 }
|
||||
} {
|
||||
faultsim_delete_and_reopen
|
||||
|
||||
execsql {PRAGMA auto_vacuum = 0}
|
||||
execsql $sql
|
||||
do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal}
|
||||
do_execsql_test wal2-14.$tn.1 {
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA wal_autocheckpoint = 10;
|
||||
} {wal 10}
|
||||
|
||||
unset -nocomplain res
|
||||
set res(0,1) {5 0 2 0 2 0} ;# checkpoint_fullfsync=0 sync=NORMAL
|
||||
set res(0,2) {8 0 3 0 5 0} ;# checkpoint_fullfsync=0 sync=FULL
|
||||
set res(1,1) {5 4 2 2 2 2} ;# checkpoint_fullfsync=1 sync=NORMAL
|
||||
set res(1,2) {8 4 3 2 5 2} ;# checkpoint_fullfsync=1 sync=FULL
|
||||
|
||||
set key1 [db one {PRAGMA checkpoint_fullfsync}]
|
||||
set key2 [db one {PRAGMA main.synchronous}]
|
||||
set reslist $res($key1,$key2)
|
||||
|
||||
set sqlite_sync_count 0
|
||||
set sqlite_fullsync_count 0
|
||||
|
||||
do_execsql_test wal2-14.$tn.2 {
|
||||
PRAGMA wal_autocheckpoint = 10;
|
||||
CREATE TABLE t1(a, b); -- 2 wal syncs
|
||||
INSERT INTO t1 VALUES(1, 2); -- 1 wal sync
|
||||
PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync
|
||||
@@ -1198,7 +1222,9 @@ foreach {tn sql reslist} {
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
COMMIT; -- 1 wal sync
|
||||
PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync
|
||||
} {10 0 5 5 0 2 2}
|
||||
} [list 0 [wal_frames db 3 2] [wal_frames db 3 2] \
|
||||
0 [wal_frames db 1 1] [wal_frames db 1 1] \
|
||||
]
|
||||
|
||||
do_test wal2-14.$tn.3 {
|
||||
cond_incr_sync_count 1
|
||||
@@ -1232,22 +1258,22 @@ catch { db close }
|
||||
# PRAGMA fullfsync
|
||||
# PRAGMA synchronous
|
||||
#
|
||||
foreach {tn settings commit_sync ckpt_sync} {
|
||||
1 {0 0 off} {0 0} {0 0}
|
||||
2 {0 0 normal} {0 0} {2 0}
|
||||
3 {0 0 full} {1 0} {2 0}
|
||||
foreach {tn settings} {
|
||||
1 {0 0 off}
|
||||
2 {0 0 normal}
|
||||
3 {0 0 full}
|
||||
|
||||
4 {0 1 off} {0 0} {0 0}
|
||||
5 {0 1 normal} {0 0} {0 2}
|
||||
6 {0 1 full} {0 1} {0 2}
|
||||
4 {0 1 off}
|
||||
5 {0 1 normal}
|
||||
6 {0 1 full}
|
||||
|
||||
7 {1 0 off} {0 0} {0 0}
|
||||
8 {1 0 normal} {0 0} {0 2}
|
||||
9 {1 0 full} {1 0} {0 2}
|
||||
7 {1 0 off}
|
||||
8 {1 0 normal}
|
||||
9 {1 0 full}
|
||||
|
||||
10 {1 1 off} {0 0} {0 0}
|
||||
11 {1 1 normal} {0 0} {0 2}
|
||||
12 {1 1 full} {0 1} {0 2}
|
||||
10 {1 1 off}
|
||||
11 {1 1 normal}
|
||||
12 {1 1 full}
|
||||
} {
|
||||
forcedelete test.db
|
||||
|
||||
@@ -1265,7 +1291,29 @@ foreach {tn settings commit_sync ckpt_sync} {
|
||||
PRAGMA checkpoint_fullfsync = [lindex $settings 0];
|
||||
PRAGMA fullfsync = [lindex $settings 1];
|
||||
PRAGMA synchronous = [lindex $settings 2];
|
||||
" {wal}
|
||||
SELECT count(*) FROM sqlite_master;
|
||||
" {wal 1}
|
||||
|
||||
unset -nocomplain res
|
||||
set res(0,0,0) {{0 0} {0 0}}
|
||||
set res(0,0,1) {{0 0} {2 0}}
|
||||
set res(0,0,2) {{1 0} {2 0}}
|
||||
set res(0,1,0) {{0 0} {0 0}}
|
||||
set res(0,1,1) {{0 0} {0 2}}
|
||||
set res(0,1,2) {{0 1} {0 2}}
|
||||
set res(1,0,0) {{0 0} {0 0}}
|
||||
set res(1,0,1) {{0 0} {0 2}}
|
||||
set res(1,0,2) {{1 0} {0 2}}
|
||||
set res(1,1,0) {{0 0} {0 0}}
|
||||
set res(1,1,1) {{0 0} {0 2}}
|
||||
set res(1,1,2) {{0 1} {0 2}}
|
||||
|
||||
set key1 [db one {PRAGMA checkpoint_fullfsync}]
|
||||
set key2 [db one {PRAGMA fullfsync}]
|
||||
set key3 [db one {PRAGMA synchronous}]
|
||||
|
||||
set commit_sync [lindex $res($key1,$key2,$key3) 0]
|
||||
set ckpt_sync [lindex $res($key1,$key2,$key3) 1]
|
||||
|
||||
do_test 15.$tn.2 {
|
||||
set sync(normal) 0
|
||||
|
||||
+25
-7
@@ -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} {
|
||||
@@ -203,6 +207,16 @@ foreach {tn syncmode synccount} {
|
||||
{test.db-wal normal test.db-wal normal test.db-wal normal test.db normal}
|
||||
} {
|
||||
|
||||
if { $::sqlite_options(default_ckptfullfsync) } {
|
||||
# checkpoint_fullfsync on by default
|
||||
if { $tn == 2} {
|
||||
set synccount {test.db-wal full test.db full}
|
||||
}
|
||||
if { $tn == 3} {
|
||||
set synccount {test.db-wal normal test.db-wal normal test.db-wal full test.db full}
|
||||
}
|
||||
}
|
||||
|
||||
proc sync_counter {args} {
|
||||
foreach {method filename id flags} $args break
|
||||
lappend ::syncs [file tail $filename] $flags
|
||||
@@ -215,8 +229,9 @@ foreach {tn syncmode synccount} {
|
||||
T script sync_counter
|
||||
sqlite3 db test.db -vfs T
|
||||
|
||||
execsql "PRAGMA synchronous = $syncmode"
|
||||
execsql { PRAGMA journal_mode = WAL }
|
||||
execsql { SELECT * FROM sqlite_master }
|
||||
execsql "PRAGMA synchronous = $syncmode"
|
||||
|
||||
set ::syncs [list]
|
||||
T filter xSync
|
||||
@@ -428,7 +443,7 @@ do_test wal3-6.1.2 {
|
||||
} {o t t f}
|
||||
do_test wal3-6.1.3 {
|
||||
execsql { PRAGMA wal_checkpoint } db2
|
||||
} {0 7 7}
|
||||
} [list 0 [wal_frames db 4 3] [wal_frames db 4 3]]
|
||||
|
||||
# At this point the log file has been fully checkpointed. However,
|
||||
# connection [db3] holds a lock that prevents the log from being wrapped.
|
||||
@@ -517,7 +532,7 @@ proc lock_callback {method file handle spec} {
|
||||
}
|
||||
do_test wal3-6.2.2 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
} {0 7 7}
|
||||
} [list 0 [wal_frames db 4 3] [wal_frames db 4 3]]
|
||||
do_test wal3-6.2.3 {
|
||||
set ::R
|
||||
} {h h l b}
|
||||
@@ -614,8 +629,8 @@ T delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_test wal3-8.1 {
|
||||
file delete -force test.db test.db-journal test.db wal
|
||||
do_test wal3-8.1.1 {
|
||||
file delete -force test.db test.db-journal test.db wal .test.db-conch
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
@@ -625,9 +640,12 @@ do_test wal3-8.1 {
|
||||
INSERT INTO b VALUES('Tehran');
|
||||
INSERT INTO b VALUES('Qom');
|
||||
INSERT INTO b VALUES('Markazi');
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
} {wal 0 9 9}
|
||||
} {wal}
|
||||
|
||||
do_test wal3.8.1.2 {
|
||||
execsql { PRAGMA wal_checkpoint; }
|
||||
} [list 0 [wal_frames db 5 4] [wal_frames db 5 4]]
|
||||
do_test wal3-8.2 {
|
||||
execsql { SELECT * FROM b }
|
||||
} {Tehran Qom Markazi}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+37
-10
@@ -197,9 +197,15 @@ foreach {testprefix do_wal_checkpoint} {
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
}
|
||||
} {}
|
||||
do_test 2.2.$tn.2 { file_page_counts } {1 5 1 5}
|
||||
do_test 2.1.$tn.3 { code1 { do_wal_checkpoint db } } {0 5 5}
|
||||
do_test 2.1.$tn.4 { file_page_counts } {2 5 2 5}
|
||||
do_test 2.2.$tn.2 { file_page_counts } [
|
||||
list 1 [wal_frames db 3 2] 1 [wal_frames db 3 2]
|
||||
]
|
||||
do_test 2.1.$tn.3 { code1 { do_wal_checkpoint db } } [
|
||||
list 0 [wal_frames db 3 2] [wal_frames db 3 2]
|
||||
]
|
||||
do_test 2.1.$tn.4 { file_page_counts } [
|
||||
list 2 [wal_frames db 3 2] 2 [wal_frames db 3 2]
|
||||
]
|
||||
}
|
||||
|
||||
do_multiclient_test tn {
|
||||
@@ -213,10 +219,16 @@ foreach {testprefix do_wal_checkpoint} {
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
}
|
||||
} {}
|
||||
do_test 2.2.$tn.2 { file_page_counts } {1 5 1 7}
|
||||
do_test 2.2.$tn.2 { file_page_counts } [
|
||||
list 1 [wal_frames db 3 2] 1 [wal_frames db 4 3]
|
||||
]
|
||||
do_test 2.2.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2}
|
||||
do_test 2.2.$tn.4 { code1 { do_wal_checkpoint db -mode restart } } {1 5 5}
|
||||
do_test 2.2.$tn.5 { file_page_counts } {2 5 2 7}
|
||||
do_test 2.2.$tn.4 { code1 { do_wal_checkpoint db -mode restart } } [
|
||||
list 1 [wal_frames db 3 2] [wal_frames db 3 2]
|
||||
]
|
||||
do_test 2.2.$tn.5 { file_page_counts } [
|
||||
list 2 [wal_frames db 3 2] 2 [wal_frames db 4 3]
|
||||
]
|
||||
}
|
||||
|
||||
do_multiclient_test tn {
|
||||
@@ -229,19 +241,27 @@ foreach {testprefix do_wal_checkpoint} {
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
}
|
||||
} {}
|
||||
do_test 2.3.$tn.2 { file_page_counts } {1 5 1 5}
|
||||
do_test 2.3.$tn.2 { file_page_counts } [
|
||||
list 1 [wal_frames db 3 2] 1 [wal_frames db 3 2]
|
||||
]
|
||||
do_test 2.3.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2}
|
||||
do_test 2.3.$tn.4 { sql1 { INSERT INTO t1 VALUES(3, 4) } } {}
|
||||
do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {}
|
||||
do_test 2.3.$tn.6 { file_page_counts } {1 7 1 7}
|
||||
do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 7 5}
|
||||
do_test 2.3.$tn.6 { file_page_counts } [
|
||||
list 1 [wal_frames db 4 3] 1 [wal_frames db 4 3]
|
||||
]
|
||||
do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } [
|
||||
list 1 [wal_frames db 4 3] [wal_frames db 3 2]
|
||||
]
|
||||
if {$tcl_platform(platform) == "windows"} {
|
||||
# on unix, the size_hint is a no-op if no chunk size is set.
|
||||
# the windows implementation does not have a similar check,
|
||||
# and because of this, the db file size has an extra page.
|
||||
do_test 2.3.$tn.8 { file_page_counts } {2 7 2 7}
|
||||
} {
|
||||
do_test 2.3.$tn.8 { file_page_counts } {1 7 2 7}
|
||||
do_test 2.3.$tn.8 { file_page_counts } [
|
||||
list 1 [wal_frames db 4 3] 2 [wal_frames db 4 3]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +321,13 @@ foreach {testprefix do_wal_checkpoint} {
|
||||
sql3 { BEGIN; SELECT * FROM t1 }
|
||||
} {1 2}
|
||||
|
||||
# The value in ckpt_expected assumes that synchronous=FULL. If
|
||||
# synchronous=NORMAL, decrease the WAL size by 2 frames.
|
||||
if {$tn==1 && [db one {PRAGMA main.synchronous}] == 1} {
|
||||
lset ckpt_expected 1 [expr [lindex $ckpt_expected 1] - 2]
|
||||
lset ckpt_expected 2 [expr [lindex $ckpt_expected 2] - 2]
|
||||
}
|
||||
|
||||
do_test 2.4.$tn1.$tn.2 {
|
||||
code1 { db busy busyhandler }
|
||||
code1 { do_wal_checkpoint db -mode [string tolower $checkpoint] }
|
||||
|
||||
@@ -20,6 +20,8 @@ source $testdir/wal_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
if { ![wal_is_ok] } {finish_test ; return }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Changing to WAL mode in one connection forces the change in others.
|
||||
#
|
||||
|
||||
@@ -33,6 +33,20 @@ proc wal_cksum_intlist {ckv1 ckv2 intlist} {
|
||||
}
|
||||
}
|
||||
|
||||
# If the synchronous mode for the main database of db handle $db
|
||||
# is either OFF or NORMAL, return $nRight. Otherwise, if it is
|
||||
# FULL, return $nWrite+$nTrans.
|
||||
#
|
||||
proc wal_frames {db nWrite nTrans} {
|
||||
set nRet $nWrite
|
||||
switch -- [$db one {PRAGMA main.synchronous}] {
|
||||
0 { }
|
||||
1 { }
|
||||
default { incr nRet $nTrans }
|
||||
}
|
||||
set nRet
|
||||
}
|
||||
|
||||
|
||||
# This proc calculates checksums in the same way as those used by SQLite
|
||||
# in WAL files. If the $endian argument is "big", then checksums are
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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} {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ 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 }
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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} {
|
||||
|
||||
+23
-1
@@ -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
|
||||
@@ -45,7 +59,15 @@ do_test walmode-1.2 {
|
||||
file size test.db
|
||||
} {1024}
|
||||
|
||||
set expected_sync_count 3
|
||||
# Determine how many sync() calls to expect from the "journal_mode=WAL"
|
||||
# command above. Note that if DEFAULT_WAL_SAFETYLEVEL is defined, the
|
||||
# safety-level may have been modified while compiling the "journal_mode=WAL"
|
||||
# statement.
|
||||
switch -- [db eval {PRAGMA main.synchronous}] {
|
||||
0 { set expected_sync_count 0 }
|
||||
1 { set expected_sync_count 2 }
|
||||
default { set expected_sync_count 3 }
|
||||
}
|
||||
if {$::tcl_platform(platform)!="windows"} {
|
||||
ifcapable dirsync {
|
||||
incr expected_sync_count
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# 2011 July 26
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains tests for using WAL with persistent WAL file mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
set ::testprefix walpersist
|
||||
|
||||
do_test walpersist-1.0 {
|
||||
db eval {
|
||||
PRAGMA journal_mode=WAL;
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(randomblob(5000));
|
||||
}
|
||||
file exists test.db-wal
|
||||
} {1}
|
||||
do_test walpersist-1.1 {
|
||||
file exists test.db-shm
|
||||
} {1}
|
||||
do_test walpersist-1.2 {
|
||||
db close
|
||||
list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
|
||||
} {1 0 0}
|
||||
do_test walpersist-1.3 {
|
||||
sqlite3 db test.db
|
||||
db eval {SELECT length(a) FROM t1}
|
||||
} {5000}
|
||||
do_test walpersist-1.4 {
|
||||
list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
|
||||
} {1 1 1}
|
||||
do_test walpersist-1.5 {
|
||||
file_control_persist_wal db -1
|
||||
} {0 0}
|
||||
do_test walpersist-1.6 {
|
||||
file_control_persist_wal db 1
|
||||
} {0 1}
|
||||
do_test walpersist-1.7 {
|
||||
file_control_persist_wal db -1
|
||||
} {0 1}
|
||||
do_test walpersist-1.8 {
|
||||
file_control_persist_wal db 0
|
||||
} {0 0}
|
||||
do_test walpersist-1.9 {
|
||||
file_control_persist_wal db -1
|
||||
} {0 0}
|
||||
do_test walpersist-1.10 {
|
||||
file_control_persist_wal db 1
|
||||
} {0 1}
|
||||
do_test walpersist-1.11 {
|
||||
db close
|
||||
list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
|
||||
} {1 1 1}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -24,6 +24,13 @@ if {$::tcl_platform(platform) != "unix"} {
|
||||
return
|
||||
}
|
||||
|
||||
# these tests can't deal with the location of the -shm file under proxy locking
|
||||
#
|
||||
if {[forced_proxy_locking]} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_multiclient_test tn {
|
||||
# Do not run tests with the connections in the same process.
|
||||
#
|
||||
|
||||
@@ -60,4 +60,3 @@ do_test walshared-1.4 {
|
||||
|
||||
sqlite3_enable_shared_cache $::enable_shared_cache
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ foreach hdr {
|
||||
sqliteicu.h
|
||||
sqliteInt.h
|
||||
sqliteLimit.h
|
||||
sqlrr.h
|
||||
vdbe.h
|
||||
vdbeInt.h
|
||||
wal.h
|
||||
@@ -308,6 +309,7 @@ foreach file {
|
||||
rtree.c
|
||||
icu.c
|
||||
fts3_icu.c
|
||||
sqlrr.c
|
||||
} {
|
||||
copy_file tsrc/$file
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user