Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Candidate fix for ticket [6bfb98dfc0c]: Make sure invalid cursors drop all references to database pages prior to doing any insert or update. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
322a5f086d9ee46017f750df81527799 |
User & Date: | drh 2013-03-27 03:15:23.329 |
Context
2013-03-27
| ||
17:20 | In order to optimize out the ORDER BY clause, outer loops must generate values for ORDER BY terms that are unique or else the inner loops must generate no more than a single row. Fix for ticket [a179fe7465]. (check-in: 2936f7466e user: drh tags: trunk) | |
15:04 | A fix and test-case for the ORDER BY problem identified by ticket [a179fe7465]. This change causes sorting to occur in some cases where it is not strictly necessary. Further work is needed to avoid those extra sorts. (check-in: 488089e615 user: drh tags: orderby-fix) | |
03:15 | Candidate fix for ticket [6bfb98dfc0c]: Make sure invalid cursors drop all references to database pages prior to doing any insert or update. (check-in: 322a5f086d user: drh tags: trunk) | |
2013-03-25
| ||
12:02 | Add a second test for [38b1ae018f]. (check-in: 5062db672c user: dan tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
570 571 572 573 574 575 576 577 578 579 580 581 582 583 | ** Clear (destroy) the BtShared.pHasContent bitvec. This should be ** invoked at the conclusion of each write-transaction. */ static void btreeClearHasContent(BtShared *pBt){ sqlite3BitvecDestroy(pBt->pHasContent); pBt->pHasContent = 0; } /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ** ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) ** prior to calling this routine. | > > > > > > > > > > > > > | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | ** Clear (destroy) the BtShared.pHasContent bitvec. This should be ** invoked at the conclusion of each write-transaction. */ static void btreeClearHasContent(BtShared *pBt){ sqlite3BitvecDestroy(pBt->pHasContent); pBt->pHasContent = 0; } /* ** Release all of the apPage[] pages for a cursor. */ static void btreeReleaseAllCursorPages(BtCursor *pCur){ int i; for(i=0; i<=pCur->iPage; i++){ releasePage(pCur->apPage[i]); pCur->apPage[i] = 0; } pCur->iPage = -1; } /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ** ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) ** prior to calling this routine. |
︙ | ︙ | |||
610 611 612 613 614 615 616 | }else{ rc = SQLITE_NOMEM; } } assert( !pCur->apPage[0]->intKey || !pCur->pKey ); if( rc==SQLITE_OK ){ | < < | < < < | | | | | > > > > | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | }else{ rc = SQLITE_NOMEM; } } assert( !pCur->apPage[0]->intKey || !pCur->pKey ); if( rc==SQLITE_OK ){ btreeReleaseAllCursorPages(pCur); pCur->eState = CURSOR_REQUIRESEEK; } invalidateOverflowCache(pCur); return rc; } /* ** Save the positions of all cursors (except pExcept) that are open on ** the table with root-page iRoot. Usually, this is called just before cursor ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ if( p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; } }else{ testcase( p->iPage>0 ); btreeReleaseAllCursorPages(p); } } } return SQLITE_OK; } /* |
︙ | ︙ |
Added test/tkt-6bfb98dfc0.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | # 2013 March 27 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. Specifically, # it tests that ticket [6bfb98dfc0] # # The final INSERT in the script below reports that the database is # corrupt (SQLITE_CORRUPT) and aborts even though the database is not # corrupt. # # PRAGMA page_size=512; # CREATE TABLE t1(x INTEGER PRIMARY KEY, y); # INSERT INTO t1 VALUES(1,randomblob(400)); # INSERT INTO t1 VALUES(2,randomblob(400)); # INSERT INTO t1 SELECT x+2, randomblob(400) FROM t1; # INSERT INTO t1 SELECT x+4, randomblob(400) FROM t1; # INSERT INTO t1 SELECT x+8, randomblob(400) FROM t1; # INSERT INTO t1 SELECT x+16, randomblob(400) FROM t1; # INSERT INTO t1 SELECT x+32, randomblob(400) FROM t1; # INSERT INTO t1 SELECT x+64, randomblob(400) FROM t1 WHERE x<10; # CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.x=74 BEGIN # DELETE FROM t1; # INSERT INTO t1 VALUES(75, randomblob(400)); # INSERT INTO t1 VALUES(76, randomblob(400)); # END; # INSERT INTO t1 VALUES(74, randomblob(400)); # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt-6bfb98dfc0.100 { db eval { PRAGMA page_size=512; CREATE TABLE t1(x INTEGER PRIMARY KEY, y); INSERT INTO t1 VALUES(1,randomblob(400)); INSERT INTO t1 VALUES(2,randomblob(400)); INSERT INTO t1 SELECT x+2, randomblob(400) FROM t1; INSERT INTO t1 SELECT x+4, randomblob(400) FROM t1; INSERT INTO t1 SELECT x+8, randomblob(400) FROM t1; INSERT INTO t1 SELECT x+16, randomblob(400) FROM t1; INSERT INTO t1 SELECT x+32, randomblob(400) FROM t1; INSERT INTO t1 SELECT x+64, randomblob(400) FROM t1 WHERE x<10; CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.x=74 BEGIN DELETE FROM t1; INSERT INTO t1 VALUES(75, randomblob(400)); INSERT INTO t1 VALUES(76, randomblob(400)); END; INSERT INTO t1 VALUES(74, randomblob(400)); SELECT x, length(y) FROM t1 ORDER BY x; } } {75 400 76 400} finish_test |