summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/pager.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/pager.c')
-rw-r--r--ext/sqlite/libsqlite/src/pager.c81
1 files changed, 72 insertions, 9 deletions
diff --git a/ext/sqlite/libsqlite/src/pager.c b/ext/sqlite/libsqlite/src/pager.c
index 7b32f6e089..e133a3cad0 100644
--- a/ext/sqlite/libsqlite/src/pager.c
+++ b/ext/sqlite/libsqlite/src/pager.c
@@ -928,6 +928,34 @@ int sqlitepager_pagecount(Pager *pPager){
}
/*
+** Forward declaration
+*/
+static int syncAllPages(Pager*);
+
+/*
+** Truncate the file to the number of pages specified.
+*/
+int sqlitepager_truncate(Pager *pPager, Pgno nPage){
+ int rc;
+ if( pPager->dbSize<0 ){
+ sqlitepager_pagecount(pPager);
+ }
+ if( pPager->errMask!=0 ){
+ rc = pager_errcode(pPager);
+ return rc;
+ }
+ if( nPage>=pPager->dbSize ){
+ return SQLITE_OK;
+ }
+ syncAllPages(pPager);
+ rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
+ if( rc==SQLITE_OK ){
+ pPager->dbSize = nPage;
+ }
+ return rc;
+}
+
+/*
** Shutdown the page cache. Free all memory and close all files.
**
** If a transaction was in progress when this routine is called, that
@@ -966,6 +994,10 @@ int sqlitepager_close(Pager *pPager){
** }
*/
CLR_PAGER(pPager);
+ if( pPager->zFilename!=(char*)&pPager[1] ){
+ sqliteFree(pPager->zFilename);
+ sqliteFree(pPager->zJournal);
+ }
sqliteFree(pPager);
return SQLITE_OK;
}
@@ -1171,6 +1203,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
*/
assert( pPager!=0 );
assert( pgno!=0 );
+ *ppPage = 0;
if( pPager->errMask & ~(PAGER_ERR_FULL) ){
return pager_errcode(pPager);
}
@@ -1181,7 +1214,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
if( pPager->nRef==0 ){
rc = sqliteOsReadLock(&pPager->fd);
if( rc!=SQLITE_OK ){
- *ppPage = 0;
return rc;
}
pPager->state = SQLITE_READLOCK;
@@ -1199,7 +1231,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* This should never happen! */
rc = SQLITE_INTERNAL;
}
- *ppPage = 0;
return rc;
}
pPager->state = SQLITE_WRITELOCK;
@@ -1215,7 +1246,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
if( rc!=SQLITE_OK ){
rc = sqliteOsUnlock(&pPager->fd);
assert( rc==SQLITE_OK );
- *ppPage = 0;
return SQLITE_BUSY;
}
pPager->journalOpen = 1;
@@ -1243,7 +1273,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE
+ sizeof(u32) + pPager->nExtra );
if( pPg==0 ){
- *ppPage = 0;
pager_unwritelock(pPager);
pPager->errMask |= PAGER_ERR_MEM;
return SQLITE_NOMEM;
@@ -1272,7 +1301,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
int rc = syncAllPages(pPager);
if( rc!=0 ){
sqlitepager_rollback(pPager);
- *ppPage = 0;
return SQLITE_IOERR;
}
pPg = pPager->pFirst;
@@ -1287,7 +1315,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
rc = pager_write_pagelist( pPg );
if( rc!=SQLITE_OK ){
sqlitepager_rollback(pPager);
- *ppPage = 0;
return SQLITE_IOERR;
}
}
@@ -1365,7 +1392,15 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
assert( pPg->pNextHash->pPrevHash==0 );
pPg->pNextHash->pPrevHash = pPg;
}
+ if( pPager->nExtra>0 ){
+ memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
+ }
if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager);
+ if( pPager->errMask!=0 ){
+ sqlitepager_unref(PGHDR_TO_DATA(pPg));
+ rc = pager_errcode(pPager);
+ return rc;
+ }
if( pPager->dbSize<(int)pgno ){
memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
}else{
@@ -1376,15 +1411,13 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
off_t fileSize;
if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
|| fileSize>=pgno*SQLITE_PAGE_SIZE ){
+ sqlitepager_unref(PGHDR_TO_DATA(pPg));
return rc;
}else{
memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
}
}
}
- if( pPager->nExtra>0 ){
- memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
- }
}else{
/* The requested page is in the page cache. */
pPager->nHit++;
@@ -1506,6 +1539,10 @@ static int pager_open_journal(Pager *pPager){
pPager->alwaysRollback = 0;
pPager->nRec = 0;
sqlitepager_pagecount(pPager);
+ if( pPager->errMask!=0 ){
+ rc = pager_errcode(pPager);
+ return rc;
+ }
pPager->origDbSize = pPager->dbSize;
if( journal_format==JOURNAL_FORMAT_3 ){
rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3));
@@ -1723,6 +1760,25 @@ int sqlitepager_iswriteable(void *pData){
}
/*
+** Replace the content of a single page with the information in the third
+** argument.
+*/
+int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
+ void *pPage;
+ int rc;
+
+ rc = sqlitepager_get(pPager, pgno, &pPage);
+ if( rc==SQLITE_OK ){
+ rc = sqlitepager_write(pPage);
+ if( rc==SQLITE_OK ){
+ memcpy(pPage, pData, SQLITE_PAGE_SIZE);
+ }
+ sqlitepager_unref(pPage);
+ }
+ return rc;
+}
+
+/*
** A call to this routine tells the pager that it is not necessary to
** write the information on page "pgno" back to the disk, even though
** that page might be marked as dirty.
@@ -2007,6 +2063,13 @@ int sqlitepager_ckpt_rollback(Pager *pPager){
return rc;
}
+/*
+** Return the full pathname of the database file.
+*/
+const char *sqlitepager_filename(Pager *pPager){
+ return pPager->zFilename;
+}
+
#ifdef SQLITE_TEST
/*
** Print a listing of all referenced pages and their ref count.