diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c index 5cfaaa47b7..6754109ebc 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c @@ -8,10 +8,10 @@ */ /* -** Forward declaration for pager codec cache update function. -** This should be called after encryption is added, removed, or changed. +** Forward declaration for db codec check function. +** Used to update cached codec status after encryption changes. */ -void libsql_pager_update_codec_cache(struct Pager *pPager); +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); /* ** "Special" version of function sqlite3BtreeSetPageSize @@ -591,8 +591,8 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) { sqlite3mcSetIsEncrypted(codec, 0); } - /* Update the pager's cached codec status after changing encryption */ - libsql_pager_update_codec_cache(pPager); + /* Update both pager and database cached codec status after changing encryption */ + db->aDb[dbIndex].hasCodec = pPager->hasCodec = libsql_db_has_codec(pPager->pVfs, pPager->zFilename); } else { diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c index 182d71ea84..8dc3ca8e72 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c @@ -16436,7 +16436,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int, int, int, - void(*)(DbPage*) + void(*)(DbPage*), + int /* hasCodec from connection-level cache */ ); SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); @@ -16625,7 +16626,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3 *db, /* Associated database connection */ Btree **ppBtree, /* Return open Btree* here */ int flags, /* Flags */ - int vfsFlags /* Flags passed through to VFS open */ + int vfsFlags, /* Flags passed through to VFS open */ + int hasCodec /* True if this database has encryption codec */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the @@ -17993,6 +17995,7 @@ struct Db { Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ + u8 hasCodec; /* True if this database has encryption codec */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; @@ -58232,27 +58235,18 @@ struct Pager { /* libSQL extension: pager codec */ #ifdef LIBSQL_CUSTOM_PAGER_CODEC -int libsql_pager_has_codec_impl(struct Pager *_p); int libsql_pager_codec_impl(libsql_pghdr *hdr, void **ret); +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); #endif int libsql_pager_has_codec(struct Pager *_p) { #ifdef LIBSQL_CUSTOM_PAGER_CODEC - return libsql_pager_has_codec_impl(_p); + return libsql_db_has_codec(_p->pVfs, _p->zFilename); #else return 0; #endif } -/* -** Update the cached codec status. -** This should be called after encryption is added, removed, or changed -** via sqlite3_rekey_v2() to ensure the cached hasCodec value is correct. -*/ -void libsql_pager_update_codec_cache(struct Pager *pPager) { - pPager->hasCodec = libsql_pager_has_codec(pPager); -} - int libsql_pager_codec(libsql_pghdr *hdr, void **ret) { if (!ret) { return SQLITE_MISUSE_BKPT; @@ -62295,7 +62289,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int nExtra, /* Extra bytes append to each in-memory page */ int flags, /* flags controlling this file */ int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ - void (*xReinit)(DbPage*) /* Function to reinitialize pages */ + void (*xReinit)(DbPage*),/* Function to reinitialize pages */ + int dbHasCodec /* hasCodec from connection-level cache */ ){ u8 *pPtr; Pager *pPager = 0; /* Pager object to allocate and return */ @@ -62635,8 +62630,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; - /* Cache the codec check result to avoid expensive VFS stack traversal on every page read */ - pPager->hasCodec = libsql_pager_has_codec(pPager); + /* Use cached codec status from connection level to avoid expensive VFS stack traversal + ** and file lookup on every pager initialization */ + pPager->hasCodec = dbHasCodec; setGetterMethod(pPager); /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ @@ -73757,7 +73753,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3 *db, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags, /* Options */ - int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ + int vfsFlags, /* Flags passed through to sqlite3_vfs.xOpen() */ + int hasCodec /* True if this database has encryption codec */ ){ BtShared *pBt = 0; /* Shared part of btree structure */ Btree *p; /* Handle to return */ @@ -73902,7 +73899,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, db->wal_manager ,&pBt->pPager, zFilename, - sizeof(MemPage), flags, vfsFlags, pageReinit); + sizeof(MemPage), flags, vfsFlags, pageReinit, hasCodec); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); @@ -98769,7 +98766,8 @@ case OP_OpenEphemeral: { /* ncycle */ pCx->isEphemeral = 1; rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, - vfsFlags); + vfsFlags, + 0); /* Ephemeral tables are never encrypted */ if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); if( rc==SQLITE_OK ){ @@ -121888,6 +121886,10 @@ int libsql_handle_extra_attach_params(sqlite3* db, const char* zName, const char SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**); #endif +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); +#endif + /* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: @@ -121940,7 +121942,8 @@ static void attachFunc( Btree *pNewBt = 0; pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB, + 0); /* Memdb databases are never encrypted */ if( rc==SQLITE_OK ){ Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); if( pNewSchema ){ @@ -122009,7 +122012,13 @@ static void attachFunc( } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); + /* Check encryption status for this database file */ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + pNew->hasCodec = libsql_db_has_codec(pVfs, zPath); +#else + pNew->hasCodec = 0; +#endif + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags, pNew->hasCodec); db->nDb++; pNew->zDbSName = sqlite3DbStrDup(db, zName); } @@ -128047,7 +128056,8 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_DB; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags); + db->aDb[1].hasCodec = 0; /* Temp databases are never encrypted */ + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags, db->aDb[1].hasCodec); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to open a temporary database " "file for storing temporary tables"); @@ -184304,6 +184314,10 @@ static const char *uriParameter(const char *zFilename, const char *zParam){ int libsql_handle_extra_uri_params(sqlite3 *db, const char *zOpen); #endif +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); +#endif + /* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" @@ -184559,9 +184573,17 @@ static int openDatabase( } #endif + /* Cache encryption status at database open time to avoid expensive + ** VFS stack traversal and file lookup on every pager initialization */ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + db->aDb[0].hasCodec = libsql_db_has_codec(db->pVfs, zOpen); +#else + db->aDb[0].hasCodec = 0; +#endif + /* Open the backend database driver */ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, - flags | SQLITE_OPEN_MAIN_DB); + flags | SQLITE_OPEN_MAIN_DB, db->aDb[0].hasCodec); if( rc!=SQLITE_OK ){ if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM_BKPT; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3mc_vfs.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3mc_vfs.c index 5d74782f9d..71b7c1b098 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3mc_vfs.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3mc_vfs.c @@ -1347,13 +1347,18 @@ sqlite3mcCheckVfs(const char* zVfs) return rc; } -int libsql_pager_has_codec_impl(struct Pager* pPager) +/* +** Check if a database file is encrypted at connection open time. +** This checks both the VFS stack and the specific file encryption status. +** The result is cached at the connection level to avoid expensive checks +** on every pager initialization. +*/ +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename) { int hasCodec = 0; sqlite3mc_vfs* pVfsMC = NULL; - sqlite3_vfs* pVfs = pPager->pVfs; - /* Check whether the VFS stack of the pager contains a Multiple Ciphers VFS */ + /* Check whether the VFS stack contains a Multiple Ciphers VFS */ for (; pVfs; pVfs = pVfs->pNext) { if (pVfs && pVfs->xOpen == mcVfsOpen) @@ -1367,7 +1372,7 @@ int libsql_pager_has_codec_impl(struct Pager* pPager) /* Check whether codec is enabled for associated database file */ if (pVfsMC) { - sqlite3mc_file* mcFile = mcFindDbMainFileName(pVfsMC, pPager->zFilename); + sqlite3mc_file* mcFile = mcFindDbMainFileName(pVfsMC, zFilename); if (mcFile) { Codec* codec = mcFile->codec; diff --git a/libsql-ffi/bundled/src/sqlite3.c b/libsql-ffi/bundled/src/sqlite3.c index 182d71ea84..8dc3ca8e72 100644 --- a/libsql-ffi/bundled/src/sqlite3.c +++ b/libsql-ffi/bundled/src/sqlite3.c @@ -16436,7 +16436,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int, int, int, - void(*)(DbPage*) + void(*)(DbPage*), + int /* hasCodec from connection-level cache */ ); SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); @@ -16625,7 +16626,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3 *db, /* Associated database connection */ Btree **ppBtree, /* Return open Btree* here */ int flags, /* Flags */ - int vfsFlags /* Flags passed through to VFS open */ + int vfsFlags, /* Flags passed through to VFS open */ + int hasCodec /* True if this database has encryption codec */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the @@ -17993,6 +17995,7 @@ struct Db { Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ + u8 hasCodec; /* True if this database has encryption codec */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; @@ -58232,27 +58235,18 @@ struct Pager { /* libSQL extension: pager codec */ #ifdef LIBSQL_CUSTOM_PAGER_CODEC -int libsql_pager_has_codec_impl(struct Pager *_p); int libsql_pager_codec_impl(libsql_pghdr *hdr, void **ret); +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); #endif int libsql_pager_has_codec(struct Pager *_p) { #ifdef LIBSQL_CUSTOM_PAGER_CODEC - return libsql_pager_has_codec_impl(_p); + return libsql_db_has_codec(_p->pVfs, _p->zFilename); #else return 0; #endif } -/* -** Update the cached codec status. -** This should be called after encryption is added, removed, or changed -** via sqlite3_rekey_v2() to ensure the cached hasCodec value is correct. -*/ -void libsql_pager_update_codec_cache(struct Pager *pPager) { - pPager->hasCodec = libsql_pager_has_codec(pPager); -} - int libsql_pager_codec(libsql_pghdr *hdr, void **ret) { if (!ret) { return SQLITE_MISUSE_BKPT; @@ -62295,7 +62289,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int nExtra, /* Extra bytes append to each in-memory page */ int flags, /* flags controlling this file */ int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ - void (*xReinit)(DbPage*) /* Function to reinitialize pages */ + void (*xReinit)(DbPage*),/* Function to reinitialize pages */ + int dbHasCodec /* hasCodec from connection-level cache */ ){ u8 *pPtr; Pager *pPager = 0; /* Pager object to allocate and return */ @@ -62635,8 +62630,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; - /* Cache the codec check result to avoid expensive VFS stack traversal on every page read */ - pPager->hasCodec = libsql_pager_has_codec(pPager); + /* Use cached codec status from connection level to avoid expensive VFS stack traversal + ** and file lookup on every pager initialization */ + pPager->hasCodec = dbHasCodec; setGetterMethod(pPager); /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ @@ -73757,7 +73753,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3 *db, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags, /* Options */ - int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ + int vfsFlags, /* Flags passed through to sqlite3_vfs.xOpen() */ + int hasCodec /* True if this database has encryption codec */ ){ BtShared *pBt = 0; /* Shared part of btree structure */ Btree *p; /* Handle to return */ @@ -73902,7 +73899,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, db->wal_manager ,&pBt->pPager, zFilename, - sizeof(MemPage), flags, vfsFlags, pageReinit); + sizeof(MemPage), flags, vfsFlags, pageReinit, hasCodec); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); @@ -98769,7 +98766,8 @@ case OP_OpenEphemeral: { /* ncycle */ pCx->isEphemeral = 1; rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, - vfsFlags); + vfsFlags, + 0); /* Ephemeral tables are never encrypted */ if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); if( rc==SQLITE_OK ){ @@ -121888,6 +121886,10 @@ int libsql_handle_extra_attach_params(sqlite3* db, const char* zName, const char SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**); #endif +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); +#endif + /* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: @@ -121940,7 +121942,8 @@ static void attachFunc( Btree *pNewBt = 0; pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB, + 0); /* Memdb databases are never encrypted */ if( rc==SQLITE_OK ){ Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); if( pNewSchema ){ @@ -122009,7 +122012,13 @@ static void attachFunc( } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); + /* Check encryption status for this database file */ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + pNew->hasCodec = libsql_db_has_codec(pVfs, zPath); +#else + pNew->hasCodec = 0; +#endif + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags, pNew->hasCodec); db->nDb++; pNew->zDbSName = sqlite3DbStrDup(db, zName); } @@ -128047,7 +128056,8 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_DB; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags); + db->aDb[1].hasCodec = 0; /* Temp databases are never encrypted */ + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags, db->aDb[1].hasCodec); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to open a temporary database " "file for storing temporary tables"); @@ -184304,6 +184314,10 @@ static const char *uriParameter(const char *zFilename, const char *zParam){ int libsql_handle_extra_uri_params(sqlite3 *db, const char *zOpen); #endif +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); +#endif + /* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" @@ -184559,9 +184573,17 @@ static int openDatabase( } #endif + /* Cache encryption status at database open time to avoid expensive + ** VFS stack traversal and file lookup on every pager initialization */ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + db->aDb[0].hasCodec = libsql_db_has_codec(db->pVfs, zOpen); +#else + db->aDb[0].hasCodec = 0; +#endif + /* Open the backend database driver */ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, - flags | SQLITE_OPEN_MAIN_DB); + flags | SQLITE_OPEN_MAIN_DB, db->aDb[0].hasCodec); if( rc!=SQLITE_OK ){ if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM_BKPT; diff --git a/libsql-sqlite3/src/attach.c b/libsql-sqlite3/src/attach.c index 989cc49ac3..dadb01e611 100644 --- a/libsql-sqlite3/src/attach.c +++ b/libsql-sqlite3/src/attach.c @@ -65,6 +65,10 @@ int libsql_handle_extra_attach_params(sqlite3* db, const char* zName, const char SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**); #endif +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); +#endif + /* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: @@ -117,7 +121,8 @@ static void attachFunc( Btree *pNewBt = 0; pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB, + 0); /* Memdb databases are never encrypted */ if( rc==SQLITE_OK ){ Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); if( pNewSchema ){ @@ -186,7 +191,13 @@ static void attachFunc( } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); + /* Check encryption status for this database file */ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + pNew->hasCodec = libsql_db_has_codec(pVfs, zPath); +#else + pNew->hasCodec = 0; +#endif + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags, pNew->hasCodec); db->nDb++; pNew->zDbSName = sqlite3DbStrDup(db, zName); } diff --git a/libsql-sqlite3/src/btree.c b/libsql-sqlite3/src/btree.c index 84002d8c91..e5abf76ebd 100644 --- a/libsql-sqlite3/src/btree.c +++ b/libsql-sqlite3/src/btree.c @@ -2477,7 +2477,8 @@ int sqlite3BtreeOpen( sqlite3 *db, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags, /* Options */ - int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ + int vfsFlags, /* Flags passed through to sqlite3_vfs.xOpen() */ + int hasCodec /* True if this database has encryption codec */ ){ BtShared *pBt = 0; /* Shared part of btree structure */ Btree *p; /* Handle to return */ @@ -2622,7 +2623,7 @@ int sqlite3BtreeOpen( goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, db->wal_manager ,&pBt->pPager, zFilename, - sizeof(MemPage), flags, vfsFlags, pageReinit); + sizeof(MemPage), flags, vfsFlags, pageReinit, hasCodec); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); diff --git a/libsql-sqlite3/src/btree.h b/libsql-sqlite3/src/btree.h index ff392a08fb..5880f5888c 100644 --- a/libsql-sqlite3/src/btree.h +++ b/libsql-sqlite3/src/btree.h @@ -49,7 +49,8 @@ int sqlite3BtreeOpen( sqlite3 *db, /* Associated database connection */ Btree **ppBtree, /* Return open Btree* here */ int flags, /* Flags */ - int vfsFlags /* Flags passed through to VFS open */ + int vfsFlags, /* Flags passed through to VFS open */ + int hasCodec /* True if this database has encryption codec */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the diff --git a/libsql-sqlite3/src/build.c b/libsql-sqlite3/src/build.c index e15bd28eba..30b26e3b47 100644 --- a/libsql-sqlite3/src/build.c +++ b/libsql-sqlite3/src/build.c @@ -5309,7 +5309,8 @@ int sqlite3OpenTempDatabase(Parse *pParse){ SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_DB; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags); + db->aDb[1].hasCodec = 0; /* Temp databases are never encrypted */ + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags, db->aDb[1].hasCodec); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to open a temporary database " "file for storing temporary tables"); diff --git a/libsql-sqlite3/src/main.c b/libsql-sqlite3/src/main.c index f77dc11114..17c997354d 100644 --- a/libsql-sqlite3/src/main.c +++ b/libsql-sqlite3/src/main.c @@ -3445,9 +3445,13 @@ static const char *uriParameter(const char *zFilename, const char *zParam){ int libsql_handle_extra_uri_params(sqlite3 *db, const char *zOpen); #endif +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); +#endif + /* ** This routine does the work of opening a database on behalf of -** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" +** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" ** is UTF-8 encoded. */ static int openDatabase( @@ -3700,9 +3704,17 @@ static int openDatabase( } #endif + /* Cache encryption status at database open time to avoid expensive + ** VFS stack traversal and file lookup on every pager initialization */ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + db->aDb[0].hasCodec = libsql_db_has_codec(db->pVfs, zOpen); +#else + db->aDb[0].hasCodec = 0; +#endif + /* Open the backend database driver */ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, - flags | SQLITE_OPEN_MAIN_DB); + flags | SQLITE_OPEN_MAIN_DB, db->aDb[0].hasCodec); if( rc!=SQLITE_OK ){ if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM_BKPT; diff --git a/libsql-sqlite3/src/pager.c b/libsql-sqlite3/src/pager.c index 88ed3d36fd..a32e5c0c10 100644 --- a/libsql-sqlite3/src/pager.c +++ b/libsql-sqlite3/src/pager.c @@ -710,27 +710,18 @@ struct Pager { /* libSQL extension: pager codec */ #ifdef LIBSQL_CUSTOM_PAGER_CODEC -int libsql_pager_has_codec_impl(struct Pager *_p); int libsql_pager_codec_impl(libsql_pghdr *hdr, void **ret); +int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename); #endif int libsql_pager_has_codec(struct Pager *_p) { #ifdef LIBSQL_CUSTOM_PAGER_CODEC - return libsql_pager_has_codec_impl(_p); + return libsql_db_has_codec(_p->pVfs, _p->zFilename); #else return 0; #endif } -/* -** Update the cached codec status. -** This should be called after encryption is added, removed, or changed -** via sqlite3_rekey_v2() to ensure the cached hasCodec value is correct. -*/ -void libsql_pager_update_codec_cache(struct Pager *pPager) { - pPager->hasCodec = libsql_pager_has_codec(pPager); -} - int libsql_pager_codec(libsql_pghdr *hdr, void **ret) { if (!ret) { return SQLITE_MISUSE_BKPT; @@ -4773,7 +4764,8 @@ int sqlite3PagerOpen( int nExtra, /* Extra bytes append to each in-memory page */ int flags, /* flags controlling this file */ int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ - void (*xReinit)(DbPage*) /* Function to reinitialize pages */ + void (*xReinit)(DbPage*),/* Function to reinitialize pages */ + int dbHasCodec /* hasCodec from connection-level cache */ ){ u8 *pPtr; Pager *pPager = 0; /* Pager object to allocate and return */ @@ -5113,8 +5105,9 @@ int sqlite3PagerOpen( /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; - /* Cache the codec check result to avoid expensive VFS stack traversal on every page read */ - pPager->hasCodec = libsql_pager_has_codec(pPager); + /* Use cached codec status from connection level to avoid expensive VFS stack traversal + ** and file lookup on every pager initialization */ + pPager->hasCodec = dbHasCodec; setGetterMethod(pPager); /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ diff --git a/libsql-sqlite3/src/pager.h b/libsql-sqlite3/src/pager.h index f16d832a1a..48963bd03c 100644 --- a/libsql-sqlite3/src/pager.h +++ b/libsql-sqlite3/src/pager.h @@ -124,7 +124,8 @@ int sqlite3PagerOpen( int, int, int, - void(*)(DbPage*) + void(*)(DbPage*), + int /* hasCodec from connection-level cache */ ); int sqlite3PagerClose(Pager *pPager, sqlite3*); int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); diff --git a/libsql-sqlite3/src/sqliteInt.h b/libsql-sqlite3/src/sqliteInt.h index cd9bf41dfa..a748096b83 100644 --- a/libsql-sqlite3/src/sqliteInt.h +++ b/libsql-sqlite3/src/sqliteInt.h @@ -1452,6 +1452,7 @@ struct Db { Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ + u8 hasCodec; /* True if this database has encryption codec */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; diff --git a/libsql-sqlite3/src/test3.c b/libsql-sqlite3/src/test3.c index 73f4bf78c1..358dfde864 100644 --- a/libsql-sqlite3/src/test3.c +++ b/libsql-sqlite3/src/test3.c @@ -72,8 +72,8 @@ static int SQLITE_TCLAPI btree_open( rc = make_ref_counted_wal_manager(sqlite3_wal_manager, &wal_manager); if (rc) return rc; sDb.wal_manager = wal_manager; - rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB, 0); destroy_wal_manager(sDb.wal_manager); sqlite3_free(zFilename); if( rc!=SQLITE_OK ){ diff --git a/libsql-sqlite3/src/vdbe.c b/libsql-sqlite3/src/vdbe.c index e8de5e640a..5ab04c3024 100644 --- a/libsql-sqlite3/src/vdbe.c +++ b/libsql-sqlite3/src/vdbe.c @@ -4552,9 +4552,10 @@ case OP_OpenEphemeral: { /* ncycle */ pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, - vfsFlags); + vfsFlags, + 0); /* Ephemeral tables are never encrypted */ if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); if( rc==SQLITE_OK ){