SQLite

Check-in [4a1ae9d032]
Login

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

Overview
Comment:Fix a bug whereby the database file was not always being extended to its original size when rolling back an incremental-vacuum operation. (CVS 5089)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4a1ae9d0320de1013a3b5f24ebdd25fe9fdab424
User & Date: danielk1977 2008-05-06 18:13:26.000
Context
2008-05-06
21:42
Remove delOnClose flag from os2File structure, use pathToDel==NULL for the same check. (CVS 5090) (check-in: 02e123bb9b user: pweilbacher tags: trunk)
18:13
Fix a bug whereby the database file was not always being extended to its original size when rolling back an incremental-vacuum operation. (CVS 5089) (check-in: 4a1ae9d032 user: danielk1977 tags: trunk)
02:28
Add defines for _FILE_OFFSET_BITS and _LARGE_FILES if needed for large file support. Ticket #3094. (CVS 5088) (check-in: 729e2f06ba user: mlcreech tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.439 2008/05/05 16:23:55 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.440 2008/05/06 18:13:26 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
1691
1692
1693
1694
1695
1696
1697
1698

1699
1700
1701
1702
1703
1704
1705
1706

1707



1708
1709
1710
1711
1712
1713
1714
**
** Might might be the case that the file on disk is smaller than nPage.
** This can happen, for example, if we are in the middle of a transaction
** which has extended the file size and the new pages are still all held
** in cache, then an INSERT or UPDATE does a statement rollback.  Some
** operating system implementations can get confused if you try to
** truncate a file to some size that is larger than it currently is,
** so detect this case and do not do the truncation.

*/
static int pager_truncate(Pager *pPager, int nPage){
  int rc = SQLITE_OK;
  if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){
    i64 currentSize, newSize;
    rc = sqlite3OsFileSize(pPager->fd, &currentSize);
    newSize = pPager->pageSize*(i64)nPage;
    if( rc==SQLITE_OK && currentSize>newSize ){

      rc = sqlite3OsTruncate(pPager->fd, newSize);



    }
  }
  if( rc==SQLITE_OK ){
    pPager->dbSize = nPage;
    pager_truncate_cache(pPager);
  }
  return rc;







|
>







|
>
|
>
>
>







1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
**
** Might might be the case that the file on disk is smaller than nPage.
** This can happen, for example, if we are in the middle of a transaction
** which has extended the file size and the new pages are still all held
** in cache, then an INSERT or UPDATE does a statement rollback.  Some
** operating system implementations can get confused if you try to
** truncate a file to some size that is larger than it currently is,
** so detect this case and write a single zero byte to the end of the new
** file instead.
*/
static int pager_truncate(Pager *pPager, int nPage){
  int rc = SQLITE_OK;
  if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){
    i64 currentSize, newSize;
    rc = sqlite3OsFileSize(pPager->fd, &currentSize);
    newSize = pPager->pageSize*(i64)nPage;
    if( rc==SQLITE_OK && currentSize!=newSize ){
      if( currentSize>newSize ){
        rc = sqlite3OsTruncate(pPager->fd, newSize);
      }else{
        rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1);
      }
    }
  }
  if( rc==SQLITE_OK ){
    pPager->dbSize = nPage;
    pager_truncate_cache(pPager);
  }
  return rc;
Changes to test/incrvacuum_ioerr.test.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: incrvacuum_ioerr.test,v 1.2 2007/05/04 18:30:41 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If this build of the library does not support auto-vacuum, omit this
# whole file.
ifcapable {!autovacuum} {







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: incrvacuum_ioerr.test,v 1.3 2008/05/06 18:13:26 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If this build of the library does not support auto-vacuum, omit this
# whole file.
ifcapable {!autovacuum} {
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  INSERT INTO abc VALUES(randstr(1500,1500));
} -sqlbody {
  BEGIN;
  CREATE TABLE abc2(a);
  DELETE FROM abc;
  PRAGMA incremental_vacuum;
  COMMIT;
}

# do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
#   db eval {
#     PRAGMA auto_vacuum = 'full';
#     PRAGMA cache_size = 10;
#     BEGIN;
#     CREATE TABLE abc(a, UNIQUE(a));







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  INSERT INTO abc VALUES(randstr(1500,1500));
} -sqlbody {
  BEGIN;
  CREATE TABLE abc2(a);
  DELETE FROM abc;
  PRAGMA incremental_vacuum;
  COMMIT;
} 

# do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
#   db eval {
#     PRAGMA auto_vacuum = 'full';
#     PRAGMA cache_size = 10;
#     BEGIN;
#     CREATE TABLE abc(a, UNIQUE(a));
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#   DELETE FROM abc WHERE (oid%3)==0;
#   INSERT INTO abc SELECT a || '1234567890' FROM abc WHERE oid%2;
#   CREATE INDEX abc_i ON abc(a);
#   DELETE FROM abc WHERE (oid%2)==0;
#   DROP INDEX abc_i;
#   COMMIT;
# }


do_ioerr_test incrvacuum-ioerr-2 -start 1 -cksum 1 -tclprep {
  db eval {
    PRAGMA auto_vacuum = 'full';
    PRAGMA cache_size = 10;
    BEGIN;
    CREATE TABLE abc(a, UNIQUE(a));







<







55
56
57
58
59
60
61

62
63
64
65
66
67
68
#   DELETE FROM abc WHERE (oid%3)==0;
#   INSERT INTO abc SELECT a || '1234567890' FROM abc WHERE oid%2;
#   CREATE INDEX abc_i ON abc(a);
#   DELETE FROM abc WHERE (oid%2)==0;
#   DROP INDEX abc_i;
#   COMMIT;
# }


do_ioerr_test incrvacuum-ioerr-2 -start 1 -cksum 1 -tclprep {
  db eval {
    PRAGMA auto_vacuum = 'full';
    PRAGMA cache_size = 10;
    BEGIN;
    CREATE TABLE abc(a, UNIQUE(a));
82
83
84
85
86
87
88




















89
  CREATE INDEX abc_i ON abc(a);
  DELETE FROM abc WHERE (oid%2)==0;
  PRAGMA incremental_vacuum;
  DROP INDEX abc_i;
  PRAGMA incremental_vacuum;
  COMMIT;
}




















finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  CREATE INDEX abc_i ON abc(a);
  DELETE FROM abc WHERE (oid%2)==0;
  PRAGMA incremental_vacuum;
  DROP INDEX abc_i;
  PRAGMA incremental_vacuum;
  COMMIT;
}

do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
  db eval {
    PRAGMA auto_vacuum = 'incremental';
    BEGIN;
    CREATE TABLE a(i integer, b blob);
    INSERT INTO a VALUES(1, randstr(1500,1500));
    INSERT INTO a VALUES(2, randstr(1500,1500));
  }
  db eval COMMIT
  db eval {DELETE FROM a WHERE oid}
} -sqlbody {
  PRAGMA incremental_vacuum(5);
} -cleanup {
  sqlite3 db test.db
  integrity_check incrvacuum-ioerr-2.$n.integritycheck
  db close
}


finish_test