Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a problem with reverting a 'DROP TABLE' command executed inside of a savepoint on an auto-vacuum database. (CVS 6129) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3a4bb83235e9a79297e7d5d47ac7674c |
User & Date: | danielk1977 2009-01-07 10:35:19.000 |
Context
2009-01-07
| ||
10:52 | Add a comment to the openSubjournal() function in pager.c. (CVS 6130) (check-in: 04387ae10a user: danielk1977 tags: trunk) | |
10:35 | Fix a problem with reverting a 'DROP TABLE' command executed inside of a savepoint on an auto-vacuum database. (CVS 6129) (check-in: 3a4bb83235 user: danielk1977 tags: trunk) | |
08:12 | Fix savepoint related bugs. A rollback caused by an IO error or "OR ROLLBACK" clause while one or more savepoints were open was leaving the sqlite3 structure in an invalid state. (CVS 6128) (check-in: e5d42c69a3 user: danielk1977 tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** 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. ** | | | 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.536 2009/01/07 10:35:19 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" /* ** Macros for troubleshooting. Normally turned off */ |
︙ | ︙ | |||
4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 | ** moved as part of a database reorganization just before the transaction ** is being committed. In this case, it is guaranteed that the database page ** pPg refers to will not be written to again within this transaction. */ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ PgHdr *pPgOld; /* The page being overwritten. */ Pgno needSyncPgno = 0; assert( pPg->nRef>0 ); PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno)); IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) pager_get_content(pPg); | > > > > > > > > > > > > > > > > > > > > > > | 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 | ** moved as part of a database reorganization just before the transaction ** is being committed. In this case, it is guaranteed that the database page ** pPg refers to will not be written to again within this transaction. */ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ PgHdr *pPgOld; /* The page being overwritten. */ Pgno needSyncPgno = 0; int rc; assert( pPg->nRef>0 ); /* If the page being moved is dirty and has not been saved by the latest ** savepoint, then save the current contents of the page into the ** sub-journal now. This is required to handle the following scenario: ** ** BEGIN; ** <journal page X, then modify it in memory> ** SAVEPOINT one; ** <Move page X to location Y> ** ROLLBACK TO one; ** ** If page X were not written to the sub-journal here, it would not ** be possible to restore its contents when the "ROLLBACK TO one" ** statement were processed. */ if( pPg->flags&PGHDR_DIRTY && subjRequiresPage(pPg) && SQLITE_OK!=(rc = subjournalPage(pPg)) ){ return rc; } PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno)); IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) pager_get_content(pPg); |
︙ | ︙ | |||
4361 4362 4363 4364 4365 4366 4367 | ** this transaction, it may be written to the database file before ** it is synced into the journal file. This way, it may end up in ** the journal file twice, but that is not a problem. ** ** The sqlite3PagerGet() call may cause the journal to sync. So make ** sure the Pager.needSync flag is set too. */ | < | 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 | ** this transaction, it may be written to the database file before ** it is synced into the journal file. This way, it may end up in ** the journal file twice, but that is not a problem. ** ** The sqlite3PagerGet() call may cause the journal to sync. So make ** sure the Pager.needSync flag is set too. */ PgHdr *pPgHdr; assert( pPager->needSync ); rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); if( rc!=SQLITE_OK ){ if( pPager->pInJournal && needSyncPgno<=pPager->dbOrigSize ){ sqlite3BitvecClear(pPager->pInJournal, needSyncPgno); } |
︙ | ︙ |
Changes to test/savepoint.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2008 December 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 2008 December 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # $Id: savepoint.test,v 1.10 2009/01/07 10:35:19 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl #---------------------------------------------------------------------- # The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE |
︙ | ︙ | |||
736 737 738 739 740 741 742 | do_test savepoint-11.6 { execsql { CREATE TABLE t3(a, b, UNIQUE(a, b)); ROLLBACK TO one; } } {} integrity_check savepoint-11.7 | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 | do_test savepoint-11.6 { execsql { CREATE TABLE t3(a, b, UNIQUE(a, b)); ROLLBACK TO one; } } {} integrity_check savepoint-11.7 do_test savepoint-11.8 { execsql { ROLLBACK } file size test.db } {8192} do_test savepoint-11.9 { execsql { DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t3; } } {} do_test savepoint-11.10 { execsql { BEGIN; CREATE TABLE t1(a, b); CREATE TABLE t2(x, y); INSERT INTO t2 VALUES(1, 2); SAVEPOINT one; INSERT INTO t2 VALUES(3, 4); SAVEPOINT two; DROP TABLE t1; ROLLBACK TO two; } execsql {SELECT * FROM t2} } {1 2 3 4} do_test savepoint-11.11 { execsql COMMIT } {} do_test savepoint-11.12 { execsql {SELECT * FROM t2} } {1 2 3 4} #------------------------------------------------------------------------- # The following tests - savepoint-12.* - test the interaction of # savepoints and "ON CONFLICT ROLLBACK" clauses. # do_test savepoint-12.1 { execsql { CREATE TABLE t4(a PRIMARY KEY, b); |
︙ | ︙ |