/ Check-in [ebdb661e]
Login

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

Overview
Comment:Prepared statements now work with CREATE and DROP. All tests pass. No memory leaks. (CVS 1866)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ebdb661e0eefe123c422d3c1c371e325bb6cf673
User & Date: drh 2004-07-24 17:38:29
Context
2004-07-26
00:31
Various size optimizations. (CVS 1867) check-in: 1186e3ce user: drh tags: trunk
2004-07-24
17:38
Prepared statements now work with CREATE and DROP. All tests pass. No memory leaks. (CVS 1866) check-in: ebdb661e user: drh tags: trunk
14:35
Fix more problems with deferred execution of CREATE. Still need to do DROP. There is now a memory leak. (CVS 1865) check-in: 6db3f122 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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.242 2004/07/24 14:35:58 drh Exp $
           26  +** $Id: build.c,v 1.243 2004/07/24 17:38:29 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
................................................................................
   186    186       int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
   187    187       if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
   188    188       p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
   189    189       if( p ) break;
   190    190     }
   191    191     return p;
   192    192   }
          193  +
          194  +/*
          195  +** Reclaim the memory used by an index
          196  +*/
          197  +static void freeIndex(Index *p){
          198  +  sqliteFree(p->zColAff);
          199  +  sqliteFree(p);
          200  +}
   193    201   
   194    202   /*
   195    203   ** Remove the given index from the index hash table, and free
   196    204   ** its memory structures.
   197    205   **
   198    206   ** The index is removed from the database hash tables but
   199    207   ** it is not unlinked from the Table that it indexes.
................................................................................
   205    213     assert( db!=0 && p->zName!=0 );
   206    214     pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName,
   207    215                             strlen(p->zName)+1, 0);
   208    216     if( pOld!=0 && pOld!=p ){
   209    217       sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
   210    218                        strlen(pOld->zName)+1, pOld);
   211    219     }
   212         -  if( p->zColAff ){
   213         -    sqliteFree(p->zColAff);
   214         -  }
   215         -  sqliteFree(p);
          220  +  freeIndex(p);
   216    221   }
   217    222   
   218    223   /*
   219    224   ** Unlink the given index from its table, then remove
   220    225   ** the index from the index hash table and free its memory
   221    226   ** structures.
   222    227   */
   223         -void sqlite3UnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
   224         -  if( pIndex->pTable->pIndex==pIndex ){
   225         -    pIndex->pTable->pIndex = pIndex->pNext;
   226         -  }else{
   227         -    Index *p;
   228         -    for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
   229         -    if( p && p->pNext==pIndex ){
   230         -      p->pNext = pIndex->pNext;
          228  +void sqlite3UnlinkAndDeleteIndex(sqlite *db, int iDb, const char *zIdxName){
          229  +  Index *pIndex;
          230  +  int len;
          231  +
          232  +  len = strlen(zIdxName);
          233  +  pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, zIdxName, len+1, 0);
          234  +  if( pIndex ){
          235  +    if( pIndex->pTable->pIndex==pIndex ){
          236  +      pIndex->pTable->pIndex = pIndex->pNext;
          237  +    }else{
          238  +      Index *p;
          239  +      for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
          240  +      if( p && p->pNext==pIndex ){
          241  +        p->pNext = pIndex->pNext;
          242  +      }
   231    243       }
          244  +    freeIndex(pIndex);
   232    245     }
   233         -  sqliteDeleteIndex(db, pIndex);
          246  +  db->flags |= SQLITE_InternChanges;
   234    247   }
   235    248   
   236    249   /*
   237    250   ** Erase all schema information from the in-memory hash tables of
   238    251   ** a single database.  This routine is called to reclaim memory
   239    252   ** before the database closes.  It is also called during a rollback
   240    253   ** if there were schema changes during the transaction or if a
................................................................................
   323    336   
   324    337   /*
   325    338   ** This routine is called when a commit occurs.
   326    339   */
   327    340   void sqlite3CommitInternalChanges(sqlite *db){
   328    341     db->flags &= ~SQLITE_InternChanges;
   329    342   }
          343  +
          344  +/*
          345  +** Clear the column names from a table or view.
          346  +*/
          347  +static void sqliteResetColumnNames(Table *pTable){
          348  +  int i;
          349  +  Column *pCol;
          350  +  assert( pTable!=0 );
          351  +  for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
          352  +    sqliteFree(pCol->zName);
          353  +    sqliteFree(pCol->zDflt);
          354  +    sqliteFree(pCol->zType);
          355  +  }
          356  +  sqliteFree(pTable->aCol);
          357  +  pTable->aCol = 0;
          358  +  pTable->nCol = 0;
          359  +}
   330    360   
   331    361   /*
   332    362   ** Remove the memory data structures associated with the given
   333    363   ** Table.  No changes are made to disk by this routine.
   334    364   **
   335    365   ** This routine just deletes the data structure.  It does not unlink
   336    366   ** the table data structure from the hash table.  Nor does it remove
................................................................................
   340    370   **
   341    371   ** Indices associated with the table are unlinked from the "db"
   342    372   ** data structure if db!=NULL.  If db==NULL, indices attached to
   343    373   ** the table are deleted, but it is assumed they have already been
   344    374   ** unlinked.
   345    375   */
   346    376   void sqlite3DeleteTable(sqlite *db, Table *pTable){
   347         -  int i;
   348    377     Index *pIndex, *pNext;
   349    378     FKey *pFKey, *pNextFKey;
   350    379   
   351    380     if( pTable==0 ) return;
   352    381   
   353    382     /* Delete all indices associated with this table
   354    383     */
................................................................................
   367    396       assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey,
   368    397                              pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
   369    398       sqliteFree(pFKey);
   370    399     }
   371    400   
   372    401     /* Delete the Table structure itself.
   373    402     */
   374         -  for(i=0; i<pTable->nCol; i++){
   375         -    Column *pCol = &pTable->aCol[i];
   376         -    sqliteFree(pCol->zName);
   377         -    sqliteFree(pCol->zDflt);
   378         -    sqliteFree(pCol->zType);
   379         -  }
          403  +  sqliteResetColumnNames(pTable);
   380    404     sqliteFree(pTable->zName);
   381         -  sqliteFree(pTable->aCol);
   382         -  if( pTable->zColAff ){
   383         -    sqliteFree(pTable->zColAff);
   384         -  }
          405  +  sqliteFree(pTable->zColAff);
   385    406     sqlite3SelectDelete(pTable->pSelect);
   386    407     sqliteFree(pTable);
   387    408   }
   388    409   
   389    410   /*
   390    411   ** Unlink the given table from the hash tables and the delete the
   391    412   ** table structure with all its indices and foreign keys.
   392    413   */
   393         -static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
   394         -  Table *pOld;
          414  +void sqlite3UnlinkAndDeleteTable(sqlite *db, int iDb, const char *zTabName){
          415  +  Table *p;
   395    416     FKey *pF1, *pF2;
   396         -  int i = p->iDb;
          417  +  Db *pDb;
          418  +
   397    419     assert( db!=0 );
   398         -  pOld = sqlite3HashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1,0);
   399         -  assert( pOld==0 || pOld==p );
   400         -  for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
   401         -    int nTo = strlen(pF1->zTo) + 1;
   402         -    pF2 = sqlite3HashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
   403         -    if( pF2==pF1 ){
   404         -      sqlite3HashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
   405         -    }else{
   406         -      while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
   407         -      if( pF2 ){
   408         -        pF2->pNextTo = pF1->pNextTo;
          420  +  assert( iDb>=0 && iDb<db->nDb );
          421  +  assert( zTabName && zTabName[0] );
          422  +  pDb = &db->aDb[iDb];
          423  +  p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0);
          424  +  if( p ){
          425  +    for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
          426  +      int nTo = strlen(pF1->zTo) + 1;
          427  +      pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo);
          428  +      if( pF2==pF1 ){
          429  +        sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo);
          430  +      }else{
          431  +        while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
          432  +        if( pF2 ){
          433  +          pF2->pNextTo = pF1->pNextTo;
          434  +        }
   409    435         }
   410    436       }
          437  +    sqlite3DeleteTable(db, p);
   411    438     }
   412         -  sqlite3DeleteTable(db, p);
          439  +  db->flags |= SQLITE_InternChanges;
   413    440   }
   414    441   
   415    442   /*
   416    443   ** Given a token, return a string that consists of the text of that
   417    444   ** token with any quotations removed.  Space to hold the returned string
   418    445   ** is obtained from sqliteMalloc() and must be freed by the calling
   419    446   ** function.
................................................................................
  1526   1553     }
  1527   1554     sqlite3SelectUnbind(pSel);
  1528   1555     sqlite3ExprListDelete(pSel->pEList);
  1529   1556     pSel->pEList = pEList;
  1530   1557     return nErr;  
  1531   1558   }
  1532   1559   
  1533         -/*
  1534         -** Clear the column names from the VIEW pTable.
  1535         -**
  1536         -** This routine is called whenever any other table or view is modified.
  1537         -** The view passed into this routine might depend directly or indirectly
  1538         -** on the modified or deleted table so we need to clear the old column
  1539         -** names so that they will be recomputed.
  1540         -*/
  1541         -static void sqliteViewResetColumnNames(Table *pTable){
  1542         -  int i;
  1543         -  Column *pCol;
  1544         -  assert( pTable!=0 && pTable->pSelect!=0 );
  1545         -  for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
  1546         -    sqliteFree(pCol->zName);
  1547         -    sqliteFree(pCol->zDflt);
  1548         -    sqliteFree(pCol->zType);
  1549         -  }
  1550         -  sqliteFree(pTable->aCol);
  1551         -  pTable->aCol = 0;
  1552         -  pTable->nCol = 0;
  1553         -}
  1554         -
  1555   1560   /*
  1556   1561   ** Clear the column names from every VIEW in database idx.
  1557   1562   */
  1558   1563   static void sqliteViewResetAll(sqlite *db, int idx){
  1559   1564     HashElem *i;
  1560   1565     if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  1561   1566     for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
  1562   1567       Table *pTab = sqliteHashData(i);
  1563   1568       if( pTab->pSelect ){
  1564         -      sqliteViewResetColumnNames(pTab);
         1569  +      sqliteResetColumnNames(pTab);
  1565   1570       }
  1566   1571     }
  1567   1572     DbClearProperty(db, idx, DB_UnresetViews);
  1568   1573   }
  1569   1574   
  1570   1575   /*
  1571   1576   ** This routine is called to do the work of a DROP TABLE statement.
................................................................................
  1656   1661       ** is generated to remove entries from sqlite_master and/or
  1657   1662       ** sqlite_temp_master if required.
  1658   1663       */
  1659   1664       pTrigger = pTab->pTrigger;
  1660   1665       while( pTrigger ){
  1661   1666         assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 );
  1662   1667         sqlite3DropTriggerPtr(pParse, pTrigger, 1);
  1663         -      if( pParse->explain ){
  1664         -        pTrigger = pTrigger->pNext;
  1665         -      }else{
  1666         -        pTrigger = pTab->pTrigger;
  1667         -      }
         1668  +      pTrigger = pTrigger->pNext;
  1668   1669       }
  1669   1670   
  1670   1671       /* Drop all SQLITE_MASTER table and index entries that refer to the
  1671   1672       ** table. The program name loops through the master table and deletes
  1672   1673       ** every row that refers to a table of the same name as the one being
  1673   1674       ** dropped. Triggers are handled seperately because a trigger can be
  1674   1675       ** created in the temp database that refers to a table in another
................................................................................
  1681   1682       sqlite3VdbeAddOp(v, OP_Close, 0, 0);
  1682   1683       if( !isView ){
  1683   1684         sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb);
  1684   1685         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
  1685   1686           sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
  1686   1687         }
  1687   1688       }
         1689  +    sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
  1688   1690       sqlite3EndWriteOperation(pParse);
  1689   1691     }
  1690         -
  1691         -  /* Delete the in-memory description of the table.
  1692         -  **
  1693         -  ** Exception: if the SQL statement began with the EXPLAIN keyword,
  1694         -  ** then no changes should be made.
  1695         -  */
  1696         -  if( !pParse->explain ){
  1697         -    sqliteUnlinkAndDeleteTable(db, pTab);
  1698         -    db->flags |= SQLITE_InternChanges;
  1699         -  }
  1700   1692     sqliteViewResetAll(db, iDb);
  1701   1693   
  1702   1694   exit_drop_table:
  1703   1695     sqlite3SrcListDelete(pName);
  1704   1696   }
  1705   1697   
  1706   1698   /*
................................................................................
  2188   2180         pOther->pNext = pIndex;
  2189   2181       }
  2190   2182       pIndex = 0;
  2191   2183     }
  2192   2184   
  2193   2185     /* Clean up before exiting */
  2194   2186   exit_create_index:
  2195         -  if( pIndex ) sqliteFree(pIndex);
         2187  +  if( pIndex ){
         2188  +    freeIndex(pIndex);
         2189  +  }
  2196   2190     sqlite3ExprListDelete(pList);
  2197   2191     sqlite3SrcListDelete(pTblName);
  2198   2192     sqliteFree(zName);
  2199   2193     return;
  2200   2194   }
  2201   2195   
  2202   2196   /*
................................................................................
  2257   2251       sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb);
  2258   2252       sqlite3OpenMasterTable(v, pIndex->iDb);
  2259   2253       base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
  2260   2254       sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0);
  2261   2255       sqlite3ChangeCookie(db, v, pIndex->iDb);
  2262   2256       sqlite3VdbeAddOp(v, OP_Close, 0, 0);
  2263   2257       sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
         2258  +    sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
  2264   2259       sqlite3EndWriteOperation(pParse);
  2265   2260     }
  2266   2261   
  2267         -  /* Delete the in-memory description of this index.
  2268         -  */
  2269         -  if( !pParse->explain ){
  2270         -    sqlite3UnlinkAndDeleteIndex(db, pIndex);
  2271         -    db->flags |= SQLITE_InternChanges;
  2272         -  }
  2273         -
  2274   2262   exit_drop_index:
  2275   2263     sqlite3SrcListDelete(pName);
  2276   2264   }
  2277   2265   
  2278   2266   /*
  2279   2267   ** Append a new element to the given IdList.  Create a new IdList if
  2280   2268   ** need be.

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.113 2004/06/21 06:50:28 danielk1977 Exp $
           15  +** $Id: insert.c,v 1.114 2004/07/24 17:38:29 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:
................................................................................
    46     46       }
    47     47       for(n=0; n<pIdx->nColumn; n++){
    48     48         pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
    49     49       }
    50     50       pIdx->zColAff[pIdx->nColumn] = '\0';
    51     51     }
    52     52    
    53         -  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, P3_STATIC);
           53  +  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, 0);
    54     54   }
    55     55   
    56     56   /*
    57     57   ** Set P3 of the most recently inserted opcode to a column affinity
    58     58   ** string for table pTab. A column affinity string has one character
    59     59   ** for each column indexed by the index, according to the affinity of the
    60     60   ** column:
................................................................................
    87     87         zColAff[i] = pTab->aCol[i].affinity;
    88     88       }
    89     89       zColAff[pTab->nCol] = '\0';
    90     90   
    91     91       pTab->zColAff = zColAff;
    92     92     }
    93     93   
    94         -  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, P3_STATIC);
           94  +  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
    95     95   }
    96     96   
    97     97   
    98     98   /*
    99     99   ** This routine is call to handle SQL of the following forms:
   100    100   **
   101    101   **    insert into TABLE (IDLIST) values(EXPRLIST)

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.310 2004/07/24 14:35:58 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.311 2004/07/24 17:38:29 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   #include "config.h"
    20     20   #include "sqlite3.h"
    21     21   #include "hash.h"
................................................................................
  1268   1268   void sqlite3ExprCode(Parse*, Expr*);
  1269   1269   int sqlite3ExprCodeExprList(Parse*, ExprList*);
  1270   1270   void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
  1271   1271   void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
  1272   1272   Table *sqlite3FindTable(sqlite*,const char*, const char*);
  1273   1273   Table *sqlite3LocateTable(Parse*,const char*, const char*);
  1274   1274   Index *sqlite3FindIndex(sqlite*,const char*, const char*);
  1275         -void sqlite3UnlinkAndDeleteIndex(sqlite*,Index*);
         1275  +void sqlite3UnlinkAndDeleteTable(sqlite*,int,const char*);
         1276  +void sqlite3UnlinkAndDeleteIndex(sqlite*,int,const char*);
         1277  +void sqlite3UnlinkAndDeleteTrigger(sqlite*,int,const char*);
  1276   1278   void sqlite3Vacuum(Parse*, Token*);
  1277   1279   int sqlite3RunVacuum(char**, sqlite*);
  1278   1280   int sqlite3GlobCompare(const unsigned char*,const unsigned char*);
  1279   1281   char *sqlite3NameFromToken(Token*);
  1280   1282   int sqlite3ExprCheck(Parse*, Expr*, int, int*);
  1281   1283   int sqlite3ExprCompare(Expr*, Expr*);
  1282   1284   int sqliteFuncId(Token*);

Changes to src/trigger.c.

   137    137       int code = SQLITE_CREATE_TRIGGER;
   138    138       const char *zDb = db->aDb[pTab->iDb].zName;
   139    139       const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
   140    140       if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
   141    141       if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
   142    142         goto trigger_cleanup;
   143    143       }
   144         -    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb), 0, zDb)){
          144  +    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb),0,zDb)){
   145    145         goto trigger_cleanup;
   146    146       }
   147    147     }
   148    148   #endif
   149    149   
   150    150     /* INSTEAD OF triggers can only appear on views and BEFORE triggers
   151    151     ** cannot appear on views.  So we might as well translate every
................................................................................
   209    209   
   210    210     /* if we are not initializing, and this trigger is not on a TEMP table, 
   211    211     ** build the sqlite_master entry
   212    212     */
   213    213     if( !db->init.busy ){
   214    214       static VdbeOpList insertTrig[] = {
   215    215         { OP_NewRecno,   0, 0,  0          },
   216         -      { OP_String8,     0, 0,  "trigger"  },
   217         -      { OP_String8,     0, 0,  0          },  /* 2: trigger name */
   218         -      { OP_String8,     0, 0,  0          },  /* 3: table name */
          216  +      { OP_String8,    0, 0,  "trigger"  },
          217  +      { OP_String8,    0, 0,  0          },  /* 2: trigger name */
          218  +      { OP_String8,    0, 0,  0          },  /* 3: table name */
   219    219         { OP_Integer,    0, 0,  0          },
   220         -      { OP_String8,     0, 0,  "CREATE TRIGGER "},
   221         -      { OP_String8,     0, 0,  0          },  /* 6: SQL */
   222         -      { OP_Concat8,     2, 0,  0          }, 
          220  +      { OP_String8,    0, 0,  "CREATE TRIGGER "},
          221  +      { OP_String8,    0, 0,  0          },  /* 6: SQL */
          222  +      { OP_Concat8,    2, 0,  0          }, 
   223    223         { OP_MakeRecord, 5, 0,  "tttit"    },
   224    224         { OP_PutIntKey,  0, 0,  0          },
   225    225       };
   226    226       int addr;
   227    227       Vdbe *v;
   228    228   
   229    229       /* Make an entry in the sqlite_master table */
................................................................................
   235    235       sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); 
   236    236       sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); 
   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  +    sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0, 
          243  +       sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC);
   242    244       sqlite3EndWriteOperation(pParse);
   243    245     }
   244    246   
   245         -  if( !pParse->explain ){
          247  +  if( db->init.busy ){
   246    248       Table *pTab;
   247    249       sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, 
   248    250                        nt->name, strlen(nt->name)+1, nt);
   249    251       pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
   250    252       assert( pTab!=0 );
   251    253       nt->pNext = pTab->pTrigger;
   252    254       pTab->pTrigger = nt;
................................................................................
   439    441       goto drop_trigger_cleanup;
   440    442     }
   441    443     sqlite3DropTriggerPtr(pParse, pTrigger, 0);
   442    444   
   443    445   drop_trigger_cleanup:
   444    446     sqlite3SrcListDelete(pName);
   445    447   }
          448  +
          449  +/*
          450  +** Return a pointer to the Table structure for the table that a trigger
          451  +** is set on.
          452  +*/
          453  +static Table *tableOfTrigger(sqlite3 *db, Trigger *pTrigger){
          454  +  return sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
          455  +}
          456  +
   446    457   
   447    458   /*
   448    459   ** Drop a trigger given a pointer to that trigger.  If nested is false,
   449    460   ** then also generate code to remove the trigger from the SQLITE_MASTER
   450    461   ** table.
   451    462   */
   452    463   void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
   453    464     Table   *pTable;
   454    465     Vdbe *v;
   455    466     sqlite *db = pParse->db;
          467  +  int iDb;
   456    468   
   457         -  assert( pTrigger->iDb<db->nDb );
   458         -  pTable = sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
          469  +  iDb = pTrigger->iDb;
          470  +  assert( iDb>=0 && iDb<db->nDb );
          471  +  pTable = tableOfTrigger(db, pTrigger);
   459    472     assert(pTable);
   460         -  assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
          473  +  assert( pTable->iDb==iDb || iDb==1 );
   461    474   #ifndef SQLITE_OMIT_AUTHORIZATION
   462    475     {
   463    476       int code = SQLITE_DROP_TRIGGER;
   464         -    const char *zDb = db->aDb[pTrigger->iDb].zName;
   465         -    const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
   466         -    if( pTrigger->iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
          477  +    const char *zDb = db->aDb[iDb].zName;
          478  +    const char *zTab = SCHEMA_TABLE(iDb);
          479  +    if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
   467    480       if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
   468    481         sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
   469    482         return;
   470    483       }
   471    484     }
   472    485   #endif
   473    486   
................................................................................
   483    496         { OP_String8,     0, 0,        "trigger"},
   484    497         { OP_Column,     0, 0,        0},
   485    498         { OP_Ne,         0, ADDR(8),  0},
   486    499         { OP_Delete,     0, 0,        0},
   487    500         { OP_Next,       0, ADDR(1),  0}, /* 8 */
   488    501       };
   489    502   
   490         -    sqlite3BeginWriteOperation(pParse, 0, pTrigger->iDb);
   491         -    sqlite3OpenMasterTable(v, pTrigger->iDb);
          503  +    sqlite3BeginWriteOperation(pParse, 0, iDb);
          504  +    sqlite3OpenMasterTable(v, iDb);
   492    505       base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
   493    506       sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
   494         -    sqlite3ChangeCookie(db, v, pTrigger->iDb);
          507  +    sqlite3ChangeCookie(db, v, iDb);
   495    508       sqlite3VdbeAddOp(v, OP_Close, 0, 0);
          509  +    sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0);
   496    510     }
          511  +}
   497    512   
   498         -  /*
   499         -  ** If this is not an "explain", then delete the trigger structure.
   500         -  */
   501         -  if( !pParse->explain ){
   502         -    const char *zName = pTrigger->name;
   503         -    int nName = strlen(zName);
          513  +/*
          514  +** Remove a trigger from the hash tables of the sqlite* pointer.
          515  +*/
          516  +void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
          517  +  Trigger *pTrigger;
          518  +  int nName = strlen(zName);
          519  +  pTrigger = sqlite3HashInsert(&(db->aDb[iDb].trigHash), zName, nName+1, 0);
          520  +  if( pTrigger ){
          521  +    Table *pTable = tableOfTrigger(db, pTrigger);
          522  +    assert( pTable!=0 );
   504    523       if( pTable->pTrigger == pTrigger ){
   505    524         pTable->pTrigger = pTrigger->pNext;
   506    525       }else{
   507    526         Trigger *cc = pTable->pTrigger;
   508    527         while( cc ){ 
   509    528           if( cc->pNext == pTrigger ){
   510    529             cc->pNext = cc->pNext->pNext;
   511    530             break;
   512    531           }
   513    532           cc = cc->pNext;
   514    533         }
   515    534         assert(cc);
   516    535       }
   517         -    sqlite3HashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
   518    536       sqlite3DeleteTrigger(pTrigger);
          537  +    db->flags |= SQLITE_InternChanges;
   519    538     }
   520    539   }
   521    540   
   522    541   /*
   523    542   ** pEList is the SET clause of an UPDATE statement.  Each entry
   524    543   ** in pEList is of the format <id>=<expr>.  If any of the entries
   525    544   ** in pEList have an <id> which matches an identifier in pIdList,

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.405 2004/07/24 14:35:59 drh Exp $
           46  +** $Id: vdbe.c,v 1.406 2004/07/24 17:38:29 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   /*
................................................................................
  3759   3759     db->init.busy = 1;
  3760   3760     rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
  3761   3761     db->init.busy = 0;
  3762   3762     sqlite3SafetyOn(db);
  3763   3763     sqliteFree(zSql);
  3764   3764     break;  
  3765   3765   }
         3766  +
         3767  +/* Opcode: DropTable P1 * P3
         3768  +**
         3769  +** Remove the internal (in-memory) data structures that describe
         3770  +** the table named P3 in database P1.  This is called after a table
         3771  +** is dropped in order to keep the internal representation of the
         3772  +** schema consistent with what is on disk.
         3773  +*/
         3774  +case OP_DropTable: {
         3775  +  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3);
         3776  +  break;
         3777  +}
         3778  +
         3779  +/* Opcode: DropIndex P1 * P3
         3780  +**
         3781  +** Remove the internal (in-memory) data structures that describe
         3782  +** the index named P3 in database P1.  This is called after an index
         3783  +** is dropped in order to keep the internal representation of the
         3784  +** schema consistent with what is on disk.
         3785  +*/
         3786  +case OP_DropIndex: {
         3787  +  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3);
         3788  +  break;
         3789  +}
         3790  +
         3791  +/* Opcode: DropTrigger P1 * P3
         3792  +**
         3793  +** Remove the internal (in-memory) data structures that describe
         3794  +** the trigger named P3 in database P1.  This is called after a trigger
         3795  +** is dropped in order to keep the internal representation of the
         3796  +** schema consistent with what is on disk.
         3797  +*/
         3798  +case OP_DropTrigger: {
         3799  +  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
         3800  +  break;
         3801  +}
  3766   3802   
  3767   3803   
  3768   3804   /* Opcode: IntegrityCk * P2 *
  3769   3805   **
  3770   3806   ** Do an analysis of the currently open database.  Push onto the
  3771   3807   ** stack the text of an error message describing any problems.
  3772   3808   ** If there are no errors, push a "ok" onto the stack.

Changes to test/misc4.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for miscellanous features that were
    14     14   # left out of other test files.
    15     15   #
    16         -# $Id: misc4.test,v 1.5 2004/07/24 14:35:59 drh Exp $
           16  +# $Id: misc4.test,v 1.6 2004/07/24 17:38:30 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   # Prepare a statement that will create a temporary table.  Then do
    22     22   # a rollback.  Then try to execute the prepared statement.
    23     23   #
................................................................................
    60     60     sqlite3_finalize $stmt
    61     61   } {SQLITE_SCHEMA}
    62     62   
    63     63   # Prepare but do not execute various CREATE statements.  Then before
    64     64   # those statements are executed, try to use the tables, indices, views,
    65     65   # are triggers that were created.
    66     66   #
    67         -if 0 {
    68     67   do_test misc4-2.1 {
    69     68     set stmt [sqlite3_prepare $DB {CREATE TABLE t3(x);} -1 TAIL]
    70     69     catchsql {
    71         -pragma vdbe_trace=on;
    72     70       INSERT INTO t3 VALUES(1);
    73     71     }
    74     72   } {1 {no such table: t3}}
    75     73   do_test misc4-2.2 {
    76     74     sqlite3_step $stmt
    77     75   } SQLITE_DONE
    78     76   do_test misc4-2.3 {
................................................................................
    79     77     sqlite3_finalize $stmt
    80     78   } SQLITE_OK
    81     79   do_test misc4-2.4 {
    82     80     catchsql {
    83     81       INSERT INTO t3 VALUES(1);
    84     82     }
    85     83   } {0 {}}
    86         -}
           84  +
    87     85   
    88     86   finish_test

Changes to test/pragma.test.

     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.
    12     12   #
    13     13   # This file implements tests for the PRAGMA command.
    14     14   #
    15         -# $Id: pragma.test,v 1.16 2004/07/22 15:02:26 drh Exp $
           15  +# $Id: pragma.test,v 1.17 2004/07/24 17:38:30 drh Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Test organization:
    21     21   #
    22     22   # pragma-1.*: Test cache_size, default_cache_size and synchronous on main db.
................................................................................
   302    302     } 
   303    303   } {2}
   304    304   catchsql {COMMIT;}
   305    305   
   306    306   # Test schema-query pragmas
   307    307   #
   308    308   do_test pragma-6.1 {
          309  +  set res {}
   309    310     foreach {idx name file} [execsql {pragma database_list}] {
   310    311       lappend res $idx $name
   311    312     }
   312    313     set res
   313    314   } {0 main 1 temp 2 aux}
   314    315   do_test pragma-6.2 {
   315    316     execsql {