/ Check-in [752a2754]
Login

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

Overview
Comment:Fix a bug that was emptying shared-schema tables during an ATTACH. (CVS 2867)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:752a2754879becc32da9f9b910f3330f8c7145e4
User & Date: danielk1977 2006-01-06 06:33:12
Context
2006-01-06
12:03
Back out the addition of the new header file - bad idea. (CVS 2868) check-in: 0c4c45c3 user: drh tags: trunk
06:33
Fix a bug that was emptying shared-schema tables during an ATTACH. (CVS 2867) check-in: 752a2754 user: danielk1977 tags: trunk
03:29
Enable async testing. Modify the OS layer interface. Add the sqlite3_aux.h include file. Add tests for boolean value representation in file format 4. (CVS 2866) check-in: b8332aa8 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.280 2006/01/06 01:42:58 drh Exp $
           12  +** $Id: btree.c,v 1.281 2006/01/06 06:33:12 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** For a detailed discussion of BTrees, refer to
    16     16   **
    17     17   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    18     18   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    19     19   **     Publishing Company, Reading, Massachusetts.
................................................................................
  1718   1718   
  1719   1719     /* Close the pager and free the shared-btree structure */
  1720   1720     assert( !pBt->pCursor );
  1721   1721     sqlite3pager_close(pBt->pPager);
  1722   1722     if( pBt->xFreeSchema && pBt->pSchema ){
  1723   1723       pBt->xFreeSchema(pBt->pSchema);
  1724   1724     }
         1725  +  sqliteFree(pBt->pSchema);
  1725   1726     sqliteFree(pBt);
  1726   1727     return SQLITE_OK;
  1727   1728   }
  1728   1729   
  1729   1730   /*
  1730   1731   ** Change the busy handler callback function.
  1731   1732   */

Changes to src/build.c.

    18     18   **     CREATE INDEX
    19     19   **     DROP INDEX
    20     20   **     creating ID lists
    21     21   **     BEGIN TRANSACTION
    22     22   **     COMMIT
    23     23   **     ROLLBACK
    24     24   **
    25         -** $Id: build.c,v 1.367 2006/01/05 11:34:34 danielk1977 Exp $
           25  +** $Id: build.c,v 1.368 2006/01/06 06:33:13 danielk1977 Exp $
    26     26   */
    27     27   #include "sqliteInt.h"
    28     28   #include <ctype.h>
    29     29   
    30     30   /*
    31     31   ** This routine is called when a new SQL statement is beginning to
    32     32   ** be parsed.  Initialize the pParse structure as needed.
................................................................................
   254    254   ** it is not unlinked from the Table that it indexes.
   255    255   ** Unlinking from the Table must be done by the calling function.
   256    256   */
   257    257   static void sqliteDeleteIndex(sqlite3 *db, Index *p){
   258    258     Index *pOld;
   259    259     const char *zName = p->zName;
   260    260   
   261         -  assert( db!=0 && zName!=0 );
   262    261     pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0);
   263    262     assert( pOld==0 || pOld==p );
   264    263     freeIndex(p);
   265    264   }
   266    265   
   267    266   /*
   268    267   ** For the index called zIdxName which is found in the database iDb,
................................................................................
   300    299   ** schema-cookie mismatch occurs.
   301    300   **
   302    301   ** If iDb<=0 then reset the internal schema tables for all database
   303    302   ** files.  If iDb>=2 then reset the internal schema for only the
   304    303   ** single file indicated.
   305    304   */
   306    305   void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
   307         -  HashElem *pElem;
   308         -  Hash temp1;
   309         -  Hash temp2;
   310    306     int i, j;
   311    307   
   312    308     assert( iDb>=0 && iDb<db->nDb );
   313    309     db->flags &= ~SQLITE_Initialized;
   314    310     for(i=iDb; i<db->nDb; i++){
   315    311       Db *pDb = &db->aDb[i];
   316    312       if( pDb->pSchema ){
   317         -      temp1 = pDb->pSchema->tblHash;
   318         -      temp2 = pDb->pSchema->trigHash;
   319         -      sqlite3HashInit(&pDb->pSchema->trigHash, SQLITE_HASH_STRING, 0);
   320         -      sqlite3HashClear(&pDb->pSchema->aFKey);
   321         -      sqlite3HashClear(&pDb->pSchema->idxHash);
   322         -      for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
   323         -        sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
   324         -      }
   325         -      sqlite3HashClear(&temp2);
   326         -      sqlite3HashInit(&pDb->pSchema->tblHash, SQLITE_HASH_STRING, 0);
   327         -      for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
   328         -        Table *pTab = sqliteHashData(pElem);
   329         -        sqlite3DeleteTable(db, pTab);
   330         -      }
   331         -      sqlite3HashClear(&temp1);
   332         -      pDb->pSchema->pSeqTab = 0;
   333         -      DbClearProperty(db, i, DB_SchemaLoaded);
          313  +      sqlite3SchemaFree(pDb->pSchema);
   334    314       }
   335    315       if( iDb>0 ) return;
   336    316     }
   337    317     assert( iDb==0 );
   338    318     db->flags &= ~SQLITE_InternChanges;
   339    319   
   340    320     /* If one or more of the auxiliary database files has been closed,
................................................................................
   422    402   ** data structure if db!=NULL.  If db==NULL, indices attached to
   423    403   ** the table are deleted, but it is assumed they have already been
   424    404   ** unlinked.
   425    405   */
   426    406   void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
   427    407     Index *pIndex, *pNext;
   428    408     FKey *pFKey, *pNextFKey;
          409  +
          410  +  db = 0;
   429    411   
   430    412     if( pTable==0 ) return;
   431    413   
   432    414     /* Do not delete the table until the reference count reaches zero. */
   433    415     pTable->nRef--;
   434    416     if( pTable->nRef>0 ){
   435    417       return;
................................................................................
   446    428   
   447    429   #ifndef SQLITE_OMIT_FOREIGN_KEY
   448    430     /* Delete all foreign keys associated with this table.  The keys
   449    431     ** should have already been unlinked from the db->aFKey hash table 
   450    432     */
   451    433     for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
   452    434       pNextFKey = pFKey->pNextFrom;
   453         -    assert( sqlite3SchemaToIndex(db, pTable->pSchema)<db->nDb );
   454    435       assert( sqlite3HashFind(&pTable->pSchema->aFKey,
   455    436                              pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
   456    437       sqliteFree(pFKey);
   457    438     }
   458    439   #endif
   459    440   
   460    441     /* Delete the Table structure itself.

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.315 2006/01/05 13:48:29 danielk1977 Exp $
           17  +** $Id: main.c,v 1.316 2006/01/06 06:33:13 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
    92     92   ** Return the number of changes since the database handle was opened.
    93     93   */
    94     94   int sqlite3_total_changes(sqlite3 *db){
    95     95     return db->nTotalChange;
    96     96   }
    97     97   
    98     98   /*
    99         -** Free a schema structure.
           99  +** Free all resources held by the schema structure. The void* argument points
          100  +** at a DbSchema struct. This function does not call sqliteFree() on the 
          101  +** pointer itself, it just cleans up subsiduary resources (i.e. the contents
          102  +** of the schema hash tables).
   100    103   */
   101    104   void sqlite3SchemaFree(void *p){
   102         -  sqliteFree(p);
          105  +  Hash temp1;
          106  +  Hash temp2;
          107  +  HashElem *pElem;
          108  +  DbSchema *pSchema = (DbSchema *)p;
          109  +
          110  +  temp1 = pSchema->tblHash;
          111  +  temp2 = pSchema->trigHash;
          112  +  sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
          113  +  sqlite3HashClear(&pSchema->aFKey);
          114  +  sqlite3HashClear(&pSchema->idxHash);
          115  +  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
          116  +    sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
          117  +  }
          118  +  sqlite3HashClear(&temp2);
          119  +  sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
          120  +  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
          121  +    Table *pTab = sqliteHashData(pElem);
          122  +    sqlite3DeleteTable(0, pTab);
          123  +  }
          124  +  sqlite3HashClear(&temp1);
          125  +  pSchema->pSeqTab = 0;
          126  +  pSchema->flags &= ~DB_SchemaLoaded;
   103    127   }
   104    128   
   105    129   DbSchema *sqlite3SchemaGet(Btree *pBt){
   106    130     DbSchema * p;
   107    131     if( pBt ){
   108    132       p = (DbSchema *)sqlite3BtreeSchema(pBt,sizeof(DbSchema),sqlite3SchemaFree);
   109    133     }else{
   110    134       p = (DbSchema *)sqliteMalloc(sizeof(DbSchema));
   111    135     }
   112         -  if( p ){
          136  +  if( p && 0==p->file_format ){
   113    137       sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0);
   114    138       sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
   115    139       sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);
   116    140       sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1);
   117    141     }
   118    142     return p;
   119    143   }

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.159 2005/12/29 01:11:37 drh Exp $
           17  +** $Id: util.c,v 1.160 2006/01/06 06:33:13 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <stdarg.h>
    22     22   #include <ctype.h>
    23     23   
    24     24   /*
................................................................................
   285    285     z = &zAlloc[TESTALLOC_OFFSET_STACK(p)];
   286    286     backtrace((void **)z, TESTALLOC_STACKFRAMES);
   287    287   
   288    288     /* Sanity check to make sure checkGuards() is working */
   289    289     checkGuards(p);
   290    290   }
   291    291   
          292  +/*
          293  +** The argument is a malloc()ed pointer as returned by the test-wrapper.
          294  +** Return a pointer to the Os level allocation.
          295  +*/
   292    296   static void *getOsPointer(void *p)
   293    297   {
   294    298     char *z = (char *)p;
   295    299     return (void *)(&z[-1 * TESTALLOC_OFFSET_DATA(p)]);
   296    300   }
   297    301   
   298    302   

Changes to test/shared.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the SELECT statement.
    13     13   #
    14         -# $Id: shared.test,v 1.2 2006/01/05 11:34:34 danielk1977 Exp $
           14  +# $Id: shared.test,v 1.3 2006/01/06 06:33:13 danielk1977 Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   db close
    19     19   
    20     20   ifcapable !shared_cache {
    21     21     finish_test
................................................................................
    27     27   #
    28     28   # shared-1.*: Simple test to verify basic sanity of table level locking when
    29     29   #             two connections share a pager cache.
    30     30   # shared-2.*: Test that a read transaction can co-exist with a 
    31     31   #             write-transaction, including a simple test to ensure the 
    32     32   #             external locking protocol is still working.
    33     33   # shared-3.*: Simple test of read-uncommitted mode.
           34  +#
           35  +# shared-4.*: Check that the schema is locked and unlocked correctly.
    34     36   #
    35     37   
    36     38   do_test shared-1.1 {
    37     39     # Open a second database on the file test.db. It should use the same pager
    38     40     # cache and schema as the original connection. Verify that only 1 file is 
    39     41     # opened.
    40     42     sqlite3 db2 test.db
................................................................................
   213    215       SELECT * FROM seq;
   214    216     }
   215    217   } {}
   216    218   
   217    219   catch {db close}
   218    220   catch {db2 close}
   219    221   catch {db3 close}
          222  +
          223  +#--------------------------------------------------------------------------
          224  +# Tests shared-4.* test that the schema locking rules are applied 
          225  +# correctly. i.e.:
          226  +#
          227  +# 1. All transactions require a read-lock on the schemas of databases they
          228  +#    access.
          229  +# 2. Transactions that modify a database schema require a write-lock on that
          230  +#    schema.
          231  +# 3. It is not possible to compile a statement while another handle has a 
          232  +#    write-lock on the schema.
          233  +#
          234  +
          235  +# Open two database handles db and db2. Each has a single attach database
          236  +# (as well as main):
          237  +#
          238  +#     db.main   ->   ./test.db
          239  +#     db.test2  ->   ./test2.db
          240  +#     db2.main  ->   ./test2.db
          241  +#     db2.test  ->   ./test.db
          242  +#
          243  +file delete -force test.db
          244  +file delete -force test2.db
          245  +file delete -force test2.db-journal
          246  +sqlite3 db  test.db
          247  +sqlite3 db2 test2.db
          248  +do_test shared-4.1.1 {
          249  +  set sqlite_open_file_count
          250  +} {2}
          251  +do_test shared-4.1.2 {
          252  +  execsql {ATTACH 'test2.db' AS test2}
          253  +  set sqlite_open_file_count
          254  +} {2}
          255  +do_test shared-4.1.3 {
          256  +  execsql {ATTACH 'test.db' AS test} db2
          257  +  set sqlite_open_file_count
          258  +} {2}
          259  +
          260  +do_test shared-4.2.1 {
          261  +  execsql {
          262  +    CREATE TABLE abc(a, b, c);
          263  +    INSERT INTO abc VALUES('i', 'ii', 'iii');
          264  +  }
          265  +} {}
          266  +do_test shared-4.2.2 {
          267  +  execsql {
          268  +    SELECT * FROM test.abc;
          269  +  } db2
          270  +} {i ii iii}
          271  +
          272  +catch {db2 close}
          273  +catch {db close}
   220    274   
   221    275   finish_test
   222    276   sqlite3_enable_shared_cache $::enable_shared_cache
   223    277