diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c index ddc845041d..5cfaaa47b7 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c @@ -7,6 +7,12 @@ ** License: MIT */ +/* +** Forward declaration for pager codec cache update function. +** This should be called after encryption is added, removed, or changed. +*/ +void libsql_pager_update_codec_cache(struct Pager *pPager); + /* ** "Special" version of function sqlite3BtreeSetPageSize ** This version allows to reduce the number of reserved bytes per page, @@ -585,6 +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); } else { diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c index a446238be3..182d71ea84 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c @@ -58152,6 +58152,7 @@ struct Pager { u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ u8 memVfs; /* VFS-implemented memory database */ + u8 hasCodec; /* True if pager has encryption codec */ /************************************************************************** ** The following block contains those class members that change during @@ -58243,6 +58244,15 @@ int libsql_pager_has_codec(struct Pager *_p) { #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; @@ -58380,7 +58390,7 @@ static const unsigned char aJournalMagic[] = { SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ if( pPager->fd->pMethods==0 ) return 0; if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; - if( libsql_pager_has_codec(pPager) != 0 ) return 0; + if( pPager->hasCodec ) return 0; #ifndef SQLITE_OMIT_WAL if( pagerUseWal(pPager) ){ u32 iRead = 0; @@ -58603,7 +58613,7 @@ static void setGetterMethod(Pager *pPager){ if( pPager->errCode ){ pPager->xGet = getPageError; #if SQLITE_MAX_MMAP_SIZE>0 - }else if( USEFETCH(pPager) && libsql_pager_has_codec(pPager) == 0 ){ + }else if( USEFETCH(pPager) && !pPager->hasCodec ){ pPager->xGet = getPageMMap; #endif /* SQLITE_MAX_MMAP_SIZE>0 */ }else{ @@ -62625,6 +62635,8 @@ 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); 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-ffi/bundled/src/sqlite3.c b/libsql-ffi/bundled/src/sqlite3.c index a446238be3..182d71ea84 100644 --- a/libsql-ffi/bundled/src/sqlite3.c +++ b/libsql-ffi/bundled/src/sqlite3.c @@ -58152,6 +58152,7 @@ struct Pager { u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ u8 memVfs; /* VFS-implemented memory database */ + u8 hasCodec; /* True if pager has encryption codec */ /************************************************************************** ** The following block contains those class members that change during @@ -58243,6 +58244,15 @@ int libsql_pager_has_codec(struct Pager *_p) { #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; @@ -58380,7 +58390,7 @@ static const unsigned char aJournalMagic[] = { SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ if( pPager->fd->pMethods==0 ) return 0; if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; - if( libsql_pager_has_codec(pPager) != 0 ) return 0; + if( pPager->hasCodec ) return 0; #ifndef SQLITE_OMIT_WAL if( pagerUseWal(pPager) ){ u32 iRead = 0; @@ -58603,7 +58613,7 @@ static void setGetterMethod(Pager *pPager){ if( pPager->errCode ){ pPager->xGet = getPageError; #if SQLITE_MAX_MMAP_SIZE>0 - }else if( USEFETCH(pPager) && libsql_pager_has_codec(pPager) == 0 ){ + }else if( USEFETCH(pPager) && !pPager->hasCodec ){ pPager->xGet = getPageMMap; #endif /* SQLITE_MAX_MMAP_SIZE>0 */ }else{ @@ -62625,6 +62635,8 @@ 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); 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.c b/libsql-sqlite3/src/pager.c index 5a2278b616..88ed3d36fd 100644 --- a/libsql-sqlite3/src/pager.c +++ b/libsql-sqlite3/src/pager.c @@ -630,6 +630,7 @@ struct Pager { u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ u8 memVfs; /* VFS-implemented memory database */ + u8 hasCodec; /* True if pager has encryption codec */ /************************************************************************** ** The following block contains those class members that change during @@ -721,6 +722,15 @@ int libsql_pager_has_codec(struct Pager *_p) { #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; @@ -858,7 +868,7 @@ static const unsigned char aJournalMagic[] = { int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ if( pPager->fd->pMethods==0 ) return 0; if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; - if( libsql_pager_has_codec(pPager) != 0 ) return 0; + if( pPager->hasCodec ) return 0; #ifndef SQLITE_OMIT_WAL if( pagerUseWal(pPager) ){ u32 iRead = 0; @@ -1081,7 +1091,7 @@ static void setGetterMethod(Pager *pPager){ if( pPager->errCode ){ pPager->xGet = getPageError; #if SQLITE_MAX_MMAP_SIZE>0 - }else if( USEFETCH(pPager) && libsql_pager_has_codec(pPager) == 0 ){ + }else if( USEFETCH(pPager) && !pPager->hasCodec ){ pPager->xGet = getPageMMap; #endif /* SQLITE_MAX_MMAP_SIZE>0 */ }else{ @@ -5103,6 +5113,8 @@ 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); setGetterMethod(pPager); /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */