/ Check-in [483994a5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Ensure that the sqlite3_scrub_backup() extension creates a backup database at least as large as indicated by the database header, even if the last page of the input database is a free-list leaf.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd
User & Date: dan 2016-07-26 10:46:21
Context
2016-07-27
18:27
When estimating the cost of an index scan, factor in the cost savings of being able to use the index to evaluate some WHERE clause terms without having to do a table lookup. check-in: a59b5622 user: drh tags: improved-index-scan
16:03
Initialize a variable in where.c to avoid a valgrind warning. check-in: 4d59df02 user: dan tags: trunk
2016-07-26
18:15
Merge latest trunk changes into this branch. check-in: d4f3d52c user: dan tags: rowvalue
15:17
Merge fixes to sqlite3_scrub_backup() from trunk. check-in: 91e811f5 user: drh tags: apple-osx
10:46
Ensure that the sqlite3_scrub_backup() extension creates a backup database at least as large as indicated by the database header, even if the last page of the input database is a free-list leaf. check-in: 483994a5 user: dan tags: trunk
04:49
Copy the cache_spill setting from the main database over to the vacuum_db transient database when running a VACUUM. check-in: c0e7d98e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/scrub.c.

    70     70     sqlite3 *dbSrc;          /* Source database connection */
    71     71     sqlite3_file *pSrc;      /* Source file handle */
    72     72     sqlite3 *dbDest;         /* Destination database connection */
    73     73     sqlite3_file *pDest;     /* Destination file handle */
    74     74     u32 szPage;              /* Page size */
    75     75     u32 szUsable;            /* Usable bytes on each page */
    76     76     u32 nPage;               /* Number of pages */
           77  +  u32 iLastPage;           /* Page number of last page written so far*/
    77     78     u8 *page1;               /* Content of page 1 */
    78     79   };
    79     80   
    80     81   /* Store an error message */
    81     82   static void scrubBackupErr(ScrubState *p, const char *zFormat, ...){
    82     83     va_list ap;
    83     84     sqlite3_free(p->zErr);
................................................................................
   126    127     if( p->rcErr ) return;
   127    128     iOff = (pgno-1)*(sqlite3_int64)p->szPage;
   128    129     rc = p->pDest->pMethods->xWrite(p->pDest, pData, p->szPage, iOff);
   129    130     if( rc!=SQLITE_OK ){
   130    131       scrubBackupErr(p, "write failed for page %d", pgno);
   131    132       p->rcErr = SQLITE_IOERR;
   132    133     }
          134  +  if( pgno>p->iLastPage ) p->iLastPage = pgno;
   133    135   }
   134    136   
   135    137   /* Prepare a statement against the "db" database. */
   136    138   static sqlite3_stmt *scrubBackupPrepare(
   137    139     ScrubState *p,      /* Backup context */
   138    140     sqlite3 *db,        /* Database to prepare against */
   139    141     const char *zSql    /* SQL statement */
................................................................................
   536    538          "SELECT rootpage FROM sqlite_master WHERE coalesce(rootpage,0)>0");
   537    539     if( pStmt==0 ) goto scrub_abort;
   538    540     while( sqlite3_step(pStmt)==SQLITE_ROW ){
   539    541       i = (u32)sqlite3_column_int(pStmt, 0);
   540    542       scrubBackupBtree(&s, i, 0);
   541    543     }
   542    544     sqlite3_finalize(pStmt);
          545  +
          546  +  /* If the last page of the input db file is a free-list leaf, then the
          547  +  ** backup file on disk is still smaller than the size indicated within 
          548  +  ** the database header. In this case, write a page of zeroes to the 
          549  +  ** last page of the backup database so that SQLite does not mistakenly
          550  +  ** think the db is corrupt.  */
          551  +  if( s.iLastPage<s.nPage ){
          552  +    u8 *aZero = scrubBackupAllocPage(&s);
          553  +    if( aZero ){
          554  +      memset(aZero, 0, s.szPage);
          555  +      scrubBackupWrite(&s, s.nPage, aZero);
          556  +      sqlite3_free(aZero);
          557  +    }
          558  +  }
   543    559   
   544    560   scrub_abort:    
   545    561     /* Close the destination database without closing the transaction. If we
   546    562     ** commit, page zero will be overwritten. */
   547    563     sqlite3_close(s.dbDest);
   548    564   
   549    565     /* But do close out the read-transaction on the source database */