/ Check-in [1c582dd1]
Login

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

Overview
Comment:Make sure the rootpage values in the symbol table are correctly updated when dropping tables and indices in autocommit mode. Ticket #1728. (CVS 3150)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:1c582dd11304f4421da2fa451f52b313b541270e
User & Date: drh 2006-03-24 03:36:26
Context
2006-03-25
14:03
Add a note to the API documentation emphasizing that the filename argument to sqlite3_open() must be UTF-8. Tickets #1713, #1533. (CVS 3151) check-in: b0111f43 user: drh tags: trunk
2006-03-24
03:36
Make sure the rootpage values in the symbol table are correctly updated when dropping tables and indices in autocommit mode. Ticket #1728. (CVS 3150) check-in: 1c582dd1 user: drh tags: trunk
2006-03-23
23:33
Improvements to comments in build.c. (CVS 3149) check-in: 986208a3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
....
1723
1724
1725
1726
1727
1728
1729











1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.392 2006/03/23 23:33:27 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
#endif /* SQLITE_OMIT_VIEW */

/*
** This function is called by the VDBE to adjust the internal schema
** used by SQLite when the btree layer moves a table root page. The
** root-page of a table or index in database iDb has changed from iFrom
** to iTo.











*/
#ifndef SQLITE_OMIT_AUTOVACUUM
void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
  HashElem *pElem;
  Hash *pHash;

  pHash = &pDb->pSchema->tblHash;
  for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    if( pTab->tnum==iFrom ){
      pTab->tnum = iTo;
      return;
    }
  }
  pHash = &pDb->pSchema->idxHash;
  for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
    Index *pIdx = sqliteHashData(pElem);
    if( pIdx->tnum==iFrom ){
      pIdx->tnum = iTo;
      return;
    }
  }
  assert(0);
}
#endif

/*
** Write code to erase the table with root-page iTable from database iDb.
** Also write code to modify the sqlite_master table and internal schema
** if a root-page of another table is moved by the btree-layer whilst







|







 







>
>
>
>
>
>
>
>
>
>
>











<







<


<







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
....
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758

1759
1760

1761
1762
1763
1764
1765
1766
1767
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.393 2006/03/24 03:36:26 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
#endif /* SQLITE_OMIT_VIEW */

/*
** This function is called by the VDBE to adjust the internal schema
** used by SQLite when the btree layer moves a table root page. The
** root-page of a table or index in database iDb has changed from iFrom
** to iTo.
**
** Ticket #1728:  The symbol table might still contain information
** on tables and/or indices that are the process of being deleted.
** If you are unlucky, one of those deleted indices or tables might
** have the same rootpage number as the real table or index that is
** being moved.  So we cannot stop searching after the first match 
** because the first match might be for one of the deleted indices
** or tables and not the table/index that is actually being moved.
** We must continue looping until all tables and indices with
** rootpage==iFrom have been converted to have a rootpage of iTo
** in order to be certain that we got the right one.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
  HashElem *pElem;
  Hash *pHash;

  pHash = &pDb->pSchema->tblHash;
  for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    if( pTab->tnum==iFrom ){
      pTab->tnum = iTo;

    }
  }
  pHash = &pDb->pSchema->idxHash;
  for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
    Index *pIdx = sqliteHashData(pElem);
    if( pIdx->tnum==iFrom ){
      pIdx->tnum = iTo;

    }
  }

}
#endif

/*
** Write code to erase the table with root-page iTable from database iDb.
** Also write code to modify the sqlite_master table and internal schema
** if a root-page of another table is moved by the btree-layer whilst

Changes to test/autovacuum.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
533
534
535
536
537
538
539
540

































541
#    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.  The
# focus of this file is testing the SELECT statement.
#
# $Id: autovacuum.test,v 1.21 2006/03/23 23:29:04 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 || !pragma} {
................................................................................
    PRAGMA auto_vacuum=1;
    CREATE TABLE t1(a);
    CREATE TABLE t2(a);
    DROP TABLE t1;
    PRAGMA integrity_check;
  }
} ok


































finish_test







|







 








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

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
#    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.  The
# focus of this file is testing the SELECT statement.
#
# $Id: autovacuum.test,v 1.22 2006/03/24 03:36:26 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 || !pragma} {
................................................................................
    PRAGMA auto_vacuum=1;
    CREATE TABLE t1(a);
    CREATE TABLE t2(a);
    DROP TABLE t1;
    PRAGMA integrity_check;
  }
} ok

# Ticket #1728.
#
# In autovacuum mode, when tables or indices are deleted, the rootpage
# values in the symbol table have to be updated.  There was a bug in this
# logic so that if an index/table was moved twice, the second move might
# not occur.  This would leave the internal symbol table in an inconsistent
# state causing subsequent statements to fail.
#
# The problem is difficult to reproduce.  The sequence of statements in
# the following test are carefully designed make it occur and thus to
# verify that this very obscure bug has been resolved.
# 
do_test autovacuum-6.1 {
  db close
  sqlite3 db :memory:
  db eval {
    PRAGMA auto_vacuum=1;
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a);
    CREATE TABLE t2(a);
    CREATE INDEX i2 ON t2(a);
    CREATE TABLE t3(a);
    CREATE INDEX i3 ON t2(a);
    CREATE INDEX x ON t1(b);
    DROP TABLE t3;
    PRAGMA integrity_check;
    DROP TABLE t2;
    PRAGMA integrity_check;
    DROP TABLE t1;
    PRAGMA integrity_check;
  }
} {ok ok ok}

finish_test