aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2024-10-02 18:54:40 +0000
committerdrh <>2024-10-02 18:54:40 +0000
commit46a62afbaba8e4e47d86ce9a03c242aa12402e99 (patch)
treee1efe25ba8888a311bacdb6e749853579e6f6c1d /src
parent44b8c37017e25e8cc6a1703b37e47524cba08bcc (diff)
downloadsqlite-46a62afbaba8e4e47d86ce9a03c242aa12402e99.tar.gz
sqlite-46a62afbaba8e4e47d86ce9a03c242aa12402e99.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/dbpage.c48
1 files changed, 19 insertions, 29 deletions
diff --git a/src/dbpage.c b/src/dbpage.c
index 136c8b0b3..0a2020883 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; j<iDb; j++) pTab->aTrunc[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; iDb<pTab->nTrunc; 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 */
};