From 46a62afbaba8e4e47d86ce9a03c242aa12402e99 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 2 Oct 2024 18:54:40 +0000 Subject: [PATCH] Modify the behavior of sqlite_dbpage so that the null-INSERT that truncates a database must be the very last INSERT operation within a transaction in order to be effective. This simplifies the code and also makes the behavior easier to document and understand. FossilOrigin-Name: b869a7d9ce9567a61d2257272032aaee705bbc6158c7f2cd36e7f3ee66d72722 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/dbpage.c | 48 +++++++++++++++++++----------------------------- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index 2f603be8f6..23af5a0848 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sfts5delete.test. -D 2024-10-02T17:43:06.145 +C Modify\sthe\sbehavior\sof\ssqlite_dbpage\sso\sthat\sthe\snull-INSERT\sthat\struncates\na\sdatabase\smust\sbe\sthe\svery\slast\sINSERT\soperation\swithin\sa\stransaction\sin\sorder\nto\sbe\seffective.\s\sThis\ssimplifies\sthe\scode\sand\salso\smakes\sthe\sbehavior\neasier\sto\sdocument\sand\sunderstand. +D 2024-10-02T18:54:40.278 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -716,7 +716,7 @@ F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d49 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64 F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a -F src/dbpage.c 9da735cb2eef4ab6941ddb235c8d2c2764e0bb5bd20f7ca3003be1d4ab8d49c9 +F src/dbpage.c 6199d8c8d6d37a405a92a5da4ed9a69829d7453e6d5ea7b852d58d1fd41d549c F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42 F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239 @@ -2215,8 +2215,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 58313ac59e0bd164f601d68a1474f658c5d1c038638e00f3dc15eb58202e661c -R c9854e52c5a2262f4abddd59c7216292 -U dan -Z 46008f325e9f0a47cd9f68f44b346532 +P b1f001435eff72c2119ecee973194385f70fd1b66ef0be8a66c0b0ad02ae43df +R cb980b8ea9ae6c90e71d1e6639808d4a +U drh +Z 0bd24346b1d9b6d9280a2c12dd94f943 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 28469eeaae..93c9829452 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b1f001435eff72c2119ecee973194385f70fd1b66ef0be8a66c0b0ad02ae43df +b869a7d9ce9567a61d2257272032aaee705bbc6158c7f2cd36e7f3ee66d72722 diff --git a/src/dbpage.c b/src/dbpage.c index 136c8b0b39..0a2020883f 100644 --- a/src/dbpage.c +++ b/src/dbpage.c @@ -57,8 +57,8 @@ struct DbpageCursor { struct DbpageTable { sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* The database */ - int nTrunc; /* Entries in aTrunc[] */ - Pgno *aTrunc; /* Truncation size for each database */ + int iDbTrunc; /* Database to truncate */ + Pgno pgnoTrunc; /* Size to truncate to */ }; /* Columns */ @@ -107,8 +107,6 @@ static int dbpageConnect( ** Disconnect from or destroy a dbpagevfs virtual table. */ static int dbpageDisconnect(sqlite3_vtab *pVtab){ - DbpageTable *pTab = (DbpageTable *)pVtab; - sqlite3_free(pTab->aTrunc); sqlite3_free(pVtab); return SQLITE_OK; } @@ -378,19 +376,9 @@ static int dbpageUpdate( if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){ /* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and ** all subsequent pages to be deleted. */ - if( iDb>=pTab->nTrunc ){ - testcase( pTab->aTrunc!=0 ); - pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno)); - if( pTab->aTrunc ){ - int j; - for(j=pTab->nTrunc; jaTrunc[j] = 0; - pTab->nTrunc = iDb+1; - }else{ - return SQLITE_NOMEM; - } - } + pTab->iDbTrunc = iDb; pgno--; - pTab->aTrunc[iDb] = pgno; + pTab->pgnoTrunc = pgno; }else{ zErr = "bad page value"; goto update_fail; @@ -403,6 +391,7 @@ static int dbpageUpdate( if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ unsigned char *aPage = sqlite3PagerGetData(pDbPage); memcpy(aPage, pData, szPage); + pTab->pgnoTrunc = 0; } } sqlite3PagerUnref(pDbPage); @@ -426,29 +415,30 @@ static int dbpageBegin(sqlite3_vtab *pVtab){ Btree *pBt = db->aDb[i].pBt; if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0); } - if( pTab->nTrunc>0 ){ - memset(pTab->aTrunc, 0, sizeof(pTab->aTrunc[0])*pTab->nTrunc); - } + pTab->pgnoTrunc = 0; return SQLITE_OK; } /* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT */ static int dbpageSync(sqlite3_vtab *pVtab){ - int iDb; DbpageTable *pTab = (DbpageTable *)pVtab; - - for(iDb=0; iDbnTrunc; iDb++){ - if( pTab->aTrunc[iDb]>0 ){ - Btree *pBt = pTab->db->aDb[iDb].pBt; - Pager *pPager = sqlite3BtreePager(pBt); - sqlite3PagerTruncateImage(pPager, pTab->aTrunc[iDb]); - pTab->aTrunc[iDb] = 0; - } + if( pTab->pgnoTrunc>0 ){ + Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt; + Pager *pPager = sqlite3BtreePager(pBt); + sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc); } + pTab->pgnoTrunc = 0; return SQLITE_OK; } +/* Cancel any pending truncate. +*/ +static dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){ + DbpageTable *pTab = (DbpageTable *)pVtab; + pTab->pgnoTrunc = 0; + (void)notUsed1; +} /* ** Invoke this routine to register the "dbpage" virtual table module @@ -477,7 +467,7 @@ int sqlite3DbpageRegister(sqlite3 *db){ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0, /* xRollbackTo */ + dbpageRollbackTo, /* xRollbackTo */ 0, /* xShadowName */ 0 /* xIntegrity */ }; -- 2.47.2