Add the sqlite3ota_create_vfs() and sqlite3ota_destroy_vfs() functions.

FossilOrigin-Name: 96443ecb6909141aa621a16e628455857d036482
This commit is contained in:
dan 2015-02-09 20:07:35 +00:00
parent de1f6a270b
commit faa8c4fdcb
6 changed files with 195 additions and 149 deletions

View File

@ -98,7 +98,7 @@ proc step_ota {target ota} {
#
proc step_ota_uri {target ota} {
while 1 {
sqlite3ota ota file:$target?xyz=123 $ota
sqlite3ota ota file:$target?xyz=&abc=123 $ota
set rc [ota step]
ota close
if {$rc != "SQLITE_OK"} break

View File

@ -85,6 +85,8 @@
typedef struct OtaState OtaState;
typedef struct OtaObjIter OtaObjIter;
typedef struct ota_vfs ota_vfs;
typedef struct ota_file ota_file;
/*
** A structure to store values read from the ota_state table in memory.
@ -156,6 +158,7 @@ struct OtaObjIter {
#define OTA_PK_WITHOUT_ROWID 4
#define OTA_PK_VTAB 5
/*
** OTA handle.
*/
@ -170,10 +173,31 @@ struct sqlite3ota {
int nProgress; /* Rows processed for all objects */
OtaObjIter objiter; /* Iterator for skipping through tbl/idx */
sqlite3_ckpt *pCkpt; /* Incr-checkpoint handle */
sqlite3_vfs *pVfs; /* Special ota VFS object */
ota_file *pTargetFd; /* File handle open on target db */
const char *zVfsName; /* Name of automatically created ota vfs */
unsigned int iCookie;
};
struct ota_vfs {
sqlite3_vfs base; /* ota VFS shim methods */
sqlite3_vfs *pRealVfs; /* Underlying VFS */
sqlite3_mutex *mutex;
const char *zOtaWal;
};
struct ota_file {
sqlite3_file base; /* sqlite3_file methods */
sqlite3_file *pReal; /* Underlying file handle */
ota_vfs *pOtaVfs; /* Pointer to the ota_vfs object */
sqlite3ota *pOta; /* Pointer to ota object (ota target only) */
int nShm; /* Number of entries in apShm[] array */
char **apShm; /* Array of mmap'd *-shm regions */
const char *zWal; /* Wal filename for this db file */
char *zDel; /* Delete this when closing file */
};
static void otaCreateVfs(sqlite3ota*, const char*);
static void otaDeleteVfs(sqlite3ota*);
@ -422,6 +446,20 @@ static int otaMPrintfExec(sqlite3ota *p, const char *zFmt, ...){
return p->rc;
}
static void *otaMalloc(sqlite3ota *p, int nByte){
void *pRet = 0;
if( p->rc==SQLITE_OK ){
pRet = sqlite3_malloc(nByte);
if( pRet==0 ){
p->rc = SQLITE_NOMEM;
}else{
memset(pRet, 0, nByte);
}
}
return pRet;
}
/*
** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that
** there is room for at least nCol elements. If an OOM occurs, store an
@ -431,17 +469,13 @@ static void otaAllocateIterArrays(sqlite3ota *p, OtaObjIter *pIter, int nCol){
int nByte = (2*sizeof(char*) + sizeof(int) + 2*sizeof(unsigned char)) * nCol;
char **azNew;
assert( p->rc==SQLITE_OK );
azNew = (char**)sqlite3_malloc(nByte);
azNew = (char**)otaMalloc(p, nByte);
if( azNew ){
memset(azNew, 0, nByte);
pIter->azTblCol = azNew;
pIter->azTblType = &azNew[nCol];
pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol];
pIter->abTblPk = (unsigned char*)&pIter->aiSrcOrder[nCol];
pIter->abNotNull = (unsigned char*)&pIter->abTblPk[nCol];
}else{
p->rc = SQLITE_NOMEM;
}
}
@ -713,19 +747,6 @@ static char *otaMPrintf(sqlite3ota *p, const char *zFmt, ...){
return zSql;
}
static void *otaMalloc(sqlite3ota *p, int nByte){
void *pRet = 0;
if( p->rc==SQLITE_OK ){
pRet = sqlite3_malloc(nByte);
if( pRet==0 ){
p->rc = SQLITE_NOMEM;
}else{
memset(pRet, 0, nByte);
}
}
return pRet;
}
/*
** This function constructs and returns a pointer to a nul-terminated
** string containing some SQL clause or list based on one or more of the
@ -991,17 +1012,14 @@ static char *otaObjIterGetSetlist(
static char *otaObjIterGetBindlist(sqlite3ota *p, int nBind){
char *zRet = 0;
if( p->rc==SQLITE_OK ){
int nByte = nBind*2 + 1;
zRet = sqlite3_malloc(nByte);
if( zRet==0 ){
p->rc = SQLITE_NOMEM;
}else{
int i;
for(i=0; i<nBind; i++){
zRet[i*2] = '?';
zRet[i*2+1] = (i+1==nBind) ? '\0' : ',';
}
int nByte = nBind*2 + 1;
zRet = (char*)otaMalloc(p, nByte);
if( zRet ){
int i;
for(i=0; i<nBind; i++){
zRet[i*2] = '?';
zRet[i*2+1] = (i+1==nBind) ? '\0' : ',';
}
}
return zRet;
@ -1460,11 +1478,21 @@ static void otaOpenDatabase(sqlite3ota *p){
assert( p->rc==SQLITE_OK );
assert( p->db==0 );
p->rc = sqlite3_open_v2(p->zTarget, &p->db, flags, p->pVfs->zName);
p->rc = sqlite3_open_v2(p->zTarget, &p->db, flags, p->zVfsName);
if( p->rc ){
p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
}else{
/* Mark the database file just opened as an OTA target database. If
** this call returns SQLITE_NOTFOUND, then the OTA vfs is not in use.
** This is an error. */
p->rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_OTA, (void*)p);
if( p->rc==SQLITE_NOTFOUND ){
p->rc = SQLITE_ERROR;
p->zErrmsg = sqlite3_mprintf("ota vfs not found");
}else{
otaMPrintfExec(p, "ATTACH %Q AS ota", p->zOta);
}
}
otaMPrintfExec(p, "ATTACH %Q AS ota", p->zOta);
}
/*
@ -2039,11 +2067,14 @@ sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){
if( p->rc==SQLITE_OK ){
if( p->eStage==OTA_STAGE_OAL ){
const char *zScript =
"PRAGMA journal_mode=off;"
"BEGIN IMMEDIATE;"
;
p->rc = sqlite3_exec(p->db, zScript, 0, 0, &p->zErrmsg);
ota_vfs *pOtaVfs = p->pTargetFd->pOtaVfs;
sqlite3_mutex_enter(pOtaVfs->mutex);
assert( pOtaVfs->zOtaWal==0 );
pOtaVfs->zOtaWal = p->pTargetFd->zWal;
p->rc = sqlite3_exec(p->db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg);
pOtaVfs->zOtaWal = 0;
sqlite3_mutex_leave(pOtaVfs->mutex);
/* Point the object iterator at the first object */
if( p->rc==SQLITE_OK ){
@ -2183,33 +2214,11 @@ sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta){
** instead.
*/
typedef struct ota_file ota_file;
typedef struct ota_vfs ota_vfs;
struct ota_file {
sqlite3_file base; /* sqlite3_file methods */
sqlite3_file *pReal; /* Underlying file handle */
ota_vfs *pOtaVfs; /* Pointer to the ota_vfs object */
int nShm; /* Number of entries in apShm[] array */
char **apShm; /* Array of mmap'd *-shm regions */
char *zFilename; /* Filename for *-oal file only */
};
struct ota_vfs {
sqlite3_vfs base; /* ota VFS shim methods */
sqlite3_vfs *pRealVfs; /* Underlying VFS */
sqlite3ota *pOta;
ota_file *pTargetDb; /* Target database file descriptor */
const char *zTargetDb; /* Path that pTargetDb was opened with */
};
/*
** Close an ota file.
*/
static int otaVfsClose(sqlite3_file *pFile){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
int rc;
int i;
@ -2219,12 +2228,7 @@ static int otaVfsClose(sqlite3_file *pFile){
}
sqlite3_free(p->apShm);
p->apShm = 0;
sqlite3_free(p->zFilename);
if( p==pOtaVfs->pTargetDb ){
pOtaVfs->pTargetDb = 0;
pOtaVfs->zTargetDb = 0;
}
sqlite3_free(p->zDel);
rc = p->pReal->pMethods->xClose(p->pReal);
return rc;
@ -2252,12 +2256,11 @@ static int otaVfsRead(
sqlite_int64 iOfst
){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
int rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
if( rc==SQLITE_OK && p==pOtaVfs->pTargetDb && iOfst==0 ){
if( rc==SQLITE_OK && p->pOta && iOfst==0 ){
unsigned char *pBuf = (unsigned char*)zBuf;
assert( iAmt>=100 );
pOtaVfs->pOta->iCookie = otaGetU32(&pBuf[24]);
p->pOta->iCookie = otaGetU32(&pBuf[24]);
}
return rc;
}
@ -2272,12 +2275,11 @@ static int otaVfsWrite(
sqlite_int64 iOfst
){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
int rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
if( rc==SQLITE_OK && p==pOtaVfs->pTargetDb && iOfst==0 ){
if( rc==SQLITE_OK && p->pOta && iOfst==0 ){
unsigned char *pBuf = (unsigned char*)zBuf;
assert( iAmt>=100 );
pOtaVfs->pOta->iCookie = otaGetU32(&pBuf[24]);
p->pOta->iCookie = otaGetU32(&pBuf[24]);
}
return rc;
}
@ -2311,13 +2313,11 @@ static int otaVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
*/
static int otaVfsLock(sqlite3_file *pFile, int eLock){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
sqlite3ota *pOta = p->pOta;
int rc = SQLITE_OK;
int eStage = pOtaVfs->pOta->eStage;
if( pOtaVfs->pTargetDb==p
&& (eStage==OTA_STAGE_OAL || eStage==OTA_STAGE_CKPT)
&& eLock==SQLITE_LOCK_EXCLUSIVE
if( pOta && eLock==SQLITE_LOCK_EXCLUSIVE
&& (pOta->eStage==OTA_STAGE_OAL || pOta->eStage==OTA_STAGE_CKPT)
){
/* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this
** prevents it from checkpointing the database from sqlite3_close(). */
@ -2350,6 +2350,12 @@ static int otaVfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*/
static int otaVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
ota_file *p = (ota_file *)pFile;
if( op==SQLITE_FCNTL_OTA ){
sqlite3ota *pOta = (sqlite3ota*)pArg;
pOta->pTargetFd = p;
p->pOta = pOta;
return SQLITE_OK;
}
return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
}
@ -2374,14 +2380,13 @@ static int otaVfsDeviceCharacteristics(sqlite3_file *pFile){
*/
static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
int rc = SQLITE_OK;
#ifdef SQLITE_AMALGAMATION
assert( WAL_WRITE_CKPT==1 );
#endif
if( pOtaVfs->pTargetDb==p && pOtaVfs->pOta->eStage==OTA_STAGE_OAL ){
if( p->pOta && p->pOta->eStage==OTA_STAGE_OAL ){
/* Magic number 1 is the WAL_WRITE_CKPT lock. Preventing SQLite from
** taking this lock also prevents any checkpoints from occurring.
** todo: really, it's not clear why this might occur, as
@ -2389,7 +2394,7 @@ static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
if( ofst==1 && n==1 ) rc = SQLITE_BUSY;
}else{
assert( p->nShm==0 );
return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
}
return rc;
@ -2403,13 +2408,12 @@ static int otaVfsShmMap(
void volatile **pp
){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
int rc = SQLITE_OK;
/* If not in OTA_STAGE_OAL, allow this call to pass through. Or, if this
** ota is in the OTA_STAGE_OAL state, use heap memory for *-shm space
** instead of a file on disk. */
if( pOtaVfs->pTargetDb==p && pOtaVfs->pOta->eStage==OTA_STAGE_OAL ){
if( p->pOta && p->pOta->eStage==OTA_STAGE_OAL ){
if( iRegion<=p->nShm ){
int nByte = (iRegion+1) * sizeof(char*);
char **apNew = (char**)sqlite3_realloc(p->apShm, nByte);
@ -2454,10 +2458,9 @@ static void otaVfsShmBarrier(sqlite3_file *pFile){
static int otaVfsShmUnmap(sqlite3_file *pFile, int delFlag){
ota_file *p = (ota_file*)pFile;
ota_vfs *pOtaVfs = p->pOtaVfs;
int rc = SQLITE_OK;
if( pOtaVfs->pTargetDb==p && pOtaVfs->pOta->eStage==OTA_STAGE_OAL ){
if( p->pOta && p->pOta->eStage==OTA_STAGE_OAL ){
/* no-op */
}else{
rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
@ -2465,17 +2468,6 @@ static int otaVfsShmUnmap(sqlite3_file *pFile, int delFlag){
return rc;
}
static int otaVfsIswal(ota_vfs *pOtaVfs, const char *zPath){
int nPath = strlen(zPath);
int nTargetDb = strlen(pOtaVfs->zTargetDb);
return ( nPath==(nTargetDb+4)
&& 0==memcmp(zPath, pOtaVfs->zTargetDb, nTargetDb)
&& 0==memcmp(&zPath[nTargetDb], "-wal", 4)
);
}
/*
** Open an ota file handle.
*/
@ -2507,7 +2499,6 @@ static int otaVfsOpen(
};
ota_vfs *pOtaVfs = (ota_vfs*)pVfs;
sqlite3_vfs *pRealVfs = pOtaVfs->pRealVfs;
sqlite3ota *p = pOtaVfs->pOta;
ota_file *pFd = (ota_file *)pFile;
int rc = SQLITE_OK;
const char *zOpen = zName;
@ -2515,13 +2506,38 @@ static int otaVfsOpen(
memset(pFd, 0, sizeof(ota_file));
pFd->pReal = (sqlite3_file*)&pFd[1];
pFd->pOtaVfs = pOtaVfs;
if( zName && p->eStage==OTA_STAGE_OAL && otaVfsIswal(pOtaVfs, zName) ){
char *zCopy = otaStrndup(zName, -1, &rc);
if( zCopy ){
int nCopy = strlen(zCopy);
zCopy[nCopy-3] = 'o';
zOpen = (const char*)(pFd->zFilename = zCopy);
if( zName ){
if( flags & SQLITE_OPEN_MAIN_DB ){
/* A main database has just been opened. The following block sets
** (pFd->zWal) to point to a buffer owned by SQLite that contains
** the name of the *-wal file this db connection will use. SQLite
** happens to pass a pointer to this buffer when using xAccess()
** or xOpen() to operate on the *-wal file. */
int n = strlen(zName);
const char *z = &zName[n];
if( flags & SQLITE_OPEN_URI ){
int odd = 0;
while( 1 ){
if( z[0]==0 ){
odd = 1 - odd;
if( odd && z[1]==0 ) break;
}
z++;
}
z += 2;
}else{
while( *z==0 ) z++;
}
z += (n + 8 + 1);
pFd->zWal = z;
}
else if( (flags & SQLITE_OPEN_WAL) && zName==pOtaVfs->zOtaWal ){
char *zCopy = otaStrndup(zName, -1, &rc);
if( zCopy ){
int nCopy = strlen(zCopy);
zCopy[nCopy-3] = 'o';
zOpen = (const char*)(pFd->zDel = zCopy);
}
}
}
@ -2530,13 +2546,6 @@ static int otaVfsOpen(
}
if( pFd->pReal->pMethods ){
pFile->pMethods = &otavfs_io_methods;
if( pOtaVfs->pTargetDb==0 ){
/* This is the target db file. */
assert( (flags & SQLITE_OPEN_MAIN_DB) );
assert( zOpen==zName );
pOtaVfs->pTargetDb = pFd;
pOtaVfs->zTargetDb = zName;
}
}
return rc;
@ -2566,11 +2575,7 @@ static int otaVfsAccess(
rc = pRealVfs->xAccess(pRealVfs, zPath, flags, pResOut);
if( rc==SQLITE_OK
&& flags==SQLITE_ACCESS_EXISTS
&& pOtaVfs->pOta->eStage==OTA_STAGE_OAL
&& otaVfsIswal(pOtaVfs, zPath)
){
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS && pOtaVfs->zOtaWal==zPath ){
if( *pResOut ){
rc = SQLITE_CANTOPEN;
}else{
@ -2666,7 +2671,15 @@ static int otaVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
return 0;
}
static void otaCreateVfs(sqlite3ota *p, const char *zParent){
void sqlite3ota_destroy_vfs(const char *zName){
sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
if( pVfs ){
sqlite3_vfs_unregister(pVfs);
sqlite3_free(pVfs);
}
}
int sqlite3ota_create_vfs(const char *zName, const char *zParent){
/* Template for VFS */
static sqlite3_vfs vfs_template = {
@ -2696,48 +2709,64 @@ static void otaCreateVfs(sqlite3ota *p, const char *zParent){
sqlite3_vfs *pParent; /* Parent VFS */
ota_vfs *pNew = 0; /* Newly allocated VFS */
int nName;
int rc = SQLITE_OK;
assert( p->rc==SQLITE_OK );
nName = strlen(zName);
pParent = sqlite3_vfs_find(zParent);
if( pParent==0 ){
p->rc = SQLITE_ERROR;
p->zErrmsg = sqlite3_mprintf("no such vfs: %s", zParent);
rc = SQLITE_NOTFOUND;
}else{
int nByte = sizeof(ota_vfs) + 64;
pNew = (ota_vfs*)otaMalloc(p, nByte);
int nByte = sizeof(ota_vfs) + nName + 1;
pNew = (ota_vfs*)sqlite3_malloc(nByte);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pNew, 0, nByte);
}
}
if( pNew ){
int rnd;
char *zName;
if( rc==SQLITE_OK ){
char *zSpace;
memcpy(&pNew->base, &vfs_template, sizeof(sqlite3_vfs));
pNew->base.mxPathname = pParent->mxPathname;
pNew->base.szOsFile = sizeof(ota_file) + pParent->szOsFile;
pNew->pOta = p;
pNew->pRealVfs = pParent;
/* Give the new VFS a unique name */
sqlite3_randomness(sizeof(int), (void*)&rnd);
pNew->base.zName = (const char*)(zName = (char*)&pNew[1]);
sprintf(zName, "ota_vfs_%d", rnd);
pNew->base.zName = (const char*)(zSpace = (char*)&pNew[1]);
memcpy(zSpace, zName, nName);
/* Register the new VFS (not as the default) */
assert( p->rc==SQLITE_OK );
p->rc = sqlite3_vfs_register(&pNew->base, 0);
if( p->rc ){
p->zErrmsg = sqlite3_mprintf("error in sqlite3_vfs_register()");
rc = sqlite3_vfs_register(&pNew->base, 0);
if( rc ){
sqlite3_free(pNew);
}else{
p->pVfs = &pNew->base;
}
}
return rc;
}
static void otaCreateVfs(sqlite3ota *p, const char *zParent){
int rnd;
char zRnd[64];
assert( p->rc==SQLITE_OK );
sqlite3_randomness(sizeof(int), (void*)&rnd);
sprintf(zRnd, "ota_vfs_%d", rnd);
p->rc = sqlite3ota_create_vfs(zRnd, zParent);
if( p->rc==SQLITE_NOTFOUND ){
p->zErrmsg = sqlite3_mprintf("no such vfs: %s", zParent);
}else if( p->rc==SQLITE_OK ){
sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd);
assert( pVfs );
p->zVfsName = pVfs->zName;
}
}
static void otaDeleteVfs(sqlite3ota *p){
if( p->pVfs ){
sqlite3_vfs_unregister(p->pVfs);
sqlite3_free(p->pVfs);
p->pVfs = 0;
if( p->zVfsName ){
sqlite3ota_destroy_vfs(p->zVfsName);
p->zVfsName = 0;
}
}

View File

@ -300,5 +300,21 @@ int sqlite3ota_close(sqlite3ota *pOta, char **pzErrmsg);
*/
sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta);
/*
** Create an OTA VFS named zName. Use existing VFS zParent to interact
** with the file-system.
*/
int sqlite3ota_create_vfs(const char *zName, const char *zParent);
/*
** Deregister and destroy an OTA vfs previously created by
** sqlite3ota_create_vfs().
**
** VFS objects are not reference counted. If a VFS object is destroyed
** before all database handles that use it have been closed, the results
** are undefined.
*/
void sqlite3ota_destroy_vfs(const char *zName);
#endif /* _SQLITE3OTA_H */

View File

@ -1,5 +1,5 @@
C Add\scomments\sto\sexplain\sthe\srole\sof\sthe\sota\svfs.
D 2015-02-07T20:20:32.171
C Add\sthe\ssqlite3ota_create_vfs()\sand\ssqlite3ota_destroy_vfs()\sfunctions.
D 2015-02-09T20:07:35.066
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -125,7 +125,7 @@ F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/ota/README.txt 2ce4ffbb0aaa6731b041c27a7359f9a5f1c69152
F ext/ota/ota.c c11a85af71dccc45976622fe7a51169a481caa91
F ext/ota/ota1.test e6b64d6ffb23dcae72386da153626b40566a69e9
F ext/ota/ota1.test a4779d5fe9710d607ebae360eebee3d82a1c14e6
F ext/ota/ota10.test 85e0f6e7964db5007590c1b299e75211ed4240d4
F ext/ota/ota3.test a77efbce7723332eb688d2b28bf18204fc9614d7
F ext/ota/ota5.test ad0799daf8923ddebffe75ae8c5504ca90b7fadb
@ -134,8 +134,8 @@ F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a
F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda
F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b
F ext/ota/otafault.test 508ba87c83d632670ac0f94371a465d4bb4d49dd
F ext/ota/sqlite3ota.c a5cea44e3d186ae53c1a0dbdc1c3ca73e9d1dc62
F ext/ota/sqlite3ota.h b4c54c7df5d223f2ee40efa5ba363188daa3ad37
F ext/ota/sqlite3ota.c 3d3179fb9bcb0edf88b3391f480e84b451f1275e
F ext/ota/sqlite3ota.h 58af0ab6361c76e0eda7aede72e7de42abf83605
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@ -245,7 +245,7 @@ F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 1f2087523007c42900ffcbdeaef06a23ad9329fc
F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af
F src/sqlite.h.in 4807b024e8d257af774cde0cf178f721ff2406ec
F src/sqlite.h.in c49acd2daa6e54110ab0cc607eb73ff32720a269
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 57f8f45028598cc2877fc08ac03b402242242c68
@ -1253,7 +1253,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 8ac58e46782bd6b81c06fdf1cb5b316b8a4e1ddf
R f5474ed197582e342ea21c91b796b802
P 7bb633639d1e41067903a49653f09a823054e213
R 290f53a2e90389d88a1ff448f97370f1
U dan
Z 4e62cdaf7cd09d75059d0dc1ee3d7cb0
Z 09bf3544f840f7fca63db224a647bd64

View File

@ -1 +1 @@
7bb633639d1e41067903a49653f09a823054e213
96443ecb6909141aa621a16e628455857d036482

View File

@ -970,6 +970,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
#define SQLITE_FCNTL_ZIPVFS_PAGER 24
#define SQLITE_FCNTL_OTA 25
/*
** CAPI3REF: Mutex Handle