From aa61773d128f5e81de5428a8d797922e3da8d671 Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> Date: Wed, 23 Jul 2025 19:40:15 +0800 Subject: [PATCH] Fixed compress issues Signed-off-by: MartinChoo <214582617@qq.com> --- patch/0001-History-features-on-OH.patch | 4 +- patch/0002-Enable-and-optimize-ICU.patch | 4 +- patch/0003-Busy-debug-and-log-dump.patch | 4 +- patch/0004-Support-meta-recovery.patch | 4 +- ...ity-report-corruption-and-check-page.patch | 4 +- patch/0006-Support-Binlog.patch | 8 +- patch/0007-DatabaseDebugTool.patch | 4 +- patch/0008-Rekey-multi-process.patch | 6 +- ...Allow-enable-checksum-through-PRAGMA.patch | 10 +- ...ExtensionLoading-LoadCustomTokenizer.patch | 6 +- patch/0011-Support-compress-db.patch | 592 +++++++++++------- patch/0012-Bugfix-on-current-version.patch | 74 +-- unittest/common.cpp | 10 + unittest/common.h | 1 + unittest/sqlite_compress_test.cpp | 122 ++++ 15 files changed, 557 insertions(+), 296 deletions(-) diff --git a/patch/0001-History-features-on-OH.patch b/patch/0001-History-features-on-OH.patch index b6a9a13..7e7236c 100644 --- a/patch/0001-History-features-on-OH.patch +++ b/patch/0001-History-features-on-OH.patch @@ -1,6 +1,6 @@ -From 1355da4b32bfb2e263e03e953d052086cf40ed20 Mon Sep 17 00:00:00 2001 +From 243b21cbaa3d360fbdfb91ea3e18398125129167 Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:53:07 +0800 +Date: Wed, 23 Jul 2025 17:38:02 +0800 Subject: [PATCH 01/12] History features on OH --- diff --git a/patch/0002-Enable-and-optimize-ICU.patch b/patch/0002-Enable-and-optimize-ICU.patch index 559c32f..ecc3699 100644 --- a/patch/0002-Enable-and-optimize-ICU.patch +++ b/patch/0002-Enable-and-optimize-ICU.patch @@ -1,6 +1,6 @@ -From 733de3813ffb596919bcc72fb8f61422cbacf295 Mon Sep 17 00:00:00 2001 +From 53b13f3aa2f41a8d30eac3702fe066d3a4a616ee Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:53:41 +0800 +Date: Wed, 23 Jul 2025 17:39:10 +0800 Subject: [PATCH 02/12] Enable and optimize ICU --- diff --git a/patch/0003-Busy-debug-and-log-dump.patch b/patch/0003-Busy-debug-and-log-dump.patch index 2dfa3c7..d918ed8 100644 --- a/patch/0003-Busy-debug-and-log-dump.patch +++ b/patch/0003-Busy-debug-and-log-dump.patch @@ -1,6 +1,6 @@ -From 65e08929709648a1ee5d6b0d3b6383634f8669e3 Mon Sep 17 00:00:00 2001 +From 75598d83216e61989af3e73af0e131593568a395 Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:54:18 +0800 +Date: Wed, 23 Jul 2025 17:39:54 +0800 Subject: [PATCH 03/12] Busy debug and log dump --- diff --git a/patch/0004-Support-meta-recovery.patch b/patch/0004-Support-meta-recovery.patch index 6f6427f..ab027f8 100644 --- a/patch/0004-Support-meta-recovery.patch +++ b/patch/0004-Support-meta-recovery.patch @@ -1,6 +1,6 @@ -From 45e883bed32094756ff8878964d911cc0cfe9fd3 Mon Sep 17 00:00:00 2001 +From d6f2f7b1d7d288bc0cb0ff998052bb8efac40f7f Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:54:55 +0800 +Date: Wed, 23 Jul 2025 17:41:00 +0800 Subject: [PATCH 04/12] Support meta recovery --- diff --git a/patch/0005-Enhance-dfx-ability-report-corruption-and-check-page.patch b/patch/0005-Enhance-dfx-ability-report-corruption-and-check-page.patch index 62075d3..6fd4d35 100644 --- a/patch/0005-Enhance-dfx-ability-report-corruption-and-check-page.patch +++ b/patch/0005-Enhance-dfx-ability-report-corruption-and-check-page.patch @@ -1,6 +1,6 @@ -From 530b32340de30cfde81712585051e5b8b77ba095 Mon Sep 17 00:00:00 2001 +From 29cc811975af684969da4f057b6107fff4d6487f Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:55:22 +0800 +Date: Wed, 23 Jul 2025 17:41:39 +0800 Subject: [PATCH 05/12] Enhance dfx ability, report corruption and check pages --- diff --git a/patch/0006-Support-Binlog.patch b/patch/0006-Support-Binlog.patch index 1fcaa0c..9bf8b39 100644 --- a/patch/0006-Support-Binlog.patch +++ b/patch/0006-Support-Binlog.patch @@ -1,6 +1,6 @@ -From 51e8e916320226d0dd6d85bdca8bceb4c0e40cf6 Mon Sep 17 00:00:00 2001 -From: Liu Hongyang -Date: Fri, 11 Jul 2025 10:33:52 +0800 +From d169331fa1819949f671071677cf4ac45c05a21a Mon Sep 17 00:00:00 2001 +From: MartinChoo <214582617@qq.com> +Date: Wed, 23 Jul 2025 17:42:36 +0800 Subject: [PATCH 06/12] Support-Binlog --- @@ -1791,5 +1791,5 @@ index e7e8b3c..3f1195a 100644 EXPORT_SYMBOLS const sqlite3_api_routines *sqlite3_export_symbols = &sqlite3Apis; -- -2.25.1 +2.47.0.windows.2 diff --git a/patch/0007-DatabaseDebugTool.patch b/patch/0007-DatabaseDebugTool.patch index 9fc0387..64dd275 100644 --- a/patch/0007-DatabaseDebugTool.patch +++ b/patch/0007-DatabaseDebugTool.patch @@ -1,6 +1,6 @@ -From ea38cd58b2a3704a2ce6e7e6840cdaa72c24b566 Mon Sep 17 00:00:00 2001 +From d97d1d7651ad5b3fc5411145942f06d65be9bcce Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:56:30 +0800 +Date: Wed, 23 Jul 2025 17:43:08 +0800 Subject: [PATCH 07/12] DatabaseDebugTool --- diff --git a/patch/0008-Rekey-multi-process.patch b/patch/0008-Rekey-multi-process.patch index 2eee90b..307f020 100644 --- a/patch/0008-Rekey-multi-process.patch +++ b/patch/0008-Rekey-multi-process.patch @@ -1,6 +1,6 @@ -From c21f5d9abd672d70f46e22ffb6bb3ef48e7f1c6e Mon Sep 17 00:00:00 2001 +From ce201b3a6be487bb3eb48e1d102ba246332aba66 Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 3 Jul 2025 22:57:18 +0800 +Date: Wed, 23 Jul 2025 17:43:40 +0800 Subject: [PATCH 08/12] Rekey multi process --- @@ -8,7 +8,7 @@ Subject: [PATCH 08/12] Rekey multi process 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c -index 37501f9..425d3d7 100644 +index 3f1195a..4c538a1 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -15689,6 +15689,7 @@ typedef int VList; diff --git a/patch/0009-Allow-enable-checksum-through-PRAGMA.patch b/patch/0009-Allow-enable-checksum-through-PRAGMA.patch index 1aba60f..89e4d39 100644 --- a/patch/0009-Allow-enable-checksum-through-PRAGMA.patch +++ b/patch/0009-Allow-enable-checksum-through-PRAGMA.patch @@ -1,7 +1,7 @@ -From 6e06b441bf3b59fdf03da8196442346a08dae60d Mon Sep 17 00:00:00 2001 +From 2919f58d1a104c99d3f84b87afe2de0f08b65fae Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 10 Jul 2025 10:37:19 +0800 -Subject: [PATCH 1/4] Allow enable checksum through PRAGMA +Date: Wed, 23 Jul 2025 17:45:44 +0800 +Subject: [PATCH 09/12] Allow enable checksum through PRAGMA --- ext/misc/cksumvfs.c | 189 ++++++++++++++++++++++++++++++++++++-------- @@ -386,7 +386,7 @@ index 6f4c55c..d7a2431 100644 int (*register_cksumvfs)(const char *); int (*unregister_cksumvfs)(); diff --git a/src/sqlite3.c b/src/sqlite3.c -index 3977ff6..be9f41d 100644 +index 4c538a1..c84348b 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -139875,6 +139875,10 @@ static int integrityCheckResultRow(Vdbe *v){ @@ -723,7 +723,7 @@ index 3977ff6..be9f41d 100644 #endif /* #ifndef SQLITE_OMIT_WAL */ } #endif /* SQLITE_OS_UNIX */ -@@ -258501,7 +258605,8 @@ static const sqlite3_api_routines_cksumvfs sqlite3CksumvfsApis = { +@@ -258499,7 +258603,8 @@ static const sqlite3_api_routines_cksumvfs sqlite3CksumvfsApis = { }; EXPORT_SYMBOLS const sqlite3_api_routines_cksumvfs *sqlite3_export_cksumvfs_symbols = &sqlite3CksumvfsApis; diff --git a/patch/0010-EnableExtensionLoading-LoadCustomTokenizer.patch b/patch/0010-EnableExtensionLoading-LoadCustomTokenizer.patch index dd6dc76..711f24b 100644 --- a/patch/0010-EnableExtensionLoading-LoadCustomTokenizer.patch +++ b/patch/0010-EnableExtensionLoading-LoadCustomTokenizer.patch @@ -1,7 +1,7 @@ -From 73c47b5dbd9efb039ff7461bebe4558b5e574fc1 Mon Sep 17 00:00:00 2001 +From 153903e64e45fa243d4da21563e8c52a6440c42a Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 10 Jul 2025 10:38:00 +0800 -Subject: [PATCH 2/4] EnableExtensionLoading-LoadCustomTokenizer +Date: Wed, 23 Jul 2025 17:47:31 +0800 +Subject: [PATCH 10/12] EnableExtensionLoading-LoadCustomTokenizer --- src/shell.c | 32 ++++++++++++++++++++++++++++++++ diff --git a/patch/0011-Support-compress-db.patch b/patch/0011-Support-compress-db.patch index b823638..1301746 100644 --- a/patch/0011-Support-compress-db.patch +++ b/patch/0011-Support-compress-db.patch @@ -1,17 +1,17 @@ -From 52d7741929a9affa25bbf1972427c31c53e98555 Mon Sep 17 00:00:00 2001 -From: zhujinlin <214582617@qq.com> -Date: Mon, 7 Jul 2025 21:52:07 +0800 -Subject: [PATCH] Support compress db +From 8bda6b2d11068a0449bbce7e24adbcb5b4707330 Mon Sep 17 00:00:00 2001 +From: MartinChoo <214582617@qq.com> +Date: Wed, 23 Jul 2025 17:48:45 +0800 +Subject: [PATCH 11/12] Support compress db --- ext/misc/cksumvfs.c | 4 +- - src/compressvfs.c | 1100 +++++++++++++++++++++++++++++++++++++++++++ - src/sqlite3.c | 448 +++++++++++++++++- - 3 files changed, 1535 insertions(+), 17 deletions(-) + src/compressvfs.c | 1044 +++++++++++++++++++++++++++++++++++++++++++ + src/sqlite3.c | 575 +++++++++++++++++++++--- + 3 files changed, 1552 insertions(+), 71 deletions(-) create mode 100644 src/compressvfs.c diff --git a/ext/misc/cksumvfs.c b/ext/misc/cksumvfs.c -index a23a997..1a801fb 100644 +index d7a2431..b756ebb 100644 --- a/ext/misc/cksumvfs.c +++ b/ext/misc/cksumvfs.c @@ -966,7 +966,7 @@ static int cksmRegisterVfs(void){ @@ -34,13 +34,12 @@ index a23a997..1a801fb 100644 diff --git a/src/compressvfs.c b/src/compressvfs.c new file mode 100644 -index 0000000..b1d0ac6 +index 0000000..90a3f44 --- /dev/null +++ b/src/compressvfs.c -@@ -0,0 +1,1100 @@ -+/************** Begin file compressvfs.c *********************************************/ +@@ -0,0 +1,1044 @@ +/* -+** 2025 June 26 ++** 2025-06-10 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: @@ -200,24 +199,19 @@ index 0000000..b1d0ac6 + +#define COMPRESSION_SQL_MAX_LENGTH 100 + -+#define SQLITE_SHMMAP_IS_WRITE 0x00000001 /*Flag for xShmMap, extend file if necessary */ -+#define SQLITE_OPEN_COMPRESS_SHM 0x00010000 /*Flag for xShmMap, need to rename shm file */ -+ -+typedef struct compress_info compress_info; -+struct compress_info{ -+ sqlite3_vfs *pRootVfs; /* Ptr to default VFS */ -+ sqlite3* pDb; /* Ptr to OutterDB */ -+ u8 bOutterDbOpen; /* True to OutterDB is opened */ -+ u8 bSubDbOpen; /* True to SubDB is opened */ -+}; ++#define SQLITE_SHMMAP_IS_WRITE 0x00000001 /* Flag for xShmMap, extend file if necessary */ ++#define SQLITE_OPEN_COMPRESS_SHM 0x00010000 /* Flag for xShmMap, need to rename shm file */ + +/* An open file */ +typedef struct{ + sqlite3_file base; /* IO methods */ -+ compress_info *pInfo; /* Ptr to compress info */ ++ sqlite3* pDb; /* Ptr to OutterDB */ ++ u8 bOutterDbOpen; /* True to OutterDB is opened */ ++ u8 bSubDbOpen; /* True to SubDB is opened */ + u8 bBegin; /* True to xSync() need commit */ + u8 compression; /* Compression options */ + int page_size; /* Uncompressed page size */ ++ int persistWalFlag; /* Flag to persist flag */ +} CompressFile; + + @@ -237,11 +231,10 @@ index 0000000..b1d0ac6 +static int compressShmLock(sqlite3_file *pFile, int offset, int n, int flags); +static void compressShmBarrier(sqlite3_file *pFile); +static int compressShmUnmap(sqlite3_file *pFile, int deleteFlag); -+static int compressFetch(sqlite3_file *pFile, sqlite_int64 iOfst, int iAmt, void **pp); -+static int compressUnfetch(sqlite3_file *pFile, sqlite_int64 iOfst, void *pPage); ++static int compressFetch(sqlite3_file *pFile, sqlite3_int64 iOfst, int iAmt, void **pp); ++static int compressUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage); + +static sqlite3_vfs compress_vfs = {0}; -+static compress_info compress_vfs_info = {0}; +static sqlite3_io_methods compress_io_methods = { + 3, + compressClose, @@ -293,6 +286,7 @@ index 0000000..b1d0ac6 +** Access to a lower-level VFS that (might) implement dynamic loading, access to randomness, etc. +*/ +#define ORIGFILE(p) ((sqlite3_file*)(((CompressFile*)(p))+1)) ++#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) + +static u32 g_compress_algo_load = COMPRESSION_UNDEFINED; +static void *g_compress_algo_library = NULL; @@ -307,7 +301,7 @@ index 0000000..b1d0ac6 +static int loadBrotliExtension(){ + g_compress_algo_library = dlopen("libbrotli_shared.z.so", RTLD_LAZY); + if( g_compress_algo_library==NULL ){ -+ sqlite3_log(SQLITE_NOTICE, "load brotli so failed :%s", dlerror()); ++ sqlite3_log(SQLITE_NOTICE, "load brotli so failed: %s", dlerror()); + return SQLITE_ERROR; + } + compressBoundPtr = (compressBound_ptr)dlsym(g_compress_algo_library, "BrotliEncoderMaxCompressedSize"); @@ -334,7 +328,7 @@ index 0000000..b1d0ac6 + return SQLITE_ERROR; +} + -+static int loadZstsExtension(){ ++static int loadZstdExtension(){ + g_compress_algo_library = dlopen("libzstd_shared.z.so", RTLD_LAZY); + if( g_compress_algo_library==NULL ){ + sqlite3_log(SQLITE_NOTICE, "load zstd so failed :%s", dlerror()); @@ -370,7 +364,7 @@ index 0000000..b1d0ac6 + } +#ifndef _WIN32 + if( compression==COMPRESSION_UNDEFINED ){ -+ if( loadZstsExtension()==SQLITE_ERROR ){ ++ if( loadZstdExtension()==SQLITE_ERROR ){ + sqlite3_log(SQLITE_NOTICE, "load zstd failed :%s", dlerror()); + if( loadBrotliExtension()==SQLITE_ERROR ){ + sqlite3_log(SQLITE_ERROR, "load compress so failed :%s", dlerror()); @@ -383,7 +377,7 @@ index 0000000..b1d0ac6 + return SQLITE_ERROR; + } + }else if( compression==COMPRESSION_ZSTD ){ -+ if( loadZstsExtension()==SQLITE_ERROR ){ ++ if( loadZstdExtension()==SQLITE_ERROR ){ + sqlite3_log(SQLITE_ERROR, "load zstd so failed :%s", dlerror()); + return SQLITE_ERROR; + } @@ -445,7 +439,7 @@ index 0000000..b1d0ac6 +} + +/* Decompress buf with compression */ -+EXPORT_SYMBOLS static int decompressBuf( ++EXPORT_SYMBOLS int decompressBuf( + u8 *dst, + int dst_buf_len, + int *dst_written_len, @@ -496,13 +490,13 @@ index 0000000..b1d0ac6 +} + +/* Get page size before compressed from OutterDB. */ -+static int getCompressPgsize(sqlite3 * db, int *pagesize){ ++static int getCompressPgsize(sqlite3 *db, int *pagesize){ + int rc = SQLITE_OK; + if( *pagesize!=0 ){ + return rc; + } + sqlite3_stmt *stmt = NULL; -+ const char *sql = "SELECT pagesize FROM vfs_compresssion;"; ++ const char *sql = "SELECT pagesize FROM vfs_compression;"; + if( sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)==SQLITE_OK ){ + if( sqlite3_step(stmt)==SQLITE_ROW ){ + *pagesize = sqlite3_column_int(stmt, 0); @@ -518,7 +512,7 @@ index 0000000..b1d0ac6 +static int setCompressPgsize(sqlite3 *db, int pagesize){ + int rc = SQLITE_OK; + sqlite3_stmt *stmt = NULL; -+ const char *sql = "UPDATE vfs_compresssion SET pagesize=?;"; ++ const char *sql = "UPDATE vfs_compression SET pagesize=?;"; + + if( sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)==SQLITE_OK ){ + sqlite3_bind_int(stmt, 1, pagesize); @@ -531,7 +525,7 @@ index 0000000..b1d0ac6 +} + +/* Get max page number from OutterDB. */ -+static int getMaxCompressPgno(sqlite3 * db){ ++static int getMaxCompressPgno(sqlite3 *db){ + sqlite3_stmt *stmt = NULL; + const char *sql = "SELECT MAX(pageno) FROM vfs_pages;"; + int max_pgno = 0; @@ -546,7 +540,7 @@ index 0000000..b1d0ac6 +} + +/* Get Compression option from OutterDB. */ -+static void getCompression(sqlite3 * db, CompressFile *pCompress){ ++static void getCompression(sqlite3 *db, CompressFile *pCompress){ + sqlite3_stmt *stmt = NULL; + const char *sql = "SELECT count(*), compression, pagesize FROM vfs_compression;"; + int count = 0; @@ -556,7 +550,7 @@ index 0000000..b1d0ac6 + if( sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)==SQLITE_OK ){ + if( sqlite3_step(stmt)==SQLITE_ROW ){ + count = sqlite3_column_int(stmt, 0); -+ if ( count==1 ){ ++ if( count==1 ){ + pCompress->compression = sqlite3_column_int(stmt, 1); + pCompress->page_size = sqlite3_column_int(stmt, 2); + } @@ -573,8 +567,7 @@ index 0000000..b1d0ac6 +static int compressSync(sqlite3_file *pFile, int flags){ + assert( pFile ); + CompressFile *pCompress = (CompressFile *)pFile; -+ compress_info *compress_info = pCompress->pInfo; -+ sqlite3 *db = compress_info->pDb; ++ sqlite3 *db = pCompress->pDb; + if( pCompress->bBegin==1 ){ + int rc = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); + if( rc!=SQLITE_OK ){ @@ -599,6 +592,16 @@ index 0000000..b1d0ac6 +*/ +static int compressFileControl(sqlite3_file *pFile, int op, void *pArg){ + assert( pFile ); ++ CompressFile *pCompress = (CompressFile *)pFile; ++ if( op==SQLITE_FCNTL_PERSIST_WAL ){ ++ int persistFlag = *(int*)pArg; ++ if( persistFlag<0 ){ ++ *(int*)pArg = pCompress->persistWalFlag; ++ }else{ ++ pCompress->persistWalFlag = persistFlag>0 ? 1 : 0; ++ } ++ return SQLITE_OK; ++ } + pFile = ORIGFILE(pFile); + return pFile->pMethods->xFileControl(pFile, op, pArg); +} @@ -644,8 +647,7 @@ index 0000000..b1d0ac6 +static int compressFileSize(sqlite3_file *pFile, i64 *pSize){ + assert( pFile ); + CompressFile *pCompress = (CompressFile *)pFile; -+ compress_info *compress_info = pCompress->pInfo; -+ sqlite3 *db = compress_info->pDb; ++ sqlite3 *db = pCompress->pDb; + int rc = getCompressPgsize(db, &pCompress->page_size); + if( rc!=SQLITE_OK ){ + return SQLITE_IOERR_FSTAT; @@ -662,15 +664,14 @@ index 0000000..b1d0ac6 +static int compressTruncate(sqlite3_file *pFile, sqlite_int64 size){ + assert( pFile ); + CompressFile *pCompress = (CompressFile *)pFile; -+ compress_info *compress_info = pCompress->pInfo; -+ sqlite3 *db = compress_info->pDb; ++ sqlite3 *db = pCompress->pDb; + int rc = getCompressPgsize(db, &pCompress->page_size); + if( rc!=SQLITE_OK || pCompress->page_size==0 ){ + return SQLITE_IOERR_TRUNCATE; + } + int pgsize = pCompress->page_size; + int pgno = size / pgsize; -+ if( size % pgsize!=0 || getMaxCompressPgno(db) < pgno){ ++ if( size % pgsize!=0 || getMaxCompressPgno(db) < pgno ){ + return SQLITE_IOERR_TRUNCATE; + } + if( pCompress->bBegin!=1 ){ @@ -699,8 +700,7 @@ index 0000000..b1d0ac6 + assert( pFile ); + assert( iAmt>0 ); + CompressFile *pCompress = (CompressFile *)pFile; -+ compress_info *compress_info = pCompress->pInfo; -+ sqlite3 *db = compress_info->pDb; ++ sqlite3 *db = pCompress->pDb; + int rc = getCompressPgsize(db, &pCompress->page_size); + if( rc!=SQLITE_OK ){ + return SQLITE_IOERR_WRITE; @@ -725,7 +725,7 @@ index 0000000..b1d0ac6 + return SQLITE_IOERR_WRITE; + } + u8 *compressed_data = sqlite3_malloc(max_compress_size); -+ if( compressed_data==0 ){ ++ if( compressed_data==NULL ){ + return SQLITE_NOMEM; + } + int compress_data_len = 0; @@ -741,7 +741,7 @@ index 0000000..b1d0ac6 + pCompress->bBegin = 1; + } + sqlite3_stmt *stmt = NULL; -+ const char *sql = "INSERT OR REPLACE INTO vfs_pages(data, pageno) VALUE (?,?);"; ++ const char *sql = "INSERT OR REPLACE INTO vfs_pages(data, pageno) VALUES (?,?);"; + if( sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)==SQLITE_OK ){ + sqlite3_bind_blob(stmt, 1, compressed_data, compress_data_len, SQLITE_STATIC); + sqlite3_bind_int(stmt, 2, pgno); @@ -770,8 +770,7 @@ index 0000000..b1d0ac6 + return SQLITE_CORRUPT; + } + (void)memset_s(pBuf, iAmt, 0, iAmt); -+ compress_info *compress_info = pCompress->pInfo; -+ sqlite3 *db = compress_info->pDb; ++ sqlite3 *db = pCompress->pDb; + int rc = getCompressPgsize(db, &pCompress->page_size); + if( rc!=SQLITE_OK || pCompress->page_size==0 ){ + return SQLITE_IOERR_SHORT_READ; @@ -792,13 +791,13 @@ index 0000000..b1d0ac6 + decompressed_data = sqlite3_malloc(pgsize); + if( decompressed_data==NULL ){ + sqlite3_finalize(stmt); -+ return SQLITE_CORRUPT; ++ return SQLITE_NOMEM; + } + }else{ -+ decompressed_data = (u8 *)pBuf; ++ decompressed_data = (u8*)pBuf; + } + -+ int decompressed_data_len = 0; ++ int decompress_data_len = 0; + sqlite3_bind_int(stmt, 1, pgno); + rc = sqlite3_step(stmt); + if( rc==SQLITE_ROW ){ @@ -812,12 +811,12 @@ index 0000000..b1d0ac6 + rc = SQLITE_IOERR_SHORT_READ; + goto failed; + } -+ if( decompressBuf(decompressed_data, pgsize, &decompressed_data_len, data, data_len, ++ if( decompressBuf(decompressed_data, pgsize, &decompress_data_len, data, data_len, + pCompress->compression)!=SQLITE_OK ){ + rc = SQLITE_IOERR_SHORT_READ; + goto failed; + } -+ if( decompressed_data_len!=pgsize ){ ++ if( decompress_data_len!=pgsize ){ + rc = SQLITE_IOERR_SHORT_READ; + goto failed; + } @@ -848,19 +847,21 @@ index 0000000..b1d0ac6 +static int compressClose(sqlite3_file *pFile){ + assert( pFile ); + CompressFile *pCompress = (CompressFile *)pFile; -+ compress_info *compress_info = pCompress->pInfo; -+ sqlite3 *db = compress_info->pDb; ++ sqlite3 *db = pCompress->pDb; + int rc = compressSync(pFile, 0); + if( rc!=SQLITE_OK ){ + return rc; + } -+ if( compress_info->bOutterDbOpen ){ -+ rc = sqlite3_close(db); -+ if( rc!=SQLITE_OK ){ -+ return rc; ++ if( pCompress->bOutterDbOpen ){ ++ if( db!=NULL ){ ++ rc = sqlite3_close_v2(db); ++ if( rc!=SQLITE_OK ){ ++ return rc; ++ } ++ pCompress->pDb = NULL; + } + } -+ if( compress_info->bSubDbOpen ){ ++ if( pCompress->bSubDbOpen ){ + pFile = ORIGFILE(pFile); + rc = pFile->pMethods->xClose(pFile); + } @@ -907,7 +908,7 @@ index 0000000..b1d0ac6 +} + +/* Fetch a page of a memory-mapped file */ -+static int compressFetch(sqlite3_file *pFile, sqlite_int64 iOfst, int iAmt, void **pp){ ++static int compressFetch(sqlite3_file *pFile, sqlite3_int64 iOfst, int iAmt, void **pp){ + assert( pFile ); + pFile = ORIGFILE(pFile); + if( pFile->pMethods->iVersion>2 && pFile->pMethods->xFetch ){ @@ -918,7 +919,7 @@ index 0000000..b1d0ac6 +} + +/* Release a memory-mapped page */ -+static int compressUnfetch(sqlite3_file *pFile, sqlite_int64 iOfst, void *pPage){ ++static int compressUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ + assert( pFile ); + pFile = ORIGFILE(pFile); + if( pFile->pMethods->iVersion>2 && pFile->pMethods->xUnfetch ){ @@ -927,21 +928,6 @@ index 0000000..b1d0ac6 + return SQLITE_OK; +} + -+/* Rename journal and wal file's name to identify InnerDB's file. */ -+static int compressGetJournalName(const char *zName, char **zJournalName){ -+ size_t len = strlen(zName); -+ if(( len >= 4 && strcmp(zName + len - 4, "-wal")==0 ) || -+ ( len >= 8 && strcmp(zName + len - 8, "-journal")==0 )){ -+ *zJournalName = (char *)sqlite3_malloc(strlen("compress") + strlen(zName) + 1); -+ if( *zJournalName==NULL ){ -+ return SQLITE_NOMEM; -+ } -+ strcpy(*zJournalName, zName); -+ strcpy(*zJournalName, "compress"); -+ } -+ return SQLITE_OK; -+} -+ +/* +** Open a compress file.If this file is not a journal or wal file, +** it will open a OutterDB and create vfs_pages and vfs_compression table @@ -954,31 +940,17 @@ index 0000000..b1d0ac6 + int flags, + int *pOutFlags +){ -+ compress_info *pInfo = pVfs->pAppData; + sqlite3_file *pSubFile = ORIGFILE(pFile); + CompressFile *pCompress = (CompressFile *)pFile; + int rc = SQLITE_OK; + if( !(flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB)) ){ -+ if( flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_WAL) ){ -+ flags |= SQLITE_OPEN_CREATE; -+ char *zJournalName = NULL; -+ rc = compressGetJournalName(zName, &zJournalName); -+ if( rc!=SQLITE_OK || zJournalName==NULL ){ -+ return rc; -+ } -+ rc = pInfo->pRootVfs->xOpen(pInfo->pRootVfs, zJournalName, pFile, flags, pOutFlags); -+ if( rc!=SQLITE_OK ){ -+ sqlite3_free(zJournalName); -+ } -+ return rc; -+ } -+ return pInfo->pRootVfs->xOpen(pInfo->pRootVfs, zName, pFile, flags, pOutFlags); ++ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags); + } -+ rc = pInfo->pRootVfs->xOpen(pInfo->pRootVfs, zName, pSubFile, flags, pOutFlags); ++ rc = ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pSubFile, flags, pOutFlags); + if( rc!=SQLITE_OK ){ + return rc; + } -+ pInfo->bSubDbOpen = 1; ++ pCompress->bSubDbOpen = 1; + sqlite3_int64 fileSize = 0; + rc = pSubFile->pMethods->xFileSize(pSubFile, &fileSize); + if( rc!=SQLITE_OK ){ @@ -986,17 +958,17 @@ index 0000000..b1d0ac6 + goto open_end; + } + -+ pCompress->pInfo = pInfo; + pFile->pMethods = &compress_io_methods; -+ rc = sqlite3_open_v2(zName, &pInfo->pDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, pInfo->pRootVfs->zName); ++ rc = sqlite3_open_v2(zName, &pCompress->pDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, ORIGVFS(pVfs)->zName); + if( rc!=SQLITE_OK ){ + rc = SQLITE_CANTOPEN; + goto open_end; + } -+ pInfo->bOutterDbOpen = 1; -+ sqlite3 *db = pInfo->pDb; ++ pCompress->bOutterDbOpen = 1; ++ sqlite3 *db = pCompress->pDb; + const char *pre_pragma = "PRAGMA page_size=4096;"\ -+ "PRAGMA auto_vacuum=INCREMENTAL;PRAGMA journal_mode=OFF;PRAGMA locking_mode=EXCLUSIVE;"; ++ "PRAGMA auto_vacuum=INCREMENTAL;PRAGMA journal_mode=OFF;"; ++ sqlite3_busy_timeout(db, 2000); // Set time out:2s + rc = sqlite3_exec(db, pre_pragma, NULL, NULL, NULL); + if( rc!=SQLITE_OK ){ + rc = SQLITE_CANTOPEN; @@ -1012,7 +984,7 @@ index 0000000..b1d0ac6 + rc = SQLITE_CANTOPEN; + goto open_end; + } -+ }else if( flags&SQLITE_OPEN_MAIN_DB && fileSize!=0){ ++ }else if( flags&SQLITE_OPEN_MAIN_DB && fileSize!=0 ){ + rc = SQLITE_WARNING_NOTCOMPRESSDB; + sqlite3_log(rc, "open compress database go wrong, it should be a compressed db"); + goto open_end; @@ -1029,7 +1001,7 @@ index 0000000..b1d0ac6 + } + char set_compression_sql[COMPRESSION_SQL_MAX_LENGTH] = {0}; + if( sprintf_s(set_compression_sql, COMPRESSION_SQL_MAX_LENGTH, -+ "INSERT INTO vfs_compression(compression, pagesize) VALUE (%u, 0);", g_compress_algo_load)<=0 ){ ++ "INSERT INTO vfs_compression(compression, pagesize) VALUES (%u, 0);", g_compress_algo_load)<=0 ){ + rc = SQLITE_CANTOPEN; + goto open_end; + } @@ -1044,8 +1016,8 @@ index 0000000..b1d0ac6 + if( tableExists(db, "vfs_pages") ){ + goto open_end; + } -+ const char *init_page_sql = "CREATE TABLE vfs_pages (pgno INTEGER PRIMARY KEY, data BLOB NOT NULL);"; -+ rc = sqlite3_exec(db, init_page_sql, NULL, NULL, NULL); ++ const char *create_sql = "CREATE TABLE vfs_pages (pageno INTEGER PRIMARY KEY, data BLOB NOT NULL);"; ++ rc = sqlite3_exec(db, create_sql, NULL, NULL, NULL); + if( rc!=SQLITE_OK ){ + rc = SQLITE_CANTOPEN; + } @@ -1058,19 +1030,7 @@ index 0000000..b1d0ac6 +** Delete compress file. If this file is journal or wal, need to delete the InnerDB's renamed file. +*/ +static int compressDelete(sqlite3_vfs *pVfs, const char *zName, int syncDir){ -+ compress_info *pInfo = pVfs->pAppData; -+ char *zJournalName = NULL; -+ int rc = compressGetJournalName(zName, &zJournalName); -+ if( rc!=SQLITE_OK ){ -+ return rc; -+ } -+ if( zJournalName!=NULL ){ -+ rc = pInfo->pRootVfs->xDelete(pInfo->pRootVfs, zJournalName, syncDir); -+ sqlite3_free(zJournalName); -+ return rc; -+ }else{ -+ return pInfo->pRootVfs->xDelete(pInfo->pRootVfs, zName, syncDir); -+ } ++ return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zName, syncDir); +} + +/* @@ -1082,19 +1042,7 @@ index 0000000..b1d0ac6 + int flags, + int *pResOut +){ -+ compress_info *pInfo = pVfs->pAppData; -+ char *zJournalName = NULL; -+ int rc = compressGetJournalName(zName, &zJournalName); -+ if( rc!=SQLITE_OK ){ -+ return rc; -+ } -+ if( zJournalName!=NULL ){ -+ rc = pInfo->pRootVfs->xAccess(pInfo->pRootVfs, zJournalName, flags, pResOut); -+ sqlite3_free(zJournalName); -+ return rc; -+ }else{ -+ return pInfo->pRootVfs->xAccess(pInfo->pRootVfs, zName, flags, pResOut); -+ } ++ return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zName, flags, pResOut); +} + + @@ -1108,23 +1056,19 @@ index 0000000..b1d0ac6 + } + sqlite3_vfs *default_vfs = sqlite3_vfs_find(0); + if( default_vfs==0 ){ -+ sqlite3_log(SQLITE_ERROR, "Default vfs not found!"); ++ sqlite3_log(SQLITE_ERROR, "Default vfs not found."); + return SQLITE_ERROR; + } + sqlite3_vfs *pVfs = &compress_vfs; -+ compress_info *pInfo = &compress_vfs_info; + *pVfs = *default_vfs; + pVfs->pNext = 0; + pVfs->zName = COMPRESS_VFS_NAME; -+ pVfs->pAppData = pInfo; ++ pVfs->pAppData = default_vfs; + pVfs->szOsFile = pVfs->szOsFile+sizeof(CompressFile); + + pVfs->xOpen = compressOpen; + pVfs->xDelete = compressDelete; + pVfs->xAccess = compressAccess; -+ pInfo->pRootVfs = default_vfs; -+ pInfo->bSubDbOpen = 0; -+ pInfo->bOutterDbOpen = 0; + int rc = sqlite3_vfs_register(pVfs, 0); + if( rc!=SQLITE_OK ){ + sqlite3_log(SQLITE_ERROR, "Compress vfs register error!"); @@ -1140,7 +1084,7 @@ index 0000000..b1d0ac6 +#endif /* SQLITE_ENABLE_PAGE_COMPRESS */ \ No newline at end of file diff --git a/src/sqlite3.c b/src/sqlite3.c -index be9f41d..5095b1e 100644 +index c84348b..1abddb3 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -881,6 +881,7 @@ SQLITE_API int sqlite3_exec( @@ -1161,8 +1105,8 @@ index be9f41d..5095b1e 100644 +** The xShmMap method on [sqlite3_io_methods] may use values +** between 0 and this upper bound as its "offset" argument. +*/ -+#define SQLITE_SHMMAP_IS_WRITE 0x00000001 /*Flag for xShmMap, extend file if necessary */ -+#define SQLITE_OPEN_COMPRESS_SHM 0x00010000 /*Flag for xShmMap, need to rename shm file */ ++#define SQLITE_SHMMAP_IS_WRITE 0x00000001 /* Flag for xShmMap, extend file if necessary */ ++#define SQLITE_OPEN_COMPRESS_SHM 0x00010000 /* Flag for xShmMap, need to rename shm file */ /* ** CAPI3REF: Initialize The SQLite Library @@ -1191,25 +1135,12 @@ index be9f41d..5095b1e 100644 int nRef; /* Number of pointers to this structure */ unixShmNode *pShmNode; /* Shared memory associated with this inode */ +#ifdef SQLITE_ENABLE_PAGE_COMPRESS -+ unixShmNode *pCompressShmNode; ++ unixShmNode *pCompressShmNode; /* Shared memory associated with this inode */ +#endif unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ unixInodeInfo *pPrev; /* .... doubly linked */ #if SQLITE_ENABLE_LOCKING_STYLE -@@ -40602,6 +40620,12 @@ static int closeUnixFile(sqlite3_file *id){ - OSTRACE(("CLOSE %-3d\n", pFile->h)); - OpenCounter(-1); - sqlite3_free(pFile->pPreallocatedUnused); -+#ifdef SQLITE_ENABLE_PAGE_COMPRESS -+ if( strcmp(pFile->zPath+strlen(pFile->zPath)-strlen("compress"), "compress")==0 ){ -+ sqlite3_free(*(char**)&pFile->zPath); -+ pFile->zPath = 0; -+ } -+#endif - memset(pFile, 0, sizeof(unixFile)); - return SQLITE_OK; - } -@@ -42889,14 +42913,23 @@ static int unixShmSystemLock( +@@ -42889,14 +42907,23 @@ static int unixShmSystemLock( unixFile *pFile, /* Open connection to the WAL file */ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ int ofst, /* First byte of the locking range */ @@ -1234,7 +1165,7 @@ index be9f41d..5095b1e 100644 assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); assert( pShmNode->nRef>0 || unixMutexHeld() ); -@@ -42984,9 +43017,11 @@ static int unixShmRegionPerMap(void){ +@@ -42984,9 +43011,11 @@ static int unixShmRegionPerMap(void){ ** This is not a VFS shared-memory method; it is a utility function called ** by VFS shared-memory methods. */ @@ -1249,7 +1180,7 @@ index be9f41d..5095b1e 100644 if( p && ALWAYS(p->nRef==0) ){ int nShmPerMap = unixShmRegionPerMap(); int i; -@@ -43004,11 +43039,35 @@ static void unixShmPurge(unixFile *pFd){ +@@ -43004,11 +43033,35 @@ static void unixShmPurge(unixFile *pFd){ robust_close(pFd, p->hShm, __LINE__); p->hShm = -1; } @@ -1285,7 +1216,7 @@ index be9f41d..5095b1e 100644 /* ** The DMS lock has not yet been taken on shm file pShmNode. Attempt to ** take it now. Return SQLITE_OK if successful, or an SQLite error -@@ -43018,7 +43077,11 @@ static void unixShmPurge(unixFile *pFd){ +@@ -43018,7 +43071,11 @@ static void unixShmPurge(unixFile *pFd){ ** connection and no other process already holds a lock, return ** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. */ @@ -1297,7 +1228,7 @@ index be9f41d..5095b1e 100644 struct flock lock; int rc = SQLITE_OK; -@@ -43051,7 +43114,11 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ +@@ -43051,7 +43108,11 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ pShmNode->isUnlocked = 1; rc = SQLITE_READONLY_CANTINIT; }else{ @@ -1309,7 +1240,7 @@ index be9f41d..5095b1e 100644 MarkLockStatusByRc(rc, SHM_DMS_IDX, 1, EXCLUSIVE_LOCK, LOCK_BY_PROCESS); MARK_LAST_BUSY_LINE(rc); /* The first connection to attach must truncate the -shm file. We -@@ -43071,7 +43138,11 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ +@@ -43071,7 +43132,11 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ if( rc==SQLITE_OK ){ assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); @@ -1321,9 +1252,13 @@ index be9f41d..5095b1e 100644 MarkLockStatusByRc(rc, SHM_DMS_IDX, 1, SHARED_LOCK, LOCK_BY_PROCESS); MARK_LAST_BUSY_LINE(rc); } -@@ -43113,7 +43184,11 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ +@@ -43112,8 +43177,15 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ + ** that no other processes are able to read or write the database. In ** that case, we do not really need shared memory. No shared memory ** file is created. The shared memory will be simulated with heap memory. ++** ++** If bCompressShm is true, it indicates that the shmFile needs to be renamed by ++** adding a suffix named "compress". */ +#ifdef SQLITE_ENABLE_PAGE_COMPRESS +static int unixOpenSharedMemory(unixFile *pDbFd, int bCompressShm){ @@ -1333,7 +1268,7 @@ index be9f41d..5095b1e 100644 struct unixShm *p = 0; /* The connection to be opened */ struct unixShmNode *pShmNode; /* The underlying mmapped file */ int rc = SQLITE_OK; /* Result code */ -@@ -43133,7 +43208,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ +@@ -43133,7 +43205,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ assert( unixFileMutexNotheld(pDbFd) ); unixEnterMutex(); pInode = pDbFd->pInode; @@ -1345,7 +1280,7 @@ index be9f41d..5095b1e 100644 if( pShmNode==0 ){ struct stat sStat; /* fstat() info for database file */ #ifndef SQLITE_SHM_DIRECTORY -@@ -43153,6 +43232,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ +@@ -43153,6 +43229,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; #else nShmFilename = 6 + (int)strlen(zBasePath); @@ -1357,7 +1292,7 @@ index be9f41d..5095b1e 100644 #endif pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ -@@ -43169,8 +43253,17 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ +@@ -43169,8 +43250,17 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); sqlite3FileSuffix3(pDbFd->zPath, zShm); #endif @@ -1376,7 +1311,7 @@ index be9f41d..5095b1e 100644 pShmNode->pInode = pDbFd->pInode; if( sqlite3GlobalConfig.bCoreMutex ){ pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); -@@ -43207,7 +43300,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ +@@ -43207,7 +43297,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ */ robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); @@ -1388,7 +1323,7 @@ index be9f41d..5095b1e 100644 if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; } } -@@ -43218,7 +43315,15 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ +@@ -43218,7 +43312,15 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ p->id = pShmNode->nextShmId++; #endif pShmNode->nRef++; @@ -1404,7 +1339,7 @@ index be9f41d..5095b1e 100644 unixLeaveMutex(); /* The reference count on pShmNode has already been incremented under -@@ -43250,6 +43355,10 @@ shm_open_err: +@@ -43250,6 +43352,10 @@ shm_open_err: ** ** If an error occurs, an error code is returned and *pp is set to NULL. ** @@ -1415,7 +1350,7 @@ index be9f41d..5095b1e 100644 ** Otherwise, if the bExtend parameter is 0 and the requested shared-memory ** region has not been allocated (by any client, including one running in a ** separate process), then *pp is set to NULL and SQLITE_OK returned. If -@@ -43260,12 +43369,15 @@ shm_open_err: +@@ -43260,12 +43366,15 @@ shm_open_err: ** this call as described above, then it is mapped into this processes ** address space (if it is not already), *pp is set to point to the mapped ** memory and SQLITE_OK returned. @@ -1432,7 +1367,7 @@ index be9f41d..5095b1e 100644 void volatile **pp /* OUT: Mapped memory */ ){ unixFile *pDbFd = (unixFile*)fd; -@@ -43274,18 +43386,35 @@ static int unixShmMap( +@@ -43274,18 +43383,33 @@ static int unixShmMap( int rc = SQLITE_OK; int nShmPerMap = unixShmRegionPerMap(); int nReqRegion; @@ -1443,18 +1378,17 @@ index be9f41d..5095b1e 100644 /* If the shared-memory file has not yet been opened, open it now. */ +#ifdef SQLITE_ENABLE_PAGE_COMPRESS -+ if(( bCompressShm && pDbFd->pCompressShm==0 ) || ( !bCompressShm && pDbFd->pShm==0 )){ ++ if( (bCompressShm && pDbFd->pCompressShm==0) || ( !bCompressShm && pDbFd->pShm==0 )){ + rc = unixOpenSharedMemory(pDbFd, bCompressShm); + if( rc!=SQLITE_OK ) return rc; + } -+ + p = bCompressShm ? pDbFd->pCompressShm : pDbFd->pShm; +#else if( pDbFd->pShm==0 ){ rc = unixOpenSharedMemory(pDbFd); if( rc!=SQLITE_OK ) return rc; } - +- p = pDbFd->pShm; +#endif pShmNode = p->pShmNode; @@ -1468,7 +1402,7 @@ index be9f41d..5095b1e 100644 if( rc!=SQLITE_OK ) goto shmpage_out; pShmNode->isUnlocked = 0; } -@@ -43448,8 +43577,13 @@ static int unixShmLock( +@@ -43448,8 +43572,13 @@ static int unixShmLock( int rc = SQLITE_OK; /* Result code */ u16 mask; /* Mask of locks to take or release */ int *aLock; @@ -1483,7 +1417,7 @@ index be9f41d..5095b1e 100644 if( p==0 ) { #ifdef LOG_DUMP sqlite3_log(SQLITE_IOERR_SHMLOCK, "unixShmLock-pShm, fd[%d], ofst[%d], n[%d], flags[%d]", pDbFd->h, ofst, n, flags); -@@ -43516,7 +43650,11 @@ static int unixShmLock( +@@ -43516,7 +43645,11 @@ static int unixShmLock( } if( bUnlock ){ @@ -1495,7 +1429,7 @@ index be9f41d..5095b1e 100644 if( rc==SQLITE_OK ){ memset(&aLock[ofst], 0, sizeof(int)*n); } -@@ -43540,7 +43678,11 @@ static int unixShmLock( +@@ -43540,7 +43673,11 @@ static int unixShmLock( if( aLock[ofst]<0 ){ rc = SQLITE_BUSY; }else if( aLock[ofst]==0 ){ @@ -1507,7 +1441,7 @@ index be9f41d..5095b1e 100644 useProcessLock = LOCK_BY_PROCESS; } MarkLockStatusByRc(rc, ofst, n, SHARED_LOCK, useProcessLock); -@@ -43566,7 +43708,11 @@ static int unixShmLock( +@@ -43566,7 +43703,11 @@ static int unixShmLock( /* Get the exclusive locks at the system level. Then if successful ** also update the in-memory values. */ if( rc==SQLITE_OK ){ @@ -1519,7 +1453,7 @@ index be9f41d..5095b1e 100644 useProcessLock = LOCK_BY_PROCESS; if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); -@@ -43619,9 +43765,14 @@ static int unixShmUnmap( +@@ -43619,9 +43760,14 @@ static int unixShmUnmap( unixShmNode *pShmNode; /* The underlying shared-memory file */ unixShm **pp; /* For looping over sibling connections */ unixFile *pDbFd; /* The underlying database file */ @@ -1535,7 +1469,7 @@ index be9f41d..5095b1e 100644 if( p==0 ) return SQLITE_OK; pShmNode = p->pShmNode; -@@ -43636,7 +43787,15 @@ static int unixShmUnmap( +@@ -43636,7 +43782,15 @@ static int unixShmUnmap( /* Free the connection p */ sqlite3_free(p); @@ -1551,7 +1485,7 @@ index be9f41d..5095b1e 100644 sqlite3_mutex_leave(pShmNode->pShmMutex); /* If pShmNode->nRef has reached 0, then close the underlying -@@ -50788,8 +50947,15 @@ static int winLockSharedMemory(winShmNode *pShmNode){ +@@ -50788,8 +50942,15 @@ static int winLockSharedMemory(winShmNode *pShmNode){ ** When opening a new shared-memory file, if no other instances of that ** file are currently open, in this process or in other processes, then ** the file must be truncated to zero length or have its header cleared. @@ -1567,7 +1501,7 @@ index be9f41d..5095b1e 100644 struct winShm *p; /* The connection to be opened */ winShmNode *pShmNode = 0; /* The underlying mmapped file */ int rc = SQLITE_OK; /* Result code */ -@@ -50804,6 +50970,11 @@ static int winOpenSharedMemory(winFile *pDbFd){ +@@ -50804,6 +50965,11 @@ static int winOpenSharedMemory(winFile *pDbFd){ p = sqlite3MallocZero( sizeof(*p) ); if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT; nName = sqlite3Strlen30(pDbFd->zPath); @@ -1579,7 +1513,7 @@ index be9f41d..5095b1e 100644 pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); if( pNew==0 ){ sqlite3_free(p); -@@ -50812,6 +50983,11 @@ static int winOpenSharedMemory(winFile *pDbFd){ +@@ -50812,6 +50978,11 @@ static int winOpenSharedMemory(winFile *pDbFd){ pNew->zFilename = (char*)&pNew[1]; sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); @@ -1591,7 +1525,7 @@ index be9f41d..5095b1e 100644 /* Look to see if there is an existing winShmNode that can be used. ** If no matching winShmNode currently exists, create a new one. -@@ -51069,6 +51245,10 @@ static void winShmBarrier( +@@ -51069,6 +51240,10 @@ static void winShmBarrier( ** ** If an error occurs, an error code is returned and *pp is set to NULL. ** @@ -1602,7 +1536,7 @@ index be9f41d..5095b1e 100644 ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory ** region has not been allocated (by any client, including one running in a ** separate process), then *pp is set to NULL and SQLITE_OK returned. If -@@ -51079,12 +51259,15 @@ static void winShmBarrier( +@@ -51079,12 +51254,15 @@ static void winShmBarrier( ** this call as described above, then it is mapped into this processes ** address space (if it is not already), *pp is set to point to the mapped ** memory and SQLITE_OK returned. @@ -1619,7 +1553,7 @@ index be9f41d..5095b1e 100644 void volatile **pp /* OUT: Mapped memory */ ){ winFile *pDbFd = (winFile*)fd; -@@ -51092,10 +51275,18 @@ static int winShmMap( +@@ -51092,10 +51270,18 @@ static int winShmMap( winShmNode *pShmNode; DWORD protect = PAGE_READWRITE; DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ; @@ -1638,7 +1572,7 @@ index be9f41d..5095b1e 100644 if( rc!=SQLITE_OK ) return rc; pShm = pDbFd->pShm; assert( pShm!=0 ); -@@ -57775,7 +57966,7 @@ struct PagerSavepoint { +@@ -57775,7 +57961,7 @@ struct PagerSavepoint { #endif }; @@ -1647,7 +1581,80 @@ index be9f41d..5095b1e 100644 #undef SQLITE_META_DWR #endif -@@ -66177,6 +66368,7 @@ static SQLITE_NOINLINE int walIndexPageRealloc( +@@ -62360,7 +62546,30 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + ** that is used by sqlite3_filename_database() and kin also depend on the + ** specific formatting and order of the various filenames, so if the format + ** changes here, be sure to change it there as well. ++ ** ++ ** Addition, in case of enable page compression, journal&WAL filename will add a file extension:"compress" ++ ** So the final layout in memory is as follows: ++ ** ++ ** Pager object (sizeof(Pager) bytes) ++ ** PCache object (sqlite3PcacheSize() bytes) ++ ** Database file handle (pVfs->szOsFile bytes) ++ ** Sub-journal file handle (journalFileSize bytes) ++ ** Main journal file handle (journalFileSize bytes) ++ ** Ptr back to the Pager (sizeof(Pager*) bytes) ++ ** \0\0\0\0 database prefix (4 bytes) ++ ** Database file name (nPathname+1 bytes) ++ ** URI query parameters (nUriByte bytes) ++ ** Journal filename (nPathname+16+1 bytes) ++ ** WAL filename (nPathname+12+1 bytes) ++ ** \0\0\0 terminator (3 bytes) ++ ** + */ ++ int fileExtSz = 0; ++#ifdef SQLITE_ENABLE_PAGE_COMPRESS ++ if( sqlite3_stricmp(pVfs->zName, "compressvfs")==0 ){ ++ fileExtSz = 8; /* 8 means the size of suffix:"compress" */ ++ } ++#endif + assert( SQLITE_PTRSIZE==sizeof(Pager*) ); + pPtr = (u8 *)sqlite3MallocZero( + ROUND8(sizeof(*pPager)) + /* Pager structure */ +@@ -62371,9 +62580,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + 4 + /* Database prefix */ + nPathname + 1 + /* database filename */ + nUriByte + /* query parameters */ +- nPathname + 8 + 1 + /* Journal filename */ ++ nPathname + 8 + fileExtSz + 1 + /* Journal filename */ + #ifndef SQLITE_OMIT_WAL +- nPathname + 4 + 1 + /* WAL filename */ ++ nPathname + 4 + fileExtSz + 1 + /* WAL filename */ + #endif + 3 /* Terminator */ + ); +@@ -62407,7 +62616,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + if( nPathname>0 ){ + pPager->zJournal = (char*)pPtr; + memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; +- memcpy(pPtr, "-journal",8); pPtr += 8 + 1; ++ memcpy(pPtr, "-journal",8); pPtr += 8; ++#ifdef SQLITE_ENABLE_PAGE_COMPRESS ++ if( fileExtSz>0 ){ /* 8 means the size of string:"compress" */ ++ memcpy(pPtr, "compress", 8); pPtr += fileExtSz; ++ } ++#endif ++ pPtr += 1; /* Skip zero suffix */ + #ifdef SQLITE_ENABLE_8_3_NAMES + sqlite3FileSuffix3(zFilename,pPager->zJournal); + pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1); +@@ -62421,7 +62636,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + if( nPathname>0 ){ + pPager->zWal = (char*)pPtr; + memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; +- memcpy(pPtr, "-wal", 4); pPtr += 4 + 1; ++ memcpy(pPtr, "-wal", 4); pPtr += 4; ++#ifdef SQLITE_ENABLE_PAGE_COMPRESS ++ if( fileExtSz>0 ){ /* 8 means the size of string:"compress" */ ++ memcpy(pPtr, "compress", 8); pPtr += fileExtSz; ++ } ++#endif ++ pPtr += 1; /* Skip zero suffix */ + #ifdef SQLITE_ENABLE_8_3_NAMES + sqlite3FileSuffix3(zFilename, pPager->zWal); + pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1); +@@ -66177,6 +66398,7 @@ static SQLITE_NOINLINE int walIndexPageRealloc( pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; }else{ @@ -1655,7 +1662,7 @@ index be9f41d..5095b1e 100644 rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] ); -@@ -137863,6 +138055,9 @@ typedef int (*sqlite3_loadext_entry)( +@@ -137863,6 +138085,9 @@ typedef int (*sqlite3_loadext_entry)( /* clean the binlog of the db */ #define sqlite3_clean_binlog sqlite3_api->clean_binlog #endif /* SQLITE_ENABLE_BINLOG */ @@ -1665,7 +1672,7 @@ index be9f41d..5095b1e 100644 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) -@@ -183070,6 +183265,188 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ +@@ -183070,6 +183295,188 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ return oldLimit; /* IMP: R-53341-35419 */ } @@ -1783,7 +1790,7 @@ index be9f41d..5095b1e 100644 + int compression = 0; + sqlite3_stmt *stmt = NULL; + u8 *decompressed_data = NULL; -+ int openFlags = (O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY|O_NOFOLLOW); ++ int openFlags = (O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY|O_NOFOLLOW); /* Flags to pass to open() */ + int fd = robust_open(destDbPath, openFlags, 0); + if( fd<0 ){ + sqlite3_log(SQLITE_ERROR, "Failed to open destDb file!"); @@ -1854,14 +1861,14 @@ index be9f41d..5095b1e 100644 /* ** This function is used to parse both URIs and non-URI filenames passed by the ** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database -@@ -183314,6 +183691,17 @@ SQLITE_PRIVATE int sqlite3ParseUri( +@@ -183314,6 +183721,17 @@ SQLITE_PRIVATE int sqlite3ParseUri( flags &= ~SQLITE_OPEN_URI; } +#ifdef SQLITE_ENABLE_PAGE_COMPRESS + if( sqlite3_stricmp(zVfs, "compressvfs")==0 ){ + rc = sqlite3CompressVFSModuleInit(); -+ if( rc!= SQLITE_OK ){ ++ if( rc!=SQLITE_OK ){ + *pzErrMsg = sqlite3_mprintf("load so of compressvfs error."); + rc = SQLITE_ERROR; + goto parse_uri_out; @@ -1872,60 +1879,147 @@ index be9f41d..5095b1e 100644 *ppVfs = sqlite3_vfs_find(zVfs); if( *ppVfs==0 ){ *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs); -@@ -256147,9 +256535,9 @@ static int PragmaCksumPersistEnable(sqlite3 *db, int iDb, Parse *parse, const ch - } - return 1; - } --extern sqlite3_file *sqlite3_get_orig_file(sqlite3_file *file); +@@ -254405,6 +254823,50 @@ SQLITE_API int sqlite3_stmt_init( + SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } + /************************** End of sqlite3.c ******************************/ + ++#ifdef SQLITE_CKSUMVFS_STATIC +extern sqlite3_file *cksmvfsGetOrigFile(sqlite3_file *file); - #else --static sqlite3_file *sqlite3_get_orig_file(sqlite3_file *file) { ++#else +static sqlite3_file *cksmvfsGetOrigFile(sqlite3_file *file) { - return file; - } - #endif /* SQLITE_CKSUMVFS_STATIC */ -@@ -256157,13 +256545,22 @@ static sqlite3_file *sqlite3_get_orig_file(sqlite3_file *file) { - #if SQLITE_OS_UNIX - #define SQLITE_CHECK_FILE_ID_UNIX 1 - #define SQLITE_CHECK_FILE_ID_CKSM 2 ++ return file; ++} ++#endif /* SQLITE_CKSUMVFS_STATIC */ ++ ++#define SQLITE_CHECK_FILE_ID_UNIX 1 ++#define SQLITE_CHECK_FILE_ID_CKSM 2 +#define SQLITE_CHECK_FILE_ID_COMPRESS 3 - --// checkFileId should not be 0, it must be SQLITE_CHECK_FILE_ID_UNIX(1) or SQLITE_CHECK_FILE_ID_CKSM(2) ++ ++static u8 Sqlite3GetCheckFileId(const sqlite3_vfs *vfs){ ++ if( vfs==NULL ){ ++ return 0; ++ }else if( sqlite3_stricmp(vfs->zName, "unix")==0 ){ ++ return SQLITE_CHECK_FILE_ID_UNIX; ++ }else if( sqlite3_stricmp(vfs->zName, "cksmvfs")==0 ){ ++ return SQLITE_CHECK_FILE_ID_CKSM; ++ }else if( sqlite3_stricmp(vfs->zName, "compressvfs")==0 ){ ++ return SQLITE_CHECK_FILE_ID_COMPRESS; ++ } ++ sqlite3_log(SQLITE_WARNING_DUMP, "Not support pVfs type %s", vfs->zName); ++ return 0; ++} ++ ++#if SQLITE_OS_UNIX +// checkFileId should not be 0 +// it must be SQLITE_CHECK_FILE_ID_UNIX(1) or SQLITE_CHECK_FILE_ID_CKSM(2) or SQLITE_CHECK_FILE_ID_COMPRESS(3) - static unixFile *Sqlite3GetUnixFile(sqlite3_file *file, u8 checkFileId) { -- if (checkFileId == SQLITE_CHECK_FILE_ID_UNIX) { -+ if( checkFileId == SQLITE_CHECK_FILE_ID_UNIX ){ - return (unixFile*)file; -+ }else if( checkFileId == SQLITE_CHECK_FILE_ID_CKSM ){ ++static unixFile *Sqlite3GetUnixFile(sqlite3_file *file, u8 checkFileId){ ++ if( checkFileId==SQLITE_CHECK_FILE_ID_UNIX ){ ++ return (unixFile*)file; ++ }else if( checkFileId==SQLITE_CHECK_FILE_ID_CKSM ){ + return (unixFile*)cksmvfsGetOrigFile(file); + } +#ifdef SQLITE_ENABLE_PAGE_COMPRESS -+ if( compressvfsGetOrigFilePtr==NULL ){ ++ if( compressvfsGetOrigFilePtr!=NULL ){ + return (unixFile*)compressvfsGetOrigFilePtr(file); - } -- return (unixFile*)sqlite3_get_orig_file(file); ++ } +#endif + return (unixFile*)file; ++} ++#endif /* SQLITE_OS_UNIX */ ++ + #ifdef SQLITE_HAS_CODEC + /************** Begin file hw_codec_openssl.h *******************************/ + #ifndef EXPOSE_INTERNAL_FUNC +@@ -255290,7 +255752,7 @@ CODEC_STATIC void sqlite3CodecTransPgno(Pgno input, unsigned char *output){ + output[1] = (u8)(input>>8); + output[2] = (u8)(input>>16); + output[3] = (u8)(input>>24); +-#endif ++#endif /* CIPHER_BIG_ENDAIN */ } - #endif /* SQLITE_OS_UNIX */ -@@ -256460,6 +256857,8 @@ static MetaDwrHdr *AllocInitMetaHeaderDwr(Pager *pPager) { - hdr->checkFileId = SQLITE_CHECK_FILE_ID_UNIX; - } else if (sqlite3_stricmp(pPager->pVfs->zName, "cksmvfs") == 0) { - hdr->checkFileId = SQLITE_CHECK_FILE_ID_CKSM; -+ } else if (sqlite3_stricmp(pPager->pVfs->zName, "compressvfs") == 0) { -+ hdr->checkFileId = SQLITE_CHECK_FILE_ID_COMPRESS; - } else { - hdr->checkFileId = 0; + CODEC_STATIC int sqlite3CodecHmac(KeyContext *ctx, Pgno pgno, int bufferSize, unsigned char *input, unsigned char *output){ +@@ -256147,26 +256609,8 @@ static int PragmaCksumPersistEnable(sqlite3 *db, int iDb, Parse *parse, const ch } -@@ -257407,14 +257806,23 @@ static void DumpTrxProcessLocks(unixFile *file, char *dumpBuf, int dumpBufLen) + return 1; + } +-extern sqlite3_file *sqlite3_get_orig_file(sqlite3_file *file); +-#else +-static sqlite3_file *sqlite3_get_orig_file(sqlite3_file *file) { +- return file; +-} + #endif /* SQLITE_CKSUMVFS_STATIC */ + +-#if SQLITE_OS_UNIX +-#define SQLITE_CHECK_FILE_ID_UNIX 1 +-#define SQLITE_CHECK_FILE_ID_CKSM 2 +- +-// checkFileId should not be 0, it must be SQLITE_CHECK_FILE_ID_UNIX(1) or SQLITE_CHECK_FILE_ID_CKSM(2) +-static unixFile *Sqlite3GetUnixFile(sqlite3_file *file, u8 checkFileId) { +- if (checkFileId == SQLITE_CHECK_FILE_ID_UNIX) { +- return (unixFile*)file; +- } +- return (unixFile*)sqlite3_get_orig_file(file); +-} +-#endif /* SQLITE_OS_UNIX */ +- + #ifdef SQLITE_META_DWR + #define META_DWR_MAX_PAGES 500 + #define META_DWR_MAGIC 0x234A86D9 +@@ -256454,15 +256898,7 @@ static MetaDwrHdr *AllocInitMetaHeaderDwr(Pager *pPager) { + MetaDwrReleaseHdr(hdr); + return NULL; + } +- if (pPager->pVfs==NULL) { +- hdr->checkFileId = 0; +- } else if (sqlite3_stricmp(pPager->pVfs->zName, "unix") == 0) { +- hdr->checkFileId = SQLITE_CHECK_FILE_ID_UNIX; +- } else if (sqlite3_stricmp(pPager->pVfs->zName, "cksmvfs") == 0) { +- hdr->checkFileId = SQLITE_CHECK_FILE_ID_CKSM; +- } else { +- hdr->checkFileId = 0; +- } ++ hdr->checkFileId = Sqlite3GetCheckFileId(pPager->pVfs); + return hdr; + } + +@@ -257156,25 +257592,19 @@ CHK_RESTORE_OUT: + static inline u8 IsConnectionValidForCheck(Pager *pPager) + { + #if SQLITE_OS_UNIX +- if (pPager->pVfs == NULL) { ++ u8 checkFileId = Sqlite3GetCheckFileId(pPager->pVfs); ++ if( checkFileId==0 ){ + return 0; + } +- if (sqlite3_stricmp(pPager->pVfs->zName, "unix") != 0 && sqlite3_stricmp(pPager->pVfs->zName, "cksmvfs") != 0) { +- return 0; +- } +- u8 checkFileId = SQLITE_CHECK_FILE_ID_UNIX; +- if (sqlite3_stricmp(pPager->pVfs->zName, "cksmvfs") == 0) { +- checkFileId = SQLITE_CHECK_FILE_ID_CKSM; +- } + unixFile *fd = Sqlite3GetUnixFile(pPager->fd, checkFileId); + // unix and only one connection exist +- if (fd == NULL || fd->pInode == NULL || fd->pInode->nRef != 1) { ++ if (fd == NULL || fd->pInode == NULL || fd->pInode->nRef != (checkFileId==SQLITE_CHECK_FILE_ID_COMPRESS ? 2 : 1)) { + return 0; + } + return 1; + #else + return 0; +-#endif ++#endif /* SQLITE_OS_UNIX */ + } + + static int MetaDwrOpenAndCheck(Btree *pBt) +@@ -257407,14 +257837,23 @@ static void DumpTrxProcessLocks(unixFile *file, char *dumpBuf, int dumpBufLen) static void DumpWalLocks(unixFile *file, u8 walEnabled, char *dumpBuf, int dumpBufLen) { +#ifdef SQLITE_ENABLE_PAGE_COMPRESS -+ if ((file->pShm == NULL || file->pShm->pShmNode == NULL) && -+ (file->pCompressShm == NULL || file->pCompressShm->pShmNode == NULL)) { ++ if( (file->pShm == NULL || file->pShm->pShmNode == NULL) && ++ (file->pCompressShm == NULL || file->pCompressShm->pShmNode == NULL) ){ +#else if (file->pShm == NULL || file->pShm->pShmNode == NULL) { +#endif @@ -1936,14 +2030,48 @@ index be9f41d..5095b1e 100644 sqlite3_log(SQLITE_ERROR, "[SQLite] walEnabled false"); } +#ifdef SQLITE_ENABLE_PAGE_COMPRESS -+ unixShmNode *pShmNode = file->pShm->pShmNode == NULL ? file->pCompressShm->pShmNode : file->pShm->pShmNode; ++ unixShmNode *pShmNode = (file->pShm == NULL || file->pShm->pShmNode == NULL) ? file->pCompressShm->pShmNode : file->pShm->pShmNode; +#else unixShmNode *pShmNode = file->pShm->pShmNode; +#endif char *tmp = dumpBuf; int availLen = dumpBufLen - 1; dumpBuf[availLen] = '\0'; -@@ -258617,6 +259025,11 @@ struct sqlite3_api_routines_hw { +@@ -257458,14 +257897,8 @@ static void DumpLocksByWal(Wal *pWal) + sqlite3_log(SQLITE_ERROR, "Wal ptr is NULL!"); + return; + } +- u8 checkFileId = 0; +- if (pWal->pVfs==NULL) { +- return; +- } else if (sqlite3_stricmp(pWal->pVfs->zName, "unix") == 0) { +- checkFileId = SQLITE_CHECK_FILE_ID_UNIX; +- } else if (sqlite3_stricmp(pWal->pVfs->zName, "cksmvfs") == 0) { +- checkFileId = SQLITE_CHECK_FILE_ID_CKSM; +- } else { ++ u8 checkFileId = Sqlite3GetCheckFileId(pWal->pVfs); ++ if( checkFileId==0 ){ + return; + } + DumpLocksInfo(Sqlite3GetUnixFile(pWal->pDbFd, checkFileId), 1); +@@ -257478,14 +257911,8 @@ static void DumpLocksByPager(Pager *pPager) + sqlite3_log(SQLITE_ERROR, "Pager ptr is NULL!"); + return; + } +- u8 checkFileId = 0; +- if (pPager->pVfs==NULL) { +- return; +- } else if (sqlite3_stricmp(pPager->pVfs->zName, "unix") == 0) { +- checkFileId = SQLITE_CHECK_FILE_ID_UNIX; +- } else if (sqlite3_stricmp(pPager->pVfs->zName, "cksmvfs") == 0) { +- checkFileId = SQLITE_CHECK_FILE_ID_CKSM; +- } else { ++ u8 checkFileId = Sqlite3GetCheckFileId(pPager->pVfs); ++ if( checkFileId==0 ){ + return; + } + #ifndef SQLITE_OMIT_WAL +@@ -258615,6 +259042,11 @@ struct sqlite3_api_routines_hw { int (*is_support_binlog)(void); int (*replay_binlog)(sqlite3*, sqlite3*); int (*clean_binlog)(sqlite3*, BinlogFileCleanModeE); @@ -1951,11 +2079,11 @@ index be9f41d..5095b1e 100644 + int (*compressdb_backup)(sqlite3*, const char*); +#else + void *dymmyFunc1; -+#endif ++#endif /* SQLITE_ENABLE_PAGE_COMPRESS */ }; typedef struct sqlite3_api_routines_hw sqlite3_api_routines_hw; -@@ -258643,6 +259056,11 @@ static const sqlite3_api_routines_hw sqlite3HwApis = { +@@ -258641,6 +259073,11 @@ static const sqlite3_api_routines_hw sqlite3HwApis = { 0, 0, #endif/* SQLITE_ENABLE_BINLOG */ @@ -1968,5 +2096,5 @@ index be9f41d..5095b1e 100644 EXPORT_SYMBOLS const sqlite3_api_routines *sqlite3_export_symbols = &sqlite3Apis; -- -2.46.0.windows.1 +2.47.0.windows.2 diff --git a/patch/0012-Bugfix-on-current-version.patch b/patch/0012-Bugfix-on-current-version.patch index 526bfcd..81f8947 100644 --- a/patch/0012-Bugfix-on-current-version.patch +++ b/patch/0012-Bugfix-on-current-version.patch @@ -1,17 +1,17 @@ -From 039a72cf82f44a36eb3863f55c6d135a5f913a39 Mon Sep 17 00:00:00 2001 +From 1b7426f474315fbc3a0468675e3e99a3ead7a6c9 Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> -Date: Thu, 10 Jul 2025 10:46:18 +0800 -Subject: [PATCH 4/4] Bugfix on current version +Date: Wed, 23 Jul 2025 21:22:02 +0800 +Subject: [PATCH 12/12] Bugfix on current version --- src/sqlite3.c | 251 ++++++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 203 insertions(+), 48 deletions(-) + 1 file changed, 204 insertions(+), 47 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c -index 3dc54be..a683ca7 100644 +index 1abddb3..88c8054 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c -@@ -38802,8 +38802,8 @@ static void enableDbFileDelMonitor(int32_t fd) +@@ -38805,8 +38805,8 @@ static void enableDbFileDelMonitor(int32_t fd) } flags |= HMFS_MONITOR_FL; ret = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags); @@ -22,7 +22,7 @@ index 3dc54be..a683ca7 100644 } } -@@ -57978,6 +57978,8 @@ static void MetaDwrCheckVacuum(BtShared *pBt); +@@ -57976,6 +57976,8 @@ static void MetaDwrCheckVacuum(BtShared *pBt); static int MetaDwrRecoverAndBeginTran(Btree *pBt, int wrflag, int *pSchemaVersion); static int MetaDwrOpenAndCheck(Btree *pBt); static void MetaDwrDisable(Btree *pBt); @@ -31,7 +31,7 @@ index 3dc54be..a683ca7 100644 #define META_HEADER_CHANGED 1 #define META_SCHEMA_CHANGED 2 #define META_IN_RECOVERY 1 -@@ -59756,11 +59758,12 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ +@@ -59754,11 +59756,12 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); } #ifdef SQLITE_META_DWR @@ -49,7 +49,7 @@ index 3dc54be..a683ca7 100644 } #endif if( pagerUseWal(pPager) ){ -@@ -73740,7 +73743,13 @@ static void zeroPage(MemPage *pPage, int flags){ +@@ -73773,7 +73776,13 @@ static void zeroPage(MemPage *pPage, int flags){ data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); pPage->nFree = (u16)(pBt->usableSize - first); @@ -64,7 +64,7 @@ index 3dc54be..a683ca7 100644 pPage->cellOffset = first; pPage->aDataEnd = &data[pBt->pageSize]; pPage->aCellIdx = &data[first]; -@@ -73949,7 +73958,9 @@ static void pageReinit(DbPage *pData){ +@@ -73982,7 +73991,9 @@ static void pageReinit(DbPage *pData){ ** But no harm is done by this. And it is very important that ** btreeInitPage() be called on every btree page so we make ** the call for every page that comes in for re-initializing. */ @@ -75,7 +75,7 @@ index 3dc54be..a683ca7 100644 } } } -@@ -74865,6 +74876,11 @@ static int lockBtree(BtShared *pBt){ +@@ -74898,6 +74909,11 @@ static int lockBtree(BtShared *pBt){ } if( nPage>nPageFile ){ if( sqlite3WritableSchema(pBt->db)==0 ){ @@ -87,7 +87,7 @@ index 3dc54be..a683ca7 100644 rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; }else{ -@@ -121725,8 +121741,8 @@ static void attachFunc( +@@ -121758,8 +121774,8 @@ static void attachFunc( if( rc==SQLITE_OK ){ extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); @@ -98,7 +98,7 @@ index 3dc54be..a683ca7 100644 int t = sqlite3_value_type(argv[2]); switch( t ){ case SQLITE_INTEGER: -@@ -121743,14 +121759,7 @@ static void attachFunc( +@@ -121776,14 +121792,7 @@ static void attachFunc( break; case SQLITE_NULL: @@ -114,7 +114,7 @@ index 3dc54be..a683ca7 100644 break; } } -@@ -184118,10 +184127,12 @@ opendb_out: +@@ -184151,10 +184160,12 @@ opendb_out: db->eOpenState = SQLITE_STATE_SICK; } #ifdef SQLITE_ENABLE_DROPTABLE_CALLBACK @@ -131,7 +131,7 @@ index 3dc54be..a683ca7 100644 #endif /* SQLITE_ENABLE_DROPTABLE_CALLBACK */ #ifdef SQLITE_ENABLE_BINLOG sqlite3BinlogReset(db); -@@ -204567,6 +204578,39 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ +@@ -204600,6 +204611,39 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ return rc; } @@ -171,7 +171,7 @@ index 3dc54be..a683ca7 100644 /* ** Implementation of offsets() function. */ -@@ -204603,6 +204647,12 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( +@@ -204636,6 +204680,12 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( sCtx.iDocid = pCsr->iPrevId; sCtx.pCsr = pCsr; @@ -184,11 +184,10 @@ index 3dc54be..a683ca7 100644 /* Loop through the table columns, appending offset information to ** string-buffer res for each column. */ -@@ -254789,7 +254839,20 @@ SQLITE_API int sqlite3_stmt_init( - /* Return the source-id for this library */ +@@ -254823,6 +254873,21 @@ SQLITE_API int sqlite3_stmt_init( SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /************************** End of sqlite3.c ******************************/ -- + +#if SQLITE_OS_UNIX +#include +#include @@ -203,10 +202,11 @@ index 3dc54be..a683ca7 100644 +#endif +} +#endif - #ifdef SQLITE_HAS_CODEC - /************** Begin file hw_codec_openssl.h *******************************/ - #ifndef EXPOSE_INTERNAL_FUNC -@@ -255983,6 +256046,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *pKey, int nKey){ ++ + #ifdef SQLITE_CKSUMVFS_STATIC + extern sqlite3_file *cksmvfsGetOrigFile(sqlite3_file *file); + #else +@@ -256060,6 +256125,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *pKey, int nKey){ } } #endif @@ -214,7 +214,7 @@ index 3dc54be..a683ca7 100644 #ifdef SQLITE_CODEC_ATTACH_CHANGED int rc = sqlite3CodecInitContext(ctx, p, pKey, nKey, nDb); #else -@@ -256586,7 +256650,12 @@ typedef struct MetaDwrHdr { +@@ -256636,7 +256702,12 @@ typedef struct MetaDwrHdr { u32 pageSz; u32 pageCnt; u64 dbFileInode; @@ -228,7 +228,7 @@ index 3dc54be..a683ca7 100644 u32 checkSum; u8 *zones; Pgno *pages; -@@ -256951,6 +257020,87 @@ static inline u64 CaculateMetaDwrWriteOffset(int pageSz, u32 idx, u8 zone) { +@@ -256991,6 +257062,87 @@ static inline u64 CaculateMetaDwrWriteOffset(int pageSz, u32 idx, u8 zone) { return META_DWR_HEADER_PAGE_SIZE + pageSz * (idx * 2 + zone); } @@ -316,7 +316,7 @@ index 3dc54be..a683ca7 100644 static void MetaDwrUpdateHeaderDbInfo(BtShared *pBt) { MetaDwrHdr *hdr = pBt->pPager->metaHdr; // 28 offset: dbSize, freelist pageNo, freelist pages count, schema cookie -@@ -257171,11 +257321,12 @@ static int MetaDwrOpenFile(Pager *pPager, u8 openCreate) { +@@ -257211,11 +257363,12 @@ static int MetaDwrOpenFile(Pager *pPager, u8 openCreate) { if (pPager->metaMapPage == NULL) { sqlite3_int64 sz = META_DWR_HEADER_PAGE_SIZE; sqlite3OsFileControlHint(metaFd, SQLITE_FCNTL_CHUNK_SIZE, &sz); @@ -334,7 +334,7 @@ index 3dc54be..a683ca7 100644 } } #endif /* SQLITE_OS_UNIX */ -@@ -257549,7 +257700,7 @@ CHK_RESTORE_OUT: +@@ -257589,7 +257742,7 @@ CHK_RESTORE_OUT: return rc; } @@ -342,9 +342,9 @@ index 3dc54be..a683ca7 100644 +static inline u8 IsOnlyOneConnection(Pager *pPager) { #if SQLITE_OS_UNIX - if (pPager->pVfs == NULL) { -@@ -257563,10 +257714,18 @@ static inline u8 IsConnectionValidForCheck(Pager *pPager) - checkFileId = SQLITE_CHECK_FILE_ID_CKSM; + u8 checkFileId = Sqlite3GetCheckFileId(pPager->pVfs); +@@ -257597,10 +257750,18 @@ static inline u8 IsConnectionValidForCheck(Pager *pPager) + return 0; } unixFile *fd = Sqlite3GetUnixFile(pPager->fd, checkFileId); + if (fd == NULL || fd->pInode == NULL) { @@ -354,8 +354,8 @@ index 3dc54be..a683ca7 100644 + unixInodeInfo *pInode = fd->pInode; + sqlite3_mutex_enter(pInode->pLockMutex); // unix and only one connection exist -- if (fd == NULL || fd->pInode == NULL || fd->pInode->nRef != 1) { -+ if (pInode->nRef != 1) { +- if (fd == NULL || fd->pInode == NULL || fd->pInode->nRef != (checkFileId==SQLITE_CHECK_FILE_ID_COMPRESS ? 2 : 1)) { ++ if (pInode->nRef != (checkFileId==SQLITE_CHECK_FILE_ID_COMPRESS ? 2 : 1)) { + sqlite3_mutex_leave(pInode->pLockMutex); return 0; } @@ -363,7 +363,7 @@ index 3dc54be..a683ca7 100644 return 1; #else return 0; -@@ -257576,7 +257735,7 @@ static inline u8 IsConnectionValidForCheck(Pager *pPager) +@@ -257610,7 +257771,7 @@ static inline u8 IsConnectionValidForCheck(Pager *pPager) static int MetaDwrOpenAndCheck(Btree *pBt) { Pager *pPager = pBt->pBt->pPager; @@ -372,7 +372,7 @@ index 3dc54be..a683ca7 100644 return SQLITE_OK; } #ifdef SQLITE_HAS_CODEC -@@ -257621,7 +257780,7 @@ DWR_OPEN_OUT: +@@ -257655,7 +257816,7 @@ DWR_OPEN_OUT: static void MetaDwrDisable(Btree *pBt) { Pager *pPager = pBt->pBt->pPager; @@ -381,7 +381,7 @@ index 3dc54be..a683ca7 100644 return; } #ifdef SQLITE_HAS_CODEC -@@ -257647,19 +257806,6 @@ static void MetaDwrDisable(Btree *pBt) +@@ -257681,19 +257842,6 @@ static void MetaDwrDisable(Btree *pBt) #endif /* SQLITE_META_DWR */ #if SQLITE_OS_UNIX @@ -401,7 +401,7 @@ index 3dc54be..a683ca7 100644 static void ResetLockStatus(void) { (void)memset(&g_lockStatus, 0, sizeof(g_lockStatus)); -@@ -257763,8 +257909,13 @@ static inline const char *FlockToName(int l_type) +@@ -257797,8 +257945,13 @@ static inline const char *FlockToName(int l_type) static int DumpProcessLocks(int fd, struct flock *lock, const char *lockName, char *dumpBuf, int bufLen) { @@ -416,7 +416,7 @@ index 3dc54be..a683ca7 100644 sqlite3_log(SQLITE_ERROR, "[SQLite]Get wal file lock ofs %u failed, errno: %d", lock->l_start, errno); return 0; } -@@ -259021,7 +259172,11 @@ struct sqlite3_api_routines_hw { +@@ -259041,7 +259194,11 @@ struct sqlite3_api_routines_hw { int (*rekey_v2)(sqlite3*,const char*,const void*,int); int (*is_support_binlog)(void); int (*replay_binlog)(sqlite3*, sqlite3*); diff --git a/unittest/common.cpp b/unittest/common.cpp index 9f98f94..c8ac153 100644 --- a/unittest/common.cpp +++ b/unittest/common.cpp @@ -87,5 +87,15 @@ int Common::MakeDir(const char *dir) } return TEST_STATUS_OK; } + +bool Common::IsFileExist(const char *fullPath) +{ + struct stat statBuf; + if (stat(fullPath, &statBuf) < 0) { + return false; + } + return S_ISREG(statBuf.st_mode); +} + } // namespace SQLiteTest } // namespace OHOS \ No newline at end of file diff --git a/unittest/common.h b/unittest/common.h index f10c192..3468644 100644 --- a/unittest/common.h +++ b/unittest/common.h @@ -25,6 +25,7 @@ class Common { public: static int RemoveDir(const char *dir); static int MakeDir(const char *dir); + static bool IsFileExist(const char *fullPath); }; } // namespace SQLiteTest } // namespace OHOS diff --git a/unittest/sqlite_compress_test.cpp b/unittest/sqlite_compress_test.cpp index cb4bc2b..338a684 100644 --- a/unittest/sqlite_compress_test.cpp +++ b/unittest/sqlite_compress_test.cpp @@ -230,4 +230,126 @@ HWTEST_F(SQLiteCompressTest, CompressTest003, TestSize.Level0) UtCheckDb(dbPath2, TEST_PRESET_TABLE_COUNT + 1); } +/** + * @tc.name: CompressTest004 + * @tc.desc: Test to create new db and enable page compression + * @tc.type: FUNC + */ +HWTEST_F(SQLiteCompressTest, CompressTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create a brand new db while page compression enabled with sqlite3_open_v2 + * @tc.expected: step1. Execute successfully + */ + std::string dbPath1 = TEST_DIR "/compresstest0040.db"; + sqlite3 *compDb = nullptr; + EXPECT_EQ(sqlite3_open_v2(dbPath1.c_str(), &compDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"), + SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DDL_CREATE_DEMO.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DML_INSERT_DEMO.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps: step2. Set meta double write enable through Pragma statement + * @tc.expected: step2. Execute successfully + */ + EXPECT_EQ(sqlite3_exec(compDb, "PRAGMA meta_double_write=enabled;", nullptr, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps: step3. Set journal mode as WAL through Pragma statement + * @tc.expected: step3. Execute successfully + */ + EXPECT_EQ(sqlite3_exec(compDb, "PRAGMA journal_mode=WAL;", nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DDL_CREATE_PHONE.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps: step4. Set WAL file persist + * @tc.expected: step4. Execute successfully + */ + int code = 1; + EXPECT_EQ(sqlite3_file_control(compDb, "main", SQLITE_FCNTL_PERSIST_WAL, &code), SQLITE_OK); + sqlite3_close_v2(compDb); + /** + * @tc.steps: step5. Check result, files should exist + * @tc.expected: step4. Execute successfully + */ + std::string wal = dbPath1 + "-walcompress"; + std::string shm = dbPath1 + "-shmcompress"; + std::string dwr = dbPath1 + "-dwr"; + EXPECT_TRUE(Common::IsFileExist(wal.c_str())); + EXPECT_TRUE(Common::IsFileExist(shm.c_str())); + EXPECT_TRUE(Common::IsFileExist(dwr.c_str())); +} + +/** + * @tc.name: CompressTest005 + * @tc.desc: Test to create new db and get db/wal/journal filename + * @tc.type: FUNC + */ +HWTEST_F(SQLiteCompressTest, CompressTest005, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create a brand new db while page compression enabled with sqlite3_open_v2 + * @tc.expected: step1. Execute successfully + */ + std::string dbPath1 = TEST_DIR "/compresstest0050.db"; + sqlite3 *compDb = nullptr; + EXPECT_EQ(sqlite3_open_v2(dbPath1.c_str(), &compDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"), + SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DDL_CREATE_DEMO.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DML_INSERT_DEMO.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, "PRAGMA meta_double_write=enabled;", nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, "PRAGMA journal_mode=WAL;", nullptr, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps: step2. Try to get db/wal/journal filename + * @tc.expected: step2. Execute successfully + */ + const char *db = sqlite3_db_filename(compDb, "main"); + const char *wal = sqlite3_filename_wal(db); + const char *journal = sqlite3_filename_journal(db); + std::string str = db; + int n = str.find("/compresstest0050.db"); + EXPECT_TRUE(n != string::npos); + EXPECT_TRUE(n==(str.size() - strlen("/compresstest0050.db"))); + str = wal; + n = str.find("/compresstest0050.db-walcompress"); + EXPECT_TRUE(n != string::npos); + EXPECT_TRUE(n==(str.size() - strlen("/compresstest0050.db-walcompress"))); + str = journal; + n = str.find("/compresstest0050.db-journalcompress"); + EXPECT_TRUE(n != string::npos); + EXPECT_TRUE(n==(str.size() - strlen("/compresstest0050.db-journalcompress"))); + sqlite3_close_v2(compDb); +} + +/** + * @tc.name: CompressTest006 + * @tc.desc: Test to create new db and open multi sqlite3 handler at the same time + * @tc.type: FUNC + */ +HWTEST_F(SQLiteCompressTest, CompressTest006, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create a brand new db while page compression enabled with sqlite3_open_v2 + * @tc.expected: step1. Execute successfully + */ + std::string dbPath1 = TEST_DIR "/compresstest0060.db"; + sqlite3 *compDb = nullptr; + EXPECT_EQ(sqlite3_open_v2(dbPath1.c_str(), &compDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"), + SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DDL_CREATE_DEMO.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, UT_DML_INSERT_DEMO.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, "PRAGMA meta_double_write=enabled;", nullptr, nullptr, nullptr), SQLITE_OK); + EXPECT_EQ(sqlite3_exec(compDb, "PRAGMA journal_mode=WAL;", nullptr, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps: step2. Open multi sqlite3 which enable page compression at the same time + * @tc.expected: step2. Execute successfully + */ + sqlite3 *compDb1 = nullptr; + sqlite3 *compDb2 = nullptr; + EXPECT_EQ(sqlite3_open_v2(dbPath1.c_str(), &compDb1, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"), + SQLITE_OK); + EXPECT_EQ(sqlite3_open_v2(dbPath1.c_str(), &compDb2, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"), + SQLITE_OK); + sqlite3_close_v2(compDb2); + sqlite3_close_v2(compDb1); + sqlite3_close_v2(compDb); +} + } // namespace Test -- Gitee