/ Check-in [b1034681]
Login

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

Overview
Comment:Beginning to clean up the trigger code. Still lots of work to do. (CVS 566)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b10346818b25940c6dc85e94de8e36d20954161c
User & Date: drh 2002-05-15 12:45:43
Context
2002-05-15
14:17
Fix for ticket #41: Better handling of CREATE TRIGGER in the sqlite_complete() function. (CVS 567) check-in: f45c4b76 user: drh tags: trunk
12:45
Beginning to clean up the trigger code. Still lots of work to do. (CVS 566) check-in: b1034681 user: drh tags: trunk
11:44
Remove all tabs from the beginning of source code lines. Replace tabs with the appropriate number of spaces. (CVS 565) check-in: 690f9a16 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.template.

   114    114   #
   115    115   TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
   116    116   
   117    117   # Object files for the SQLite library.
   118    118   #
   119    119   LIBOBJ = btree.o build.o delete.o expr.o func.o hash.o insert.o \
   120    120            main.o os.o pager.o parse.o printf.o random.o select.o table.o \
   121         -         tokenize.o update.o util.o vdbe.o where.o tclsqlite.o
          121  +         tokenize.o trigger.o update.o util.o vdbe.o where.o tclsqlite.o
   122    122   
   123    123   # All of the source code files.
   124    124   #
   125    125   SRC = \
   126    126     $(TOP)/src/btree.c \
   127    127     $(TOP)/src/btree.h \
   128    128     $(TOP)/src/build.c \
................................................................................
   142    142     $(TOP)/src/select.c \
   143    143     $(TOP)/src/shell.c \
   144    144     $(TOP)/src/sqlite.h.in \
   145    145     $(TOP)/src/sqliteInt.h \
   146    146     $(TOP)/src/table.c \
   147    147     $(TOP)/src/tclsqlite.c \
   148    148     $(TOP)/src/tokenize.c \
          149  +  $(TOP)/src/trigger.c \
   149    150     $(TOP)/src/update.c \
   150    151     $(TOP)/src/util.c \
   151    152     $(TOP)/src/vdbe.c \
   152    153     $(TOP)/src/vdbe.h \
   153    154     $(TOP)/src/where.c
   154    155   
   155    156   # Source code to the test files.
................................................................................
   240    241   sqlite.h:	$(TOP)/src/sqlite.h.in 
   241    242   	sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \
   242    243               -e s/--ENCODING--/$(ENCODING)/ \
   243    244                    $(TOP)/src/sqlite.h.in >sqlite.h
   244    245   
   245    246   tokenize.o:	$(TOP)/src/tokenize.c $(HDR)
   246    247   	$(TCCX) -c $(TOP)/src/tokenize.c
          248  +
          249  +trigger.o:	$(TOP)/src/trigger.c $(HDR)
          250  +	$(TCCX) -c $(TOP)/src/trigger.c
   247    251   
   248    252   util.o:	$(TOP)/src/util.c $(HDR)
   249    253   	$(TCCX) -c $(TOP)/src/util.c
   250    254   
   251    255   vdbe.o:	$(TOP)/src/vdbe.c $(HDR)
   252    256   	$(TCCX) -c $(TOP)/src/vdbe.c
   253    257   

Changes to src/build.c.

    21     21   **     COPY
    22     22   **     VACUUM
    23     23   **     BEGIN TRANSACTION
    24     24   **     COMMIT
    25     25   **     ROLLBACK
    26     26   **     PRAGMA
    27     27   **
    28         -** $Id: build.c,v 1.89 2002/05/15 11:44:14 drh Exp $
           28  +** $Id: build.c,v 1.90 2002/05/15 12:45:43 drh Exp $
    29     29   */
    30     30   #include "sqliteInt.h"
    31     31   #include <ctype.h>
    32     32   
    33     33   /*
    34     34   ** This routine is called after a single SQL statement has been
    35     35   ** parsed and we want to execute the VDBE code to implement 
................................................................................
   352    352     /* Any triggers that were dropped - put 'em back in place */
   353    353     for(pElem = sqliteHashFirst(&db->trigDrop); pElem; 
   354    354         pElem = sqliteHashNext(pElem)) {
   355    355       Trigger * pTrigger = sqliteHashData(pElem);
   356    356       Table * tab = sqliteFindTable(db, pTrigger->table);
   357    357       sqliteHashInsert(&db->trigHash, pTrigger->name, 
   358    358           strlen(pTrigger->name) + 1, pTrigger);
   359         -
   360    359       pTrigger->pNext = tab->pTrigger;
   361    360       tab->pTrigger = pTrigger;
   362    361     }
   363    362   
   364    363     sqliteHashClear(&db->trigDrop);
   365    364     db->flags &= ~SQLITE_InternChanges;
   366    365   }
................................................................................
   649    648   **
   650    649   ** This plan is not completely bullet-proof.  It is possible for
   651    650   ** the schema to change multiple times and for the cookie to be
   652    651   ** set back to prior value.  But schema changes are infrequent
   653    652   ** and the probability of hitting the same cookie value is only
   654    653   ** 1 chance in 2^32.  So we're safe enough.
   655    654   */
   656         -void changeCookie(sqlite *db){
          655  +void sqliteChangeCookie(sqlite *db){
   657    656     if( db->next_cookie==db->schema_cookie ){
   658    657       db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
   659    658       db->flags |= SQLITE_InternChanges;
   660    659     }
   661    660   }
   662    661   
   663    662   /*
................................................................................
   848    847         }else{
   849    848           assert( pEnd!=0 );
   850    849           n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
   851    850           sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
   852    851         }
   853    852         sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
   854    853         sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
   855         -      changeCookie(db);
          854  +      sqliteChangeCookie(db);
   856    855         sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
   857    856         sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
   858    857         sqliteVdbeAddOp(v, OP_Close, 0, 0);
   859    858       }
   860    859       if( pSelect ){
   861    860         int op = p->isTemp ? OP_OpenWrAux : OP_OpenWrite;
   862    861         sqliteVdbeAddOp(v, op, 1, 0);
................................................................................
  1091   1090         { OP_Integer,    0, 0,        0}, /* 9 */
  1092   1091         { OP_SetCookie,  0, 0,        0},
  1093   1092         { OP_Close,      0, 0,        0},
  1094   1093       };
  1095   1094       Index *pIdx;
  1096   1095       sqliteBeginWriteOperation(pParse);
  1097   1096       /* Drop all triggers associated with the table being dropped */
  1098         -    while (pTable->pTrigger) {
         1097  +    while( pTable->pTrigger ){
  1099   1098         Token tt;
  1100   1099         tt.z = pTable->pTrigger->name;
  1101   1100         tt.n = strlen(pTable->pTrigger->name);
  1102   1101         sqliteDropTrigger(pParse, &tt, 1);
  1103   1102       }
  1104   1103       if( !pTable->isTemp ){
  1105   1104         base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
  1106   1105         sqliteVdbeChangeP3(v, base+2, pTable->zName, 0);
  1107         -      changeCookie(db);
         1106  +      sqliteChangeCookie(db);
  1108   1107         sqliteVdbeChangeP1(v, base+9, db->next_cookie);
  1109   1108       }
  1110   1109       if( !isView ){
  1111   1110         sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp);
  1112   1111         for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
  1113   1112           sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
  1114   1113         }
................................................................................
  1405   1404         sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
  1406   1405         sqliteVdbeResolveLabel(v, lbl2);
  1407   1406         sqliteVdbeAddOp(v, OP_Close, 2, 0);
  1408   1407         sqliteVdbeAddOp(v, OP_Close, 1, 0);
  1409   1408       }
  1410   1409       if( pTable!=0 ){
  1411   1410         if( !isTemp ){
  1412         -        changeCookie(db);
         1411  +        sqliteChangeCookie(db);
  1413   1412           sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
  1414   1413           sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
  1415   1414           sqliteVdbeAddOp(v, OP_Close, 0, 0);
  1416   1415         }
  1417   1416         sqliteEndWriteOperation(pParse);
  1418   1417       }
  1419   1418     }
................................................................................
  1468   1467       int base;
  1469   1468       Table *pTab = pIndex->pTable;
  1470   1469   
  1471   1470       sqliteBeginWriteOperation(pParse);
  1472   1471       if( !pTab->isTemp ){
  1473   1472         base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
  1474   1473         sqliteVdbeChangeP3(v, base+2, pIndex->zName, P3_STATIC);
  1475         -      changeCookie(db);
         1474  +      sqliteChangeCookie(db);
  1476   1475         sqliteVdbeChangeP1(v, base+10, db->next_cookie);
  1477   1476       }
  1478   1477       sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
  1479   1478       sqliteEndWriteOperation(pParse);
  1480   1479     }
  1481   1480   
  1482   1481     /* Move the index onto the pending DROP queue.  Or, if the index was
................................................................................
  1707   1706     db->onError = OE_Default;
  1708   1707   }
  1709   1708   
  1710   1709   /*
  1711   1710   ** Generate VDBE code that prepares for doing an operation that
  1712   1711   ** might change the database.  The operation will be atomic in the
  1713   1712   ** sense that it will either do its changes completely or not at
  1714         -** all.  So there is not need to set a checkpoint is a transaction
         1713  +** all.  So there is no need to set a checkpoint is a transaction
  1715   1714   ** is already in effect.
  1716   1715   */
  1717   1716   void sqliteBeginWriteOperation(Parse *pParse){
  1718   1717     Vdbe *v;
  1719   1718     v = sqliteGetVdbe(pParse);
  1720   1719     if( v==0 ) return;
  1721         -  if (pParse->trigStack) return; /* if this is in a trigger */
         1720  +  if( pParse->trigStack ) return; /* if this is in a trigger */
  1722   1721     if( (pParse->db->flags & SQLITE_InTrans)==0  ){
  1723   1722       sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
  1724   1723       sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
  1725   1724       pParse->schemaVerified = 1;
  1726   1725     }
  1727   1726   }
  1728   1727   
................................................................................
  1734   1733   ** of a transaction, then this sets a checkpoint.  If we are not in
  1735   1734   ** a transaction, then start a transaction.
  1736   1735   */
  1737   1736   void sqliteBeginMultiWriteOperation(Parse *pParse){
  1738   1737     Vdbe *v;
  1739   1738     v = sqliteGetVdbe(pParse);
  1740   1739     if( v==0 ) return;
  1741         -  if (pParse->trigStack) return; /* if this is in a trigger */
         1740  +  if( pParse->trigStack ) return; /* if this is in a trigger */
  1742   1741     if( (pParse->db->flags & SQLITE_InTrans)==0 ){
  1743   1742       sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
  1744   1743       sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
  1745   1744       pParse->schemaVerified = 1;
  1746   1745     }else{
  1747   1746       sqliteVdbeAddOp(v, OP_Checkpoint, 0, 0);
  1748   1747     }

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.108 2002/05/15 08:30:14 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.109 2002/05/15 12:45:43 drh Exp $
    15     15   */
    16     16   #include "sqlite.h"
    17     17   #include "hash.h"
    18     18   #include "vdbe.h"
    19     19   #include "parse.h"
    20     20   #include "btree.h"
    21     21   #include <stdio.h>
................................................................................
   554    554     int nSet;            /* Number of sets used so far */
   555    555     int nAgg;            /* Number of aggregate expressions */
   556    556     AggExpr *aAgg;       /* An array of aggregate expressions */
   557    557     int useAgg;          /* If true, extract field values from the aggregator
   558    558                          ** while generating expressions.  Normally false */
   559    559     int schemaVerified;  /* True if an OP_VerifySchema has been coded someplace
   560    560                          ** other than after an OP_Transaction */
   561         -
   562         -  TriggerStack * trigStack;
          561  +  TriggerStack *trigStack;
   563    562   };
   564    563   
   565    564   struct TriggerStack {
   566         -  Trigger * pTrigger;
   567         -  Table *   pTab;         /* Table that triggers are currently being coded as */
   568         -  int       newIdx;       /* Index of "new" temp table */
   569         -  int       oldIdx;       /* Index of "old" temp table */
   570         -  int       orconf;       /* Current orconf policy */
   571         -  struct TriggerStack * pNext;
          565  +  Trigger *pTrigger;
          566  +  Table *pTab;         /* Table that triggers are currently being coded as */
          567  +  int newIdx;          /* Index of "new" temp table */
          568  +  int oldIdx;          /* Index of "old" temp table */
          569  +  int orconf;          /* Current orconf policy */
          570  +  TriggerStack *pNext;
   572    571   };
   573    572   struct TriggerStep {
   574    573     int op;               /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
   575    574     int orconf;
   576    575   
   577         -  Select * pSelect;     /* Valid for SELECT and sometimes 
          576  +  Select *pSelect;     /* Valid for SELECT and sometimes 
   578    577   			   INSERT steps (when pExprList == 0) */
   579    578     Token target;         /* Valid for DELETE, UPDATE, INSERT steps */
   580         -  Expr * pWhere;        /* Valid for DELETE, UPDATE steps */
   581         -  ExprList * pExprList; /* Valid for UPDATE statements and sometimes 
          579  +  Expr *pWhere;        /* Valid for DELETE, UPDATE steps */
          580  +  ExprList *pExprList; /* Valid for UPDATE statements and sometimes 
   582    581   			   INSERT steps (when pSelect == 0)         */
   583    582     IdList *pIdList;      /* Valid for INSERT statements only */
   584    583   
   585    584     TriggerStep * pNext;  /* Next in the link-list */
   586    585   };
   587    586   struct Trigger {
   588         -  char * name;             /* The name of the trigger                        */
   589         -  char * table;            /* The table or view to which the trigger applies */
   590         -  int    op;               /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
   591         -  int    tr_tm;            /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD         */
   592         -  Expr * pWhen;            /* The WHEN clause of the expresion (may be NULL) */
   593         -  IdList * pColumns;       /* If this is an UPDATE OF <column-list> trigger,
   594         -			      the column names are stored in this list       */
   595         -  int foreach;             /* One of TK_ROW or TK_STATEMENT */
          587  +  char *name;             /* The name of the trigger                        */
          588  +  char *table;            /* The table or view to which the trigger applies */
          589  +  int op;                 /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
          590  +  int tr_tm;              /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD         */
          591  +  Expr *pWhen;            /* The WHEN clause of the expresion (may be NULL) */
          592  +  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
          593  +                             the column names are stored in this list       */
          594  +  int foreach;            /* One of TK_ROW or TK_STATEMENT */
   596    595   
   597         -  TriggerStep * step_list; /* Link list of trigger program steps             */
   598         -
   599         -  char * strings;  /* pointer to the allocation of Token strings */
   600         -  Trigger * pNext; /* Next trigger associated with the table */
          596  +  TriggerStep *step_list; /* Link list of trigger program steps             */
          597  +  char *strings;          /* pointer to allocation of Token strings */
          598  +  Trigger *pNext;         /* Next trigger associated with the table */
   601    599     int isCommit;
   602    600   };
   603    601   
   604         -TriggerStep * sqliteTriggerSelectStep(Select *);
   605         -TriggerStep * sqliteTriggerInsertStep(Token *, IdList *, ExprList *, 
   606         -    Select *, int);
   607         -TriggerStep * sqliteTriggerUpdateStep(Token *, ExprList *, Expr *, int);
   608         -TriggerStep * sqliteTriggerDeleteStep(Token *, Expr *);
   609         -
   610    602   extern int always_code_trigger_setup;
   611    603   
   612         -void sqliteCreateTrigger(Parse * ,Token *, int, int, IdList *, Token *, int, Expr *, TriggerStep *, char const *,int);
   613         -void sqliteDropTrigger(Parse *, Token *, int);
   614         -int sqliteTriggersExist( Parse * , Trigger * , int , int , int, ExprList * );
   615         -int sqliteCodeRowTrigger( Parse * pParse, int op, ExprList *, int tr_tm,   Table * tbl, int newTable, int oldTable, int onError);
   616         -
   617         -void sqliteViewTriggers(Parse *, Table *, Expr *, int, ExprList *);
   618    604   
   619    605   /*
   620    606   ** Internal function prototypes
   621    607   */
   622    608   int sqliteStrICmp(const char *, const char *);
   623    609   int sqliteStrNICmp(const char *, const char *, int);
   624    610   int sqliteHashNoCase(const char *, int);
................................................................................
   722    708   IdList *sqliteIdListDup(IdList*);
   723    709   Select *sqliteSelectDup(Select*);
   724    710   FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
   725    711   void sqliteRegisterBuildinFunctions(sqlite*);
   726    712   int sqliteSafetyOn(sqlite*);
   727    713   int sqliteSafetyOff(sqlite*);
   728    714   int sqliteSafetyCheck(sqlite*);
   729         -
   730         -void changeCookie(sqlite *);
          715  +void sqliteChangeCookie(sqlite *);
          716  +void sqliteCreateTrigger(Parse*, Token*, int, int, IdList*, Token*, 
          717  +                         int, Expr*, TriggerStep*, char const*,int);
          718  +void sqliteDropTrigger(Parse*, Token*, int);
          719  +int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
          720  +int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, int);
          721  +void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
          722  +TriggerStep *sqliteTriggerSelectStep(Select*);
          723  +TriggerStep *sqliteTriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
          724  +TriggerStep *sqliteTriggerUpdateStep(Token*, ExprList*, Expr*, int);
          725  +TriggerStep *sqliteTriggerDeleteStep(Token*, Expr*);

Changes to src/trigger.c.

    98     98       sqliteVdbeAddOp(pParse->pVdbe,        OP_Integer,    0, 0);
    99     99       sqliteVdbeAddOp(pParse->pVdbe,        OP_String,    0, 0);
   100    100       sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->strings,     0);
   101    101       sqliteVdbeAddOp(pParse->pVdbe,        OP_MakeRecord, 5, 0);
   102    102       sqliteVdbeAddOp(pParse->pVdbe,        OP_PutIntKey, 0, 1);
   103    103   
   104    104       /* Change the cookie, since the schema is changed */
   105         -    changeCookie(pParse->db);
          105  +    sqliteChangeCookie(pParse->db);
   106    106       sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, pParse->db->next_cookie, 0);
   107    107       sqliteVdbeAddOp(pParse->pVdbe, OP_SetCookie, 0, 0);
   108    108   
   109    109       sqliteVdbeAddOp(pParse->pVdbe,        OP_Close,     0, 0);
   110    110   
   111    111       sqliteEndWriteOperation(pParse);
   112    112     }
................................................................................
   296    296         { OP_Delete,     0, 0,        0},
   297    297         { OP_Next,       0, ADDR(4),  0}, /* 8 */
   298    298         { OP_Integer,    0, 0,        0}, /* 9 */
   299    299         { OP_SetCookie,  0, 0,        0},
   300    300         { OP_Close,      0, 0,        0},
   301    301       };
   302    302   
   303         -    if (!nested) 
          303  +    if( !nested ){
   304    304         sqliteBeginWriteOperation(pParse);
   305         -
          305  +    }
   306    306       base = sqliteVdbeAddOpList(pParse->pVdbe, 
   307    307           ArraySize(dropTrigger), dropTrigger);
   308    308       sqliteVdbeChangeP3(pParse->pVdbe, base+2, tmp_name, 0);
   309         -
   310         -    if (!nested)
   311         -      changeCookie(pParse->db);
   312         -
          309  +    if( !nested ){
          310  +      sqliteChangeCookie(pParse->db);
          311  +    }
   313    312       sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
   314         -
   315         -    if (!nested)
          313  +    if( !nested ){
   316    314         sqliteEndWriteOperation(pParse);
          315  +    }
   317    316     }
   318    317   
   319    318     sqliteFree(tmp_name);
   320    319   }
   321    320   
   322    321   static int checkColumnOverLap(IdList * ii, ExprList * ee)
   323    322   {