diff --git a/ext/ota/ota1.test b/ext/ota/ota1.test index 265a3d2a2f..6b8ed971da 100644 --- a/ext/ota/ota1.test +++ b/ext/ota/ota1.test @@ -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 diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c index cf408b8b9f..41207501cf 100644 --- a/ext/ota/sqlite3ota.c +++ b/ext/ota/sqlite3ota.c @@ -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; } } diff --git a/ext/ota/sqlite3ota.h b/ext/ota/sqlite3ota.h index e549022f9a..f6890f4508 100644 --- a/ext/ota/sqlite3ota.h +++ b/ext/ota/sqlite3ota.h @@ -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 */ diff --git a/manifest b/manifest index 777601fb6b..fe890ddfd3 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index 489302fa8e..ae4cdfe82d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7bb633639d1e41067903a49653f09a823054e213 \ No newline at end of file +96443ecb6909141aa621a16e628455857d036482 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index cdf5a8c179..23681cc6f3 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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