/ Check-in [81ff8107]
Login

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

Overview
Comment:Add support for DEFERRED, IMMEDIATE, and EXCLUSIVE transactions. (CVS 2000)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 81ff8107ad63113782cf5a9ba7a512496114ba08
User & Date: drh 2004-10-05 02:41:42
Context
2004-10-05
15:42
Use the database name supplied to table_info() and related pragmas. (CVS 2001) check-in: 0415af32 user: drh tags: trunk
02:41
Add support for DEFERRED, IMMEDIATE, and EXCLUSIVE transactions. (CVS 2000) check-in: 81ff8107 user: drh tags: trunk
2004-10-04
13:38
More changes to take advantage of the TK_ and OP_ alignments to avoid unnecessary translations. (CVS 1999) check-in: e8e972ba 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.191 2004/09/27 13:19:52 drh Exp $
           12  +** $Id: btree.c,v 1.192 2004/10/05 02:41:42 drh 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.
................................................................................
  1285   1285     zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
  1286   1286     pBt->pageSizeFixed = 1;
  1287   1287     return SQLITE_OK;
  1288   1288   }
  1289   1289   
  1290   1290   /*
  1291   1291   ** Attempt to start a new transaction. A write-transaction
  1292         -** is started if the second argument is true, otherwise a read-
  1293         -** transaction.
         1292  +** is started if the second argument is nonzero, otherwise a read-
         1293  +** transaction.  If the second argument is 2 or more and exclusive
         1294  +** transaction is started, meaning that no other process is allowed
         1295  +** to access the database.  A preexisting transaction may not be
         1296  +** upgrade to exclusive by calling this routine a second time - the
         1297  +** exclusivity flag only works for a new transaction.
  1294   1298   **
  1295   1299   ** A write-transaction must be started before attempting any 
  1296   1300   ** changes to the database.  None of the following routines 
  1297   1301   ** will work unless a transaction is started first:
  1298   1302   **
  1299   1303   **      sqlite3BtreeCreateTable()
  1300   1304   **      sqlite3BtreeCreateIndex()
................................................................................
  1325   1329     }
  1326   1330   
  1327   1331     if( pBt->pPage1==0 ){
  1328   1332       rc = lockBtree(pBt);
  1329   1333     }
  1330   1334   
  1331   1335     if( rc==SQLITE_OK && wrflag ){
  1332         -    rc = sqlite3pager_begin(pBt->pPage1->aData);
         1336  +    rc = sqlite3pager_begin(pBt->pPage1->aData, wrflag>1);
  1333   1337       if( rc==SQLITE_OK ){
  1334   1338         rc = newDatabase(pBt);
  1335   1339       }
  1336   1340     }
  1337   1341   
  1338   1342     if( rc==SQLITE_OK ){
  1339   1343       pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);

Changes to src/build.c.

    19     19   **     DROP INDEX
    20     20   **     creating ID lists
    21     21   **     BEGIN TRANSACTION
    22     22   **     COMMIT
    23     23   **     ROLLBACK
    24     24   **     PRAGMA
    25     25   **
    26         -** $Id: build.c,v 1.255 2004/09/30 14:22:47 drh Exp $
           26  +** $Id: build.c,v 1.256 2004/10/05 02:41:42 drh Exp $
    27     27   */
    28     28   #include "sqliteInt.h"
    29     29   #include <ctype.h>
    30     30   
    31     31   /*
    32     32   ** This routine is called when a new SQL statement is beginning to
    33     33   ** be parsed.  Check to see if the schema for the database needs
................................................................................
  1372   1372       }
  1373   1373       sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
  1374   1374       sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
  1375   1375       sqlite3ChangeCookie(db, v, p->iDb);
  1376   1376       sqlite3VdbeAddOp(v, OP_Close, 0, 0);
  1377   1377       sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0,
  1378   1378           sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC);
  1379         -
  1380         -    sqlite3EndWriteOperation(pParse);
  1381   1379     }
  1382   1380   
  1383   1381     /* Add the table to the in-memory representation of the database.
  1384   1382     */
  1385   1383     if( db->init.busy && pParse->nErr==0 ){
  1386   1384       Table *pOld;
  1387   1385       FKey *pFKey; 
................................................................................
  1659   1657       if( !isView ){
  1660   1658         sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb);
  1661   1659         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
  1662   1660           sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
  1663   1661         }
  1664   1662       }
  1665   1663       sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
  1666         -    sqlite3EndWriteOperation(pParse);
  1667   1664     }
  1668   1665     sqliteViewResetAll(db, iDb);
  1669   1666   
  1670   1667   exit_drop_table:
  1671   1668     sqlite3SrcListDelete(pName);
  1672   1669   }
  1673   1670   
................................................................................
  2127   2124                         "indexed columns are not unique", P3_STATIC);
  2128   2125         sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
  2129   2126         sqlite3VdbeResolveLabel(v, lbl2);
  2130   2127         sqlite3VdbeAddOp(v, OP_Close, 2, 0);
  2131   2128         sqlite3VdbeAddOp(v, OP_Close, 1, 0);
  2132   2129         sqlite3ChangeCookie(db, v, iDb);
  2133   2130         sqlite3VdbeAddOp(v, OP_Close, 0, 0);
  2134         -      sqlite3EndWriteOperation(pParse);
  2135   2131         sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
  2136   2132            sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC);
  2137   2133       }
  2138   2134     }
  2139   2135   
  2140   2136     /* When adding an index to the list of indices for a table, make
  2141   2137     ** sure all indices labeled OE_Replace come after all those labeled
................................................................................
  2228   2224       sqlite3OpenMasterTable(v, pIndex->iDb);
  2229   2225       base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
  2230   2226       sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0);
  2231   2227       sqlite3ChangeCookie(db, v, pIndex->iDb);
  2232   2228       sqlite3VdbeAddOp(v, OP_Close, 0, 0);
  2233   2229       sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
  2234   2230       sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
  2235         -    sqlite3EndWriteOperation(pParse);
  2236   2231     }
  2237   2232   
  2238   2233   exit_drop_index:
  2239   2234     sqlite3SrcListDelete(pName);
  2240   2235   }
  2241   2236   
  2242   2237   /*
................................................................................
  2394   2389     }
  2395   2390     sqliteFree(pList);
  2396   2391   }
  2397   2392   
  2398   2393   /*
  2399   2394   ** Begin a transaction
  2400   2395   */
  2401         -void sqlite3BeginTransaction(Parse *pParse){
         2396  +void sqlite3BeginTransaction(Parse *pParse, int type){
  2402   2397     sqlite3 *db;
  2403   2398     Vdbe *v;
         2399  +  int i;
  2404   2400   
  2405   2401     if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
  2406   2402     if( pParse->nErr || sqlite3_malloc_failed ) return;
  2407   2403     if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
  2408   2404   
  2409   2405     v = sqlite3GetVdbe(pParse);
  2410   2406     if( !v ) return;
         2407  +  if( type!=TK_DEFERRED ){
         2408  +    for(i=0; i<db->nDb; i++){
         2409  +      sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
         2410  +    }
         2411  +  }
  2411   2412     sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0);
  2412   2413   }
  2413   2414   
  2414   2415   /*
  2415   2416   ** Commit a transaction
  2416   2417   */
  2417   2418   void sqlite3CommitTransaction(Parse *pParse){
................................................................................
  2547   2548       sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
  2548   2549     }
  2549   2550     if( iDb!=1 && pParse->db->aDb[1].pBt!=0 ){
  2550   2551       sqlite3BeginWriteOperation(pParse, setStatement, 1);
  2551   2552     }
  2552   2553   }
  2553   2554   
  2554         -/*
  2555         -** Generate code that concludes an operation that may have changed
  2556         -** the database.  If a statement transaction was started, then emit
  2557         -** an OP_Commit that will cause the changes to be committed to disk.
  2558         -**
  2559         -** Note that checkpoints are automatically committed at the end of
  2560         -** a statement.  Note also that there can be multiple calls to 
  2561         -** sqlite3BeginWriteOperation() but there should only be a single
  2562         -** call to sqlite3EndWriteOperation() at the conclusion of the statement.
  2563         -*/
  2564         -void sqlite3EndWriteOperation(Parse *pParse){
  2565         -  /* Delete me! */
  2566         -  return;
  2567         -}
  2568         -
  2569   2555   /* 
  2570   2556   ** Return the transient sqlite3_value object used for encoding conversions
  2571   2557   ** during SQL compilation.
  2572   2558   */
  2573   2559   sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){
  2574   2560     if( !db->pValue ){
  2575   2561       db->pValue = sqlite3ValueNew();
  2576   2562     }
  2577   2563     return db->pValue;
  2578   2564   }

Changes to src/delete.c.

     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     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle DELETE FROM statements.
    14     14   **
    15         -** $Id: delete.c,v 1.81 2004/09/19 02:15:25 drh Exp $
           15  +** $Id: delete.c,v 1.82 2004/10/05 02:41:42 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Look up every table that is named in pSrc.  If any table is not found,
    21     21   ** add an error message to pParse->zErrMsg and return NULL.  If all tables
    22     22   ** are found, return a pointer to the last table.
................................................................................
   303    303       if( !row_triggers_exist ){
   304    304         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
   305    305           sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
   306    306         }
   307    307         sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
   308    308       }
   309    309     }
   310         -  sqlite3EndWriteOperation(pParse);
   311    310   
   312    311     /*
   313    312     ** Return the number of rows that were deleted.
   314    313     */
   315    314     if( db->flags & SQLITE_CountRows ){
   316    315       sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
   317    316       sqlite3VdbeSetNumCols(v, 1);

Changes to src/insert.c.

     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     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle INSERT statements in SQLite.
    14     14   **
    15         -** $Id: insert.c,v 1.118 2004/09/19 02:15:26 drh Exp $
           15  +** $Id: insert.c,v 1.119 2004/10/05 02:41:42 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Set P3 of the most recently inserted opcode to a column affinity
    21     21   ** string for index pIdx. A column affinity string has one character
    22     22   ** for each column in the table, according to the affinity of the column:
................................................................................
   612    612       /* Close all tables opened */
   613    613       sqlite3VdbeAddOp(v, OP_Close, base, 0);
   614    614       for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
   615    615         sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
   616    616       }
   617    617     }
   618    618   
   619         -  sqlite3EndWriteOperation(pParse);
   620         -
   621    619     /*
   622    620     ** Return the number of rows inserted.
   623    621     */
   624    622     if( db->flags & SQLITE_CountRows ){
   625    623       sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
   626    624       sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
   627    625       sqlite3VdbeSetNumCols(v, 1);

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.166 2004/10/02 20:38:28 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.167 2004/10/05 02:41:43 drh Exp $
    22     22   */
    23     23   #include "sqliteInt.h"
    24     24   #include "os.h"
    25     25   #include "pager.h"
    26     26   #include <assert.h>
    27     27   #include <string.h>
    28     28   
................................................................................
    84     84   ** called on an outstanding page which means that the pager must
    85     85   ** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)
    86     86   ** The transition to PAGER_EXCLUSIVE occurs when before any changes
    87     87   ** are made to the database file.  After an sqlite3pager_rollback()
    88     88   ** or sqlite_pager_commit(), the state goes back to PAGER_SHARED.
    89     89   */
    90     90   #define PAGER_UNLOCK      0
    91         -#define PAGER_SHARED      1
    92         -#define PAGER_RESERVED    2
    93         -#define PAGER_EXCLUSIVE   3
    94         -#define PAGER_SYNCED      4
           91  +#define PAGER_SHARED      1   /* same as SHARED_LOCK */
           92  +#define PAGER_RESERVED    2   /* same as RESERVED_LOCK */
           93  +#define PAGER_EXCLUSIVE   4   /* same as EXCLUSIVE_LOCK */
           94  +#define PAGER_SYNCED      5
    95     95   
           96  +/*
           97  +** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time,
           98  +** then failed attempts to get a reserved lock will invoke the busy callback.
           99  +** This is off by default.  To see why, consider the following scenario:
          100  +** 
          101  +** Suppose thread A already has a shared lock and wants a reserved lock.
          102  +** Thread B already has a reserved lock and wants an exclusive lock.  If
          103  +** both threads are using their busy callbacks, it might be a long time
          104  +** be for one of the threads give up and allows the other to proceed.
          105  +** But if the thread trying to get the reserved lock gives up quickly
          106  +** (if it never invokes its busy callback) then the contention will be
          107  +** resolved quickly.
          108  +*/
          109  +#ifndef SQLITE_BUSY_RESERVED_LOCK
          110  +# define SQLITE_BUSY_RESERVED_LOCK 0
          111  +#endif
    96    112   
    97    113   /*
    98    114   ** Each in-memory image of a page begins with the following header.
    99    115   ** This header is only visible to this pager module.  The client
   100    116   ** code that calls pager sees only the data that follows the header.
   101    117   **
   102    118   ** Client code should call sqlite3pager_write() on a page prior to making
................................................................................
  1902   1918       }
  1903   1919       assert( pPager->pFirstSynced==pPager->pFirst );
  1904   1920     }
  1905   1921   #endif
  1906   1922   
  1907   1923     return rc;
  1908   1924   }
         1925  +
         1926  +/*
         1927  +** Try to obtain a lock on a file.  Invoke the busy callback if the lock
         1928  +** is currently not available.  Repeate until the busy callback returns
         1929  +** false or until the lock succeeds.
         1930  +**
         1931  +** Return SQLITE_OK on success and an error code if we cannot obtain
         1932  +** the lock.
         1933  +*/
         1934  +static int pager_wait_on_lock(Pager *pPager, int locktype){
         1935  +  int rc;
         1936  +  assert( PAGER_SHARED==SHARED_LOCK );
         1937  +  assert( PAGER_RESERVED==RESERVED_LOCK );
         1938  +  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
         1939  +  if( pPager->state>=locktype ){
         1940  +    rc = SQLITE_OK;
         1941  +  }else{
         1942  +    int busy = 1;
         1943  +    do {
         1944  +      rc = sqlite3OsLock(&pPager->fd, locktype);
         1945  +    }while( rc==SQLITE_BUSY && 
         1946  +        pPager->pBusyHandler && 
         1947  +        pPager->pBusyHandler->xFunc && 
         1948  +        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
         1949  +    );
         1950  +    if( rc==SQLITE_OK ){
         1951  +      pPager->state = locktype;
         1952  +    }
         1953  +  }
         1954  +  return rc;
         1955  +}
  1909   1956   
  1910   1957   /*
  1911   1958   ** Given a list of pages (connected by the PgHdr.pDirty pointer) write
  1912   1959   ** every one of those pages out to the database file and mark them all
  1913   1960   ** as clean.
  1914   1961   */
  1915   1962   static int pager_write_pagelist(PgHdr *pList){
  1916   1963     Pager *pPager;
  1917   1964     int rc;
  1918         -  int busy = 1;
  1919   1965   
  1920   1966     if( pList==0 ) return SQLITE_OK;
  1921   1967     pPager = pList->pPager;
  1922   1968   
  1923   1969     /* At this point there may be either a RESERVED or EXCLUSIVE lock on the
  1924   1970     ** database file. If there is already an EXCLUSIVE lock, the following
  1925   1971     ** calls to sqlite3OsLock() are no-ops.
................................................................................
  1932   1978     **
  1933   1979     ** While the pager is in the RESERVED state, the original database file
  1934   1980     ** is unchanged and we can rollback without having to playback the
  1935   1981     ** journal into the original database file.  Once we transition to
  1936   1982     ** EXCLUSIVE, it means the database file has been changed and any rollback
  1937   1983     ** will require a journal playback.
  1938   1984     */
  1939         -  do {
  1940         -    rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK);
  1941         -  }while( rc==SQLITE_BUSY && 
  1942         -      pPager->pBusyHandler && 
  1943         -      pPager->pBusyHandler->xFunc && 
  1944         -      pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
  1945         -  );
         1985  +  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
  1946   1986     if( rc!=SQLITE_OK ){
  1947   1987       return rc;
  1948   1988     }
  1949         -  pPager->state = PAGER_EXCLUSIVE;
  1950   1989   
  1951   1990     while( pList ){
  1952   1991       assert( pList->dirty );
  1953   1992       sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
  1954   1993       CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
  1955   1994       TRACE3("STORE %d page %d\n", pPager->fd.h, pList->pgno);
  1956   1995       rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize);
................................................................................
  2015   2054       return pager_errcode(pPager);
  2016   2055     }
  2017   2056   
  2018   2057     /* If this is the first page accessed, then get a SHARED lock
  2019   2058     ** on the database file.
  2020   2059     */
  2021   2060     if( pPager->nRef==0 && !pPager->memDb ){
  2022         -    int busy = 1;
  2023         -    do {
  2024         -      rc = sqlite3OsLock(&pPager->fd, SHARED_LOCK);
  2025         -    }while( rc==SQLITE_BUSY && 
  2026         -        pPager->pBusyHandler && 
  2027         -        pPager->pBusyHandler->xFunc && 
  2028         -        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
  2029         -    );
         2061  +    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
  2030   2062       if( rc!=SQLITE_OK ){
  2031   2063         return rc;
  2032   2064       }
  2033         -    pPager->state = PAGER_SHARED;
  2034   2065   
  2035   2066       /* If a journal file exists, and there is no RESERVED lock on the
  2036   2067       ** database file, then it either needs to be played back or deleted.
  2037   2068       */
  2038   2069       if( pPager->useJournal && 
  2039   2070           sqlite3OsFileExists(pPager->zJournal) &&
  2040   2071           !sqlite3OsCheckReservedLock(&pPager->fd) 
................................................................................
  2404   2435   ** master journal file-name at the start of the journal when it is created.
  2405   2436   **
  2406   2437   ** A journal file is opened if this is not a temporary file.  For temporary
  2407   2438   ** files, the opening of the journal file is deferred until there is an
  2408   2439   ** actual need to write to the journal.
  2409   2440   **
  2410   2441   ** If the database is already reserved for writing, this routine is a no-op.
         2442  +**
         2443  +** If exFlag is true, go ahead and get an EXCLUSIVE lock on the file
         2444  +** immediately instead of waiting until we try to flush the cache.  The
         2445  +** exFlag is ignored if a transaction is already active.
  2411   2446   */
  2412         -int sqlite3pager_begin(void *pData){
         2447  +int sqlite3pager_begin(void *pData, int exFlag){
  2413   2448     PgHdr *pPg = DATA_TO_PGHDR(pData);
  2414   2449     Pager *pPager = pPg->pPager;
  2415   2450     int rc = SQLITE_OK;
  2416   2451     assert( pPg->nRef>0 );
  2417   2452     assert( pPager->state!=PAGER_UNLOCK );
  2418   2453     if( pPager->state==PAGER_SHARED ){
  2419   2454       assert( pPager->aInJournal==0 );
  2420   2455       if( pPager->memDb ){
  2421   2456         pPager->state = PAGER_EXCLUSIVE;
  2422   2457         pPager->origDbSize = pPager->dbSize;
  2423   2458       }else{
  2424         -#ifdef SQLITE_BUSY_RESERVED_LOCK
  2425         -      int busy = 1;
  2426         -      do {
         2459  +      if( SQLITE_BUSY_RESERVED_LOCK || exFlag ){
         2460  +        rc = pager_wait_on_lock(pPager, RESERVED_LOCK);
         2461  +      }else{
  2427   2462           rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
  2428         -      }while( rc==SQLITE_BUSY && 
  2429         -          pPager->pBusyHandler && 
  2430         -          pPager->pBusyHandler->xFunc && 
  2431         -          pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
  2432         -      );
  2433         -#else
  2434         -      rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
  2435         -#endif
         2463  +      }
         2464  +      if( rc==SQLITE_OK ){
         2465  +        pPager->state = PAGER_RESERVED;
         2466  +        if( exFlag ){
         2467  +          rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
         2468  +        }
         2469  +      }
  2436   2470         if( rc!=SQLITE_OK ){
  2437         -        /* We do not call the busy handler when we fail to get a reserved lock.
  2438         -        ** The only reason we might fail is because another process is holding
  2439         -        ** the reserved lock.  But the other process will not be able to
  2440         -        ** release its reserved lock until this process releases its shared
  2441         -        ** lock.  So we might as well fail in this process, let it release
  2442         -        ** its shared lock so that the other process can commit.
  2443         -        */
  2444   2471           return rc;
  2445   2472         }
  2446         -      pPager->state = PAGER_RESERVED;
  2447   2473         pPager->dirtyCache = 0;
  2448   2474         TRACE2("TRANSACTION %d\n", pPager->fd.h);
  2449   2475         if( pPager->useJournal && !pPager->tempFile ){
  2450   2476           rc = pager_open_journal(pPager);
  2451   2477         }
  2452   2478       }
  2453   2479     }
................................................................................
  2500   2526     ** written to the transaction journal or the ckeckpoint journal
  2501   2527     ** or both.
  2502   2528     **
  2503   2529     ** First check to see that the transaction journal exists and
  2504   2530     ** create it if it does not.
  2505   2531     */
  2506   2532     assert( pPager->state!=PAGER_UNLOCK );
  2507         -  rc = sqlite3pager_begin(pData);
         2533  +  rc = sqlite3pager_begin(pData, 0);
  2508   2534     if( rc!=SQLITE_OK ){
  2509   2535       return rc;
  2510   2536     }
  2511   2537     assert( pPager->state>=PAGER_RESERVED );
  2512   2538     if( !pPager->journalOpen && pPager->useJournal ){
  2513   2539       rc = pager_open_journal(pPager);
  2514   2540       if( rc!=SQLITE_OK ) return rc;

Changes to src/pager.h.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite page cache
    13     13   ** subsystem.  The page cache subsystem reads and writes a file a page
    14     14   ** at a time and provides a journal for rollback.
    15     15   **
    16         -** @(#) $Id: pager.h,v 1.37 2004/07/22 01:19:35 drh Exp $
           16  +** @(#) $Id: pager.h,v 1.38 2004/10/05 02:41:43 drh Exp $
    17     17   */
    18     18   
    19     19   /*
    20     20   ** The default size of a database page.
    21     21   */
    22     22   #ifndef SQLITE_DEFAULT_PAGE_SIZE
    23     23   # define SQLITE_DEFAULT_PAGE_SIZE 1024
................................................................................
    70     70   int sqlite3pager_unref(void*);
    71     71   Pgno sqlite3pager_pagenumber(void*);
    72     72   int sqlite3pager_write(void*);
    73     73   int sqlite3pager_iswriteable(void*);
    74     74   int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*);
    75     75   int sqlite3pager_pagecount(Pager*);
    76     76   int sqlite3pager_truncate(Pager*,Pgno);
    77         -int sqlite3pager_begin(void*);
           77  +int sqlite3pager_begin(void*, int exFlag);
    78     78   int sqlite3pager_commit(Pager*);
    79     79   int sqlite3pager_sync(Pager*,const char *zMaster);
    80     80   int sqlite3pager_rollback(Pager*);
    81     81   int sqlite3pager_isreadonly(Pager*);
    82     82   int sqlite3pager_stmt_begin(Pager*);
    83     83   int sqlite3pager_stmt_commit(Pager*);
    84     84   int sqlite3pager_stmt_rollback(Pager*);

Changes to src/parse.y.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains SQLite's grammar for SQL.  Process this file
    13     13   ** using the lemon parser generator to generate C code that runs
    14     14   ** the parser.  Lemon will also generate a header file containing
    15     15   ** numeric codes for all of the tokens.
    16     16   **
    17         -** @(#) $Id: parse.y,v 1.141 2004/10/04 13:38:09 drh Exp $
           17  +** @(#) $Id: parse.y,v 1.142 2004/10/05 02:41:43 drh Exp $
    18     18   */
    19     19   %token_prefix TK_
    20     20   %token_type {Token}
    21     21   %default_type {Token}
    22     22   %extra_argument {Parse *pParse}
    23     23   %syntax_error {
    24     24     if( pParse->zErrMsg==0 ){
................................................................................
    77     77   cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }
    78     78   explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); }
    79     79   explain ::= .           { sqlite3BeginParse(pParse, 0); }
    80     80   
    81     81   ///////////////////// Begin and end transactions. ////////////////////////////
    82     82   //
    83     83   
    84         -cmd ::= BEGIN trans_opt.  {sqlite3BeginTransaction(pParse);}
           84  +cmd ::= BEGIN transtype(Y) trans_opt.  {sqlite3BeginTransaction(pParse, Y);}
    85     85   trans_opt ::= .
    86     86   trans_opt ::= TRANSACTION.
    87     87   trans_opt ::= TRANSACTION nm.
           88  +%type transtype {int}
           89  +transtype(A) ::= .             {A = TK_DEFERRED;}
           90  +transtype(A) ::= DEFERRED(X).  {A = @X;}
           91  +transtype(A) ::= IMMEDIATE(X). {A = @X;}
           92  +transtype(A) ::= EXCLUSIVE(X). {A = @X;}
    88     93   cmd ::= COMMIT trans_opt.      {sqlite3CommitTransaction(pParse);}
    89     94   cmd ::= END trans_opt.         {sqlite3CommitTransaction(pParse);}
    90     95   cmd ::= ROLLBACK trans_opt.    {sqlite3RollbackTransaction(pParse);}
    91     96   
    92     97   ///////////////////// The CREATE TABLE statement ////////////////////////////
    93     98   //
    94     99   cmd ::= create_table create_table_args.
................................................................................
   123    128   
   124    129   // The following directive causes tokens ABORT, AFTER, ASC, etc. to
   125    130   // fallback to ID if they will not parse as their original value.
   126    131   // This obviates the need for the "id" nonterminal.
   127    132   //
   128    133   %fallback ID
   129    134     ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CONFLICT
   130         -  DATABASE DEFERRED DESC DETACH EACH END EXPLAIN FAIL FOR
          135  +  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
   131    136     GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
   132    137     OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
   133    138     TEMP TRIGGER VACUUM VIEW.
   134    139   
   135    140   // Define operator precedence early so that this is the first occurance
   136    141   // of the operator tokens in the grammer.  Keeping the operators together
   137    142   // causes them to be assigned integer values that are close together,

Changes to src/pragma.c.

     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     12   ** This file contains code used to implement the PRAGMA command.
    13     13   **
    14         -** $Id: pragma.c,v 1.67 2004/09/25 14:39:19 drh Exp $
           14  +** $Id: pragma.c,v 1.68 2004/10/05 02:41:43 drh Exp $
    15     15   */
    16     16   #include "sqliteInt.h"
    17     17   #include <ctype.h>
    18     18   
    19     19   #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
    20     20   # include "pager.h"
    21     21   # include "btree.h"
................................................................................
   257    257         sqlite3BeginWriteOperation(pParse, 0, iDb);
   258    258         sqlite3VdbeAddOp(v, OP_Integer, size, 0);
   259    259         sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2);
   260    260         addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
   261    261         sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3);
   262    262         sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
   263    263         sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2);
   264         -      sqlite3EndWriteOperation(pParse);
   265    264         pDb->cache_size = size;
   266    265         sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);
   267    266       }
   268    267     }else
   269    268   
   270    269     /*
   271    270     **  PRAGMA [database.]page_size

Changes to src/sqliteInt.h.

     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     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.326 2004/10/04 13:19:24 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.327 2004/10/05 02:41:43 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** These #defines should enable >2GB file support on Posix if the
    21     21   ** underlying operating system supports it.  If the OS lacks
................................................................................
  1306   1306   int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
  1307   1307   int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*);
  1308   1308   int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
  1309   1309   Vdbe *sqlite3GetVdbe(Parse*);
  1310   1310   void sqlite3Randomness(int, void*);
  1311   1311   void sqlite3RollbackAll(sqlite3*);
  1312   1312   void sqlite3CodeVerifySchema(Parse*, int);
  1313         -void sqlite3BeginTransaction(Parse*);
         1313  +void sqlite3BeginTransaction(Parse*, int);
  1314   1314   void sqlite3CommitTransaction(Parse*);
  1315   1315   void sqlite3RollbackTransaction(Parse*);
  1316   1316   int sqlite3ExprIsConstant(Expr*);
  1317   1317   int sqlite3ExprIsInteger(Expr*, int*);
  1318   1318   int sqlite3IsRowid(const char*);
  1319   1319   void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int);
  1320   1320   void sqlite3GenerateRowIndexDelete(sqlite3*, Vdbe*, Table*, int, char*);
  1321   1321   void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
  1322   1322   void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
  1323   1323   void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int);
  1324   1324   void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
  1325   1325   void sqlite3BeginWriteOperation(Parse*, int, int);
  1326         -void sqlite3EndWriteOperation(Parse*);
  1327   1326   Expr *sqlite3ExprDup(Expr*);
  1328   1327   void sqlite3TokenCopy(Token*, Token*);
  1329   1328   ExprList *sqlite3ExprListDup(ExprList*);
  1330   1329   SrcList *sqlite3SrcListDup(SrcList*);
  1331   1330   IdList *sqlite3IdListDup(IdList*);
  1332   1331   Select *sqlite3SelectDup(Select*);
  1333   1332   FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);

Changes to src/tokenize.c.

    11     11   *************************************************************************
    12     12   ** An tokenizer for SQL
    13     13   **
    14     14   ** This file contains C code that splits an SQL input string up into
    15     15   ** individual tokens and sends those tokens one-by-one over to the
    16     16   ** parser for analysis.
    17     17   **
    18         -** $Id: tokenize.c,v 1.89 2004/09/25 15:25:26 drh Exp $
           18  +** $Id: tokenize.c,v 1.90 2004/10/05 02:41:43 drh Exp $
    19     19   */
    20     20   #include "sqliteInt.h"
    21     21   #include "os.h"
    22     22   #include <ctype.h>
    23     23   #include <stdlib.h>
    24     24   
    25     25   /*
................................................................................
    67     67     { "DETACH",            TK_DETACH,       },
    68     68     { "DISTINCT",          TK_DISTINCT,     },
    69     69     { "DROP",              TK_DROP,         },
    70     70     { "END",               TK_END,          },
    71     71     { "EACH",              TK_EACH,         },
    72     72     { "ELSE",              TK_ELSE,         },
    73     73     { "EXCEPT",            TK_EXCEPT,       },
           74  +  { "EXCLUSIVE",         TK_EXCLUSIVE,    },
    74     75     { "EXPLAIN",           TK_EXPLAIN,      },
    75     76     { "FAIL",              TK_FAIL,         },
    76     77     { "FOR",               TK_FOR,          },
    77     78     { "FOREIGN",           TK_FOREIGN,      },
    78     79     { "FROM",              TK_FROM,         },
    79     80     { "FULL",              TK_JOIN_KW,      },
    80     81     { "GLOB",              TK_GLOB,         },

Changes to src/trigger.c.

   237    237       sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n);
   238    238       if( nt->iDb!=0 ){
   239    239         sqlite3ChangeCookie(db, v, nt->iDb);
   240    240       }
   241    241       sqlite3VdbeAddOp(v, OP_Close, 0, 0);
   242    242       sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0, 
   243    243          sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC);
   244         -    sqlite3EndWriteOperation(pParse);
   245    244     }
   246    245   
   247    246     if( db->init.busy ){
   248    247       Table *pTab;
   249    248       sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, 
   250    249                        nt->name, strlen(nt->name)+1, nt);
   251    250       pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);

Changes to src/update.c.

     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     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle UPDATE statements.
    14     14   **
    15         -** $Id: update.c,v 1.89 2004/09/19 02:15:26 drh Exp $
           15  +** $Id: update.c,v 1.90 2004/10/05 02:41:43 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Process an UPDATE statement.
    21     21   **
    22     22   **   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
   426    426       }
   427    427       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
   428    428     }else{
   429    429       sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
   430    430       sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
   431    431     }
   432    432   
   433         -  sqlite3EndWriteOperation(pParse);
   434         -
   435    433     /*
   436    434     ** Return the number of rows that were changed.
   437    435     */
   438    436     if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
   439    437       sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
   440    438       sqlite3VdbeSetNumCols(v, 1);
   441    439       sqlite3VdbeSetColName(v, 0, "rows updated", P3_STATIC);

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.416 2004/10/04 13:19:24 drh Exp $
           46  +** $Id: vdbe.c,v 1.417 2004/10/05 02:41:43 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
  2153   2153   ** file used for temporary tables.
  2154   2154   **
  2155   2155   ** If P2 is non-zero, then a write-transaction is started.  A RESERVED lock is
  2156   2156   ** obtained on the database file when a write-transaction is started.  No
  2157   2157   ** other process can start another write transaction while this transaction is
  2158   2158   ** underway.  Starting a write transaction also creates a rollback journal. A
  2159   2159   ** write transaction must be started before any changes can be made to the
  2160         -** database.
         2160  +** database.  If P2 is 2 or greater then an EXCLUSIVE lock is also obtained
         2161  +** on the file.
  2161   2162   **
  2162   2163   ** If P2 is zero, then a read-lock is obtained on the database file.
  2163   2164   */
  2164   2165   case OP_Transaction: {
  2165   2166     int i = pOp->p1;
  2166   2167     Btree *pBt;
  2167   2168   

Added test/lock3.test.

            1  +# 2001 September 15
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this script is database locks and the operation of the
           13  +# DEFERRED, IMMEDIATE, and EXCLUSIVE keywords as modifiers to the
           14  +# BEGIN command.
           15  +#
           16  +# $Id: lock3.test,v 1.1 2004/10/05 02:41:43 drh Exp $
           17  +
           18  +
           19  +set testdir [file dirname $argv0]
           20  +source $testdir/tester.tcl
           21  +
           22  +# Establish two connections to the same database.  Put some
           23  +# sample data into the database.
           24  +#
           25  +do_test lock3-1.1 {
           26  +  sqlite3 db2 test.db
           27  +  execsql {
           28  +    CREATE TABLE t1(a);
           29  +    INSERT INTO t1 VALUES(1);
           30  +  }
           31  +  execsql {
           32  +    SELECT * FROM t1
           33  +  } db2
           34  +} 1
           35  +
           36  +# Get a deferred lock on the database using one connection.  The
           37  +# other connection should still be able to write.
           38  +#
           39  +do_test lock3-2.1 {
           40  +  execsql {BEGIN DEFERRED TRANSACTION}
           41  +  execsql {INSERT INTO t1 VALUES(2)} db2
           42  +  execsql {END TRANSACTION}
           43  +  execsql {SELECT * FROM t1}
           44  +} {1 2}
           45  +
           46  +# Get an immediate lock on the database using one connection.  The
           47  +# other connection should be able to read the database but not write
           48  +# it.
           49  +#
           50  +do_test lock3-3.1 {
           51  +  execsql {BEGIN IMMEDIATE TRANSACTION}
           52  +  catchsql {SELECT * FROM t1} db2
           53  +} {0 {1 2}}
           54  +do_test lock3-3.2 {
           55  +  catchsql {INSERT INTO t1 VALUES(3)} db2
           56  +} {1 {database is locked}}
           57  +do_test lock3-3.3 {
           58  +  execsql {END TRANSACTION}
           59  +} {}
           60  +
           61  +
           62  +# Get an exclusive lock on the database using one connection.  The
           63  +# other connection should be unable to read or write the database.
           64  +#
           65  +do_test lock3-4.1 {
           66  +  execsql {BEGIN EXCLUSIVE TRANSACTION}
           67  +  catchsql {SELECT * FROM t1} db2
           68  +} {1 {database is locked}}
           69  +do_test lock3-4.2 {
           70  +  catchsql {INSERT INTO t1 VALUES(3)} db2
           71  +} {1 {database is locked}}
           72  +do_test lock3-4.3 {
           73  +  execsql {END TRANSACTION}
           74  +} {}
           75  +
           76  +catch {db2 close}
           77  +
           78  +finish_test

Changes to test/pager2.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 script is page cache subsystem.
    13     13   #
    14         -# $Id: pager2.test,v 1.3 2004/09/08 20:13:06 drh Exp $
           14  +# $Id: pager2.test,v 1.4 2004/10/05 02:41:43 drh Exp $
    15     15   
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   if {[info commands pager_open]!=""} {
    21     21   db close
................................................................................
   118    118     set v [catch {
   119    119       page_write $::g1 "Page-One"
   120    120     } msg]
   121    121     lappend v $msg
   122    122   } {0 {}}
   123    123   do_test pager2-2.15 {
   124    124     pager_stats $::p1
   125         -} {ref 1 page 1 max 10 size 1 state 3 err 0 hit 1 miss 1 ovfl 0}
          125  +} {ref 1 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
   126    126   do_test pager2-2.16 {
   127    127     page_read $::g1
   128    128   } {Page-One}
   129    129   do_test pager2-2.17 {
   130    130     set v [catch {
   131    131       pager_commit $::p1
   132    132     } msg]
................................................................................
   291    291         }
   292    292       }
   293    293       set res
   294    294     } {}
   295    295     do_test pager2-4.5.$i.1 {
   296    296       page_write $g1 "Page-1 v$i"
   297    297       lrange [pager_stats $p1] 8 9
   298         -  } {state 3}
          298  +  } {state 4}
   299    299     do_test pager2-4.5.$i.2 {
   300    300       for {set j 2} {$j<=20} {incr j} {
   301    301         set gx [page_get $p1 $j]
   302    302         page_write $gx "Page-$j v$i"
   303    303         page_unref $gx
   304    304         if {$j==$i} {
   305    305           pager_stmt_begin $p1
................................................................................
   332    332         }
   333    333       }
   334    334       set res
   335    335     } {}
   336    336     do_test pager2-4.5.$i.5 {
   337    337       page_write $g1 "Page-1 v$i"
   338    338       lrange [pager_stats $p1] 8 9
   339         -  } {state 3}
          339  +  } {state 4}
   340    340     do_test pager2-4.5.$i.6 {
   341    341       for {set j 2} {$j<=20} {incr j} {
   342    342         set gx [page_get $p1 $j]
   343    343         page_write $gx "Page-$j v$i"
   344    344         page_unref $gx
   345    345         if {$j==$i} {
   346    346           pager_stmt_begin $p1

Changes to www/lang.tcl.

     1      1   #
     2      2   # Run this Tcl script to generate the sqlite.html file.
     3      3   #
     4         -set rcsid {$Id: lang.tcl,v 1.72 2004/09/08 13:06:21 drh Exp $}
            4  +set rcsid {$Id: lang.tcl,v 1.73 2004/10/05 02:41:43 drh Exp $}
     5      5   source common.tcl
     6      6   header {Query Language Understood by SQLite}
     7      7   puts {
     8      8   <h2>SQL As Understood By SQLite</h2>
     9      9   
    10     10   <p>The SQLite library understands most of the standard SQL
    11     11   language.  But it does <a href="omitted.html">omit some features</a>
................................................................................
   165    165   <p>There is a compile-time limit of 10 attached database files.</p>
   166    166   }
   167    167   
   168    168   
   169    169   Section {BEGIN TRANSACTION} transaction
   170    170   
   171    171   Syntax {sql-statement} {
   172         -BEGIN [TRANSACTION [<name>]]
          172  +BEGIN [ DEFERRED | IMMEDIATE | EXCLUSIVE ] [TRANSACTION [<name>]]
   173    173   }
   174    174   Syntax {sql-statement} {
   175    175   END [TRANSACTION [<name>]]
   176    176   }
   177    177   Syntax {sql-statement} {
   178    178   COMMIT [TRANSACTION [<name>]]
   179    179   }
................................................................................
   203    203   ROLLBACK if the database is closed or if an error occurs
   204    204   and the ROLLBACK conflict resolution algorithm is specified.
   205    205   See the documention on the <a href="#conflict">ON CONFLICT</a>
   206    206   clause for additional information about the ROLLBACK
   207    207   conflict resolution algorithm.
   208    208   </p>
   209    209   
          210  +<p>
          211  +In SQLite version 3.0.8 and later, transactions can be deferred,
          212  +immediate, or exclusive.  Deferred means that no locks are acquired
          213  +on the database until the database is first accessed.  Thus with a
          214  +deferred transaction, the BEGIN statement itself does nothing.  Locks
          215  +are not acquired until the first read or write operation.  The first read
          216  +operation against a database creates a SHARED lock and the first
          217  +write operation creates a RESERVED lock.   Because the acquisition of
          218  +locks is deferred until they are needed, it is possible that another
          219  +thread or process could create a separate transaction and write to
          220  +the database after the BEGIN on the current thread has executed.
          221  +If the transation is immediate, then RESERVED locks
          222  +are acquired on all databases as soon as the BEGIN command is
          223  +executed, without waiting for the
          224  +database to be used.  After a BEGIN IMMEDIATE, you are guaranteed that
          225  +no other thread or process will be able to write to the database or
          226  +do a BEGIN IMMEDIATE or BEGIN EXCLUSIVE.  Other processes can continue
          227  +to read from the database, however.  An exclusive transaction causes
          228  +EXCLUSIVE locks to be acquired on all databases.  After a BEGIN
          229  +EXCLUSIVE, you are guaranteed that no other thread or process will
          230  +be able to read or write the database until the transaction is
          231  +complete.
          232  +</p>
          233  +
          234  +<p>
          235  +A description of the meaning of SHARED, RESERVED, and EXCLUSIVE locks
          236  +is available <a href="lockingv3.html">separately</a>.
          237  +</p>
          238  +
          239  +<p>
          240  +The default behavior for SQLite version 3.0.8 is a
          241  +deferred transaction.  For SQLite version 3.0.0 through 3.0.7,
          242  +deferred is the only kind of transaction available.  For SQLite
          243  +version 2.8 and earlier, all transactions are exclusive.
          244  +</p>
          245  +
   210    246   <p>
   211    247   The COMMIT command does not actually perform a commit until all
   212    248   pending SQL commands finish.  Thus if two or more SELECT statements
   213    249   are in the middle of processing and a COMMIT is executed, the commit
   214    250   will not actually occur until all SELECT statements finish.
   215    251   </p>
   216    252