/ Check-in [e2112d61]
Login

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

Overview
Comment:Simplify the way the read-uncommitted flag is handled to facilitate test coverage. (CVS 6841)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e2112d6160a82ccd4b6a1c798d2064d0f1b086eb
User & Date: danielk1977 2009-07-03 16:25:07
Context
2009-07-03
17:09
Add a version of the Lemon parser template "lempar.c" to the src/ subfolder. This new parser template contains a couple of NEVER() macros that disable tests that are needed for general grammars but not for the specific grammar used by SQLite. SQLite builds with the modified lempar.c. (CVS 6842) check-in: d426cc64 user: drh tags: trunk
16:25
Simplify the way the read-uncommitted flag is handled to facilitate test coverage. (CVS 6841) check-in: e2112d61 user: danielk1977 tags: trunk
15:37
Make explicit the restrictions on UPDATE, DELETE, and INSERT statement syntax within triggers. Ticket #3947. (CVS 6840) check-in: c8bf40df 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.649 2009/07/02 17:21:58 danielk1977 Exp $
           12  +** $Id: btree.c,v 1.650 2009/07/03 16:25:07 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** See the header comment on "btreeInt.h" for additional information.
    16     16   ** Including a description of file format and an overview of operation.
    17     17   */
    18     18   #include "btreeInt.h"
    19     19   
................................................................................
   198    198   static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
   199    199     BtShared *pBt = p->pBt;
   200    200     BtLock *pIter;
   201    201   
   202    202     assert( sqlite3BtreeHoldsMutex(p) );
   203    203     assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
   204    204     assert( p->db!=0 );
          205  +  assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
   205    206     
   206    207     /* If requesting a write-lock, then the Btree must have an open write
   207    208     ** transaction on this file. And, obviously, for this to be so there 
   208    209     ** must be an open write transaction on the file itself.
   209    210     */
   210    211     assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
   211    212     assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
................................................................................
   219    220     ** requested lock may not be obtained.
   220    221     */
   221    222     if( pBt->pWriter!=p && pBt->isExclusive ){
   222    223       sqlite3ConnectionBlocked(p->db, pBt->pWriter->db);
   223    224       return SQLITE_LOCKED_SHAREDCACHE;
   224    225     }
   225    226   
   226         -  /* This (along with setSharedCacheTableLock()) is where
   227         -  ** the ReadUncommitted flag is dealt with.
   228         -  ** If the caller is querying for a read-lock on any table
   229         -  ** other than the sqlite_master table (table 1) and if the ReadUncommitted
   230         -  ** flag is set, then the lock granted even if there are write-locks
   231         -  ** on the table. If a write-lock is requested, the ReadUncommitted flag
   232         -  ** is not considered.
   233         -  **
   234         -  ** In function setSharedCacheTableLock(), if a read-lock is demanded and the 
   235         -  ** ReadUncommitted flag is set, no entry is added to the locks list 
   236         -  ** (BtShared.pLock).
   237         -  **
   238         -  ** To summarize: If the ReadUncommitted flag is set, then read cursors
   239         -  ** on non-schema tables do not create or respect table locks. The locking
   240         -  ** procedure for a write-cursor does not change.
   241         -  */
   242         -  if( 
   243         -    0==(p->db->flags&SQLITE_ReadUncommitted) || 
   244         -    eLock==WRITE_LOCK ||
   245         -    iTab==MASTER_ROOT
   246         -  ){
   247         -    for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
   248         -      /* The condition (pIter->eLock!=eLock) in the following if(...) 
   249         -      ** statement is a simplification of:
   250         -      **
   251         -      **   (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
   252         -      **
   253         -      ** since we know that if eLock==WRITE_LOCK, then no other connection
   254         -      ** may hold a WRITE_LOCK on any table in this file (since there can
   255         -      ** only be a single writer).
   256         -      */
   257         -      assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK );
   258         -      assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK);
   259         -      if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
   260         -        sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
   261         -        if( eLock==WRITE_LOCK ){
   262         -          assert( p==pBt->pWriter );
   263         -          pBt->isPending = 1;
   264         -        }
   265         -        return SQLITE_LOCKED_SHAREDCACHE;
   266         -      }
          227  +  for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
          228  +    /* The condition (pIter->eLock!=eLock) in the following if(...) 
          229  +    ** statement is a simplification of:
          230  +    **
          231  +    **   (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
          232  +    **
          233  +    ** since we know that if eLock==WRITE_LOCK, then no other connection
          234  +    ** may hold a WRITE_LOCK on any table in this file (since there can
          235  +    ** only be a single writer).
          236  +    */
          237  +    assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK );
          238  +    assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK);
          239  +    if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
          240  +      sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
          241  +      if( eLock==WRITE_LOCK ){
          242  +        assert( p==pBt->pWriter );
          243  +        pBt->isPending = 1;
          244  +      }
          245  +      return SQLITE_LOCKED_SHAREDCACHE;
   267    246       }
   268    247     }
   269    248     return SQLITE_OK;
   270    249   }
   271    250   #endif /* !SQLITE_OMIT_SHARED_CACHE */
   272    251   
   273    252   #ifndef SQLITE_OMIT_SHARED_CACHE
................................................................................
   284    263     BtLock *pLock = 0;
   285    264     BtLock *pIter;
   286    265   
   287    266     assert( sqlite3BtreeHoldsMutex(p) );
   288    267     assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
   289    268     assert( p->db!=0 );
   290    269   
          270  +  /* A connection with the read-uncommitted flag set will never try to
          271  +  ** obtain a read-lock using this function. The only read-lock obtained
          272  +  ** by a connection in read-uncommitted mode is on the sqlite_master 
          273  +  ** table, and that lock is obtained in BtreeBeginTrans().  */
          274  +  assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
          275  +
   291    276     /* This is a no-op if the shared-cache is not enabled */
   292    277     if( !p->sharable ){
   293    278       return SQLITE_OK;
   294    279     }
   295    280   
   296    281     assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
   297    282   
   298         -  /* If the read-uncommitted flag is set and a read-lock is requested on
   299         -  ** a non-schema table, then the lock is always granted.  Return early
   300         -  ** without adding an entry to the BtShared.pLock list. See
   301         -  ** comment in function querySharedCacheTableLock() for more info
   302         -  ** on handling the ReadUncommitted flag.
   303         -  */
   304         -  if( 
   305         -    (p->db->flags&SQLITE_ReadUncommitted) && 
   306         -    (eLock==READ_LOCK) &&
   307         -    iTable!=MASTER_ROOT
   308         -  ){
   309         -    return SQLITE_OK;
   310         -  }
   311         -
   312    283     /* First search the list for an existing lock on this table. */
   313    284     for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
   314    285       if( pIter->iTable==iTable && pIter->pBtree==p ){
   315    286         pLock = pIter;
   316    287         break;
   317    288       }
   318    289     }
................................................................................
   391    362       ** If there is not currently a writer, then BtShared.isPending must
   392    363       ** be zero already. So this next line is harmless in that case.
   393    364       */
   394    365       pBt->isPending = 0;
   395    366     }
   396    367   }
   397    368   
          369  +/*
          370  +** This function changes all write-locks held by connection p to read-locks.
          371  +*/
   398    372   static void downgradeAllSharedCacheTableLocks(Btree *p){
   399    373     BtShared *pBt = p->pBt;
   400    374     if( pBt->pWriter==p ){
   401    375       BtLock *pLock;
   402    376       pBt->pWriter = 0;
   403    377       pBt->isExclusive = 0;
   404    378       pBt->isPending = 0;
................................................................................
  7028   7002   ** free pages is not visible.  So Cookie[0] is the same as Meta[1].
  7029   7003   */
  7030   7004   void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
  7031   7005     BtShared *pBt = p->pBt;
  7032   7006   
  7033   7007     sqlite3BtreeEnter(p);
  7034   7008     assert( p->inTrans>TRANS_NONE );
  7035         -  assert( SQLITE_OK==querySharedCacheTableLock(p, 1, READ_LOCK) );
         7009  +  assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
  7036   7010     assert( pBt->pPage1 );
  7037   7011     assert( idx>=0 && idx<=15 );
  7038   7012   
  7039   7013     *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
  7040   7014   
  7041   7015     /* If auto-vacuum is disabled in this build and this is an auto-vacuum
  7042   7016     ** database, mark the database as read-only.  */

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.868 2009/07/02 07:47:33 danielk1977 Exp $
           46  +** $Id: vdbe.c,v 1.869 2009/07/03 16:25:07 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "vdbeInt.h"
    50     50   
    51     51   /*
    52     52   ** The following global variable is incremented every time a cursor
    53     53   ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test
................................................................................
  4999   4999   **
  5000   5000   ** P2 contains the root-page of the table to lock.
  5001   5001   **
  5002   5002   ** P4 contains a pointer to the name of the table being locked. This is only
  5003   5003   ** used to generate an error message if the lock cannot be obtained.
  5004   5004   */
  5005   5005   case OP_TableLock: {
  5006         -  int p1;
  5007         -  u8 isWriteLock;
  5008         -
  5009         -  p1 = pOp->p1; 
  5010         -  isWriteLock = (u8)pOp->p3;
  5011         -  assert( p1>=0 && p1<db->nDb );
  5012         -  assert( (p->btreeMask & (1<<p1))!=0 );
  5013         -  assert( isWriteLock==0 || isWriteLock==1 );
  5014         -  rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
  5015         -  if( (rc&0xFF)==SQLITE_LOCKED ){
  5016         -    const char *z = pOp->p4.z;
  5017         -    sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
         5006  +  u8 isWriteLock = (u8)pOp->p3;
         5007  +  if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
         5008  +    int p1 = pOp->p1; 
         5009  +    assert( p1>=0 && p1<db->nDb );
         5010  +    assert( (p->btreeMask & (1<<p1))!=0 );
         5011  +    assert( isWriteLock==0 || isWriteLock==1 );
         5012  +    rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
         5013  +    if( (rc&0xFF)==SQLITE_LOCKED ){
         5014  +      const char *z = pOp->p4.z;
         5015  +      sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
         5016  +    }
  5018   5017     }
  5019   5018     break;
  5020   5019   }
  5021   5020   #endif /* SQLITE_OMIT_SHARED_CACHE */
  5022   5021   
  5023   5022   #ifndef SQLITE_OMIT_VIRTUALTABLE
  5024   5023   /* Opcode: VBegin * * * P4 *