extensions/sqlite/sqlite-source/trigger.c
author David Anderson <dvander@alliedmods.net>
Sun Jul 29 01:15:31 2007 +0000 (2007-07-29)
changeset 1203 633c25ce6405
child 1645 27307df4d711
permissions -rw-r--r--
initial import of sqlite extension
dvander@1203
     1
/*
dvander@1203
     2
**
dvander@1203
     3
** The author disclaims copyright to this source code.  In place of
dvander@1203
     4
** a legal notice, here is a blessing:
dvander@1203
     5
**
dvander@1203
     6
**    May you do good and not evil.
dvander@1203
     7
**    May you find forgiveness for yourself and forgive others.
dvander@1203
     8
**    May you share freely, never taking more than you give.
dvander@1203
     9
**
dvander@1203
    10
*************************************************************************
dvander@1203
    11
*
dvander@1203
    12
*/
dvander@1203
    13
#include "sqliteInt.h"
dvander@1203
    14
dvander@1203
    15
#ifndef SQLITE_OMIT_TRIGGER
dvander@1203
    16
/*
dvander@1203
    17
** Delete a linked list of TriggerStep structures.
dvander@1203
    18
*/
dvander@1203
    19
void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
dvander@1203
    20
  while( pTriggerStep ){
dvander@1203
    21
    TriggerStep * pTmp = pTriggerStep;
dvander@1203
    22
    pTriggerStep = pTriggerStep->pNext;
dvander@1203
    23
dvander@1203
    24
    if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
dvander@1203
    25
    sqlite3ExprDelete(pTmp->pWhere);
dvander@1203
    26
    sqlite3ExprListDelete(pTmp->pExprList);
dvander@1203
    27
    sqlite3SelectDelete(pTmp->pSelect);
dvander@1203
    28
    sqlite3IdListDelete(pTmp->pIdList);
dvander@1203
    29
dvander@1203
    30
    sqliteFree(pTmp);
dvander@1203
    31
  }
dvander@1203
    32
}
dvander@1203
    33
dvander@1203
    34
/*
dvander@1203
    35
** This is called by the parser when it sees a CREATE TRIGGER statement
dvander@1203
    36
** up to the point of the BEGIN before the trigger actions.  A Trigger
dvander@1203
    37
** structure is generated based on the information available and stored
dvander@1203
    38
** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
dvander@1203
    39
** sqlite3FinishTrigger() function is called to complete the trigger
dvander@1203
    40
** construction process.
dvander@1203
    41
*/
dvander@1203
    42
void sqlite3BeginTrigger(
dvander@1203
    43
  Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
dvander@1203
    44
  Token *pName1,      /* The name of the trigger */
dvander@1203
    45
  Token *pName2,      /* The name of the trigger */
dvander@1203
    46
  int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
dvander@1203
    47
  int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
dvander@1203
    48
  IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
dvander@1203
    49
  SrcList *pTableName,/* The name of the table/view the trigger applies to */
dvander@1203
    50
  Expr *pWhen,        /* WHEN clause */
dvander@1203
    51
  int isTemp,         /* True if the TEMPORARY keyword is present */
dvander@1203
    52
  int noErr           /* Suppress errors if the trigger already exists */
dvander@1203
    53
){
dvander@1203
    54
  Trigger *pTrigger = 0;
dvander@1203
    55
  Table *pTab;
dvander@1203
    56
  char *zName = 0;        /* Name of the trigger */
dvander@1203
    57
  sqlite3 *db = pParse->db;
dvander@1203
    58
  int iDb;                /* The database to store the trigger in */
dvander@1203
    59
  Token *pName;           /* The unqualified db name */
dvander@1203
    60
  DbFixer sFix;
dvander@1203
    61
  int iTabDb;
dvander@1203
    62
dvander@1203
    63
  assert( pName1!=0 );   /* pName1->z might be NULL, but not pName1 itself */
dvander@1203
    64
  assert( pName2!=0 );
dvander@1203
    65
  if( isTemp ){
dvander@1203
    66
    /* If TEMP was specified, then the trigger name may not be qualified. */
dvander@1203
    67
    if( pName2->n>0 ){
dvander@1203
    68
      sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
dvander@1203
    69
      goto trigger_cleanup;
dvander@1203
    70
    }
dvander@1203
    71
    iDb = 1;
dvander@1203
    72
    pName = pName1;
dvander@1203
    73
  }else{
dvander@1203
    74
    /* Figure out the db that the the trigger will be created in */
dvander@1203
    75
    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
dvander@1203
    76
    if( iDb<0 ){
dvander@1203
    77
      goto trigger_cleanup;
dvander@1203
    78
    }
dvander@1203
    79
  }
dvander@1203
    80
dvander@1203
    81
  /* If the trigger name was unqualified, and the table is a temp table,
dvander@1203
    82
  ** then set iDb to 1 to create the trigger in the temporary database.
dvander@1203
    83
  ** If sqlite3SrcListLookup() returns 0, indicating the table does not
dvander@1203
    84
  ** exist, the error is caught by the block below.
dvander@1203
    85
  */
dvander@1203
    86
  if( !pTableName || sqlite3MallocFailed() ){
dvander@1203
    87
    goto trigger_cleanup;
dvander@1203
    88
  }
dvander@1203
    89
  pTab = sqlite3SrcListLookup(pParse, pTableName);
dvander@1203
    90
  if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
dvander@1203
    91
    iDb = 1;
dvander@1203
    92
  }
dvander@1203
    93
dvander@1203
    94
  /* Ensure the table name matches database name and that the table exists */
dvander@1203
    95
  if( sqlite3MallocFailed() ) goto trigger_cleanup;
dvander@1203
    96
  assert( pTableName->nSrc==1 );
dvander@1203
    97
  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && 
dvander@1203
    98
      sqlite3FixSrcList(&sFix, pTableName) ){
dvander@1203
    99
    goto trigger_cleanup;
dvander@1203
   100
  }
dvander@1203
   101
  pTab = sqlite3SrcListLookup(pParse, pTableName);
dvander@1203
   102
  if( !pTab ){
dvander@1203
   103
    /* The table does not exist. */
dvander@1203
   104
    goto trigger_cleanup;
dvander@1203
   105
  }
dvander@1203
   106
  if( IsVirtual(pTab) ){
dvander@1203
   107
    sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
dvander@1203
   108
    goto trigger_cleanup;
dvander@1203
   109
  }
dvander@1203
   110
dvander@1203
   111
  /* Check that the trigger name is not reserved and that no trigger of the
dvander@1203
   112
  ** specified name exists */
dvander@1203
   113
  zName = sqlite3NameFromToken(pName);
dvander@1203
   114
  if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
dvander@1203
   115
    goto trigger_cleanup;
dvander@1203
   116
  }
dvander@1203
   117
  if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
dvander@1203
   118
    if( !noErr ){
dvander@1203
   119
      sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
dvander@1203
   120
    }
dvander@1203
   121
    goto trigger_cleanup;
dvander@1203
   122
  }
dvander@1203
   123
dvander@1203
   124
  /* Do not create a trigger on a system table */
dvander@1203
   125
  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
dvander@1203
   126
    sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
dvander@1203
   127
    pParse->nErr++;
dvander@1203
   128
    goto trigger_cleanup;
dvander@1203
   129
  }
dvander@1203
   130
dvander@1203
   131
  /* INSTEAD of triggers are only for views and views only support INSTEAD
dvander@1203
   132
  ** of triggers.
dvander@1203
   133
  */
dvander@1203
   134
  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
dvander@1203
   135
    sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
dvander@1203
   136
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
dvander@1203
   137
    goto trigger_cleanup;
dvander@1203
   138
  }
dvander@1203
   139
  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
dvander@1203
   140
    sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
dvander@1203
   141
        " trigger on table: %S", pTableName, 0);
dvander@1203
   142
    goto trigger_cleanup;
dvander@1203
   143
  }
dvander@1203
   144
  iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
dvander@1203
   145
dvander@1203
   146
#ifndef SQLITE_OMIT_AUTHORIZATION
dvander@1203
   147
  {
dvander@1203
   148
    int code = SQLITE_CREATE_TRIGGER;
dvander@1203
   149
    const char *zDb = db->aDb[iTabDb].zName;
dvander@1203
   150
    const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
dvander@1203
   151
    if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
dvander@1203
   152
    if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
dvander@1203
   153
      goto trigger_cleanup;
dvander@1203
   154
    }
dvander@1203
   155
    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
dvander@1203
   156
      goto trigger_cleanup;
dvander@1203
   157
    }
dvander@1203
   158
  }
dvander@1203
   159
#endif
dvander@1203
   160
dvander@1203
   161
  /* INSTEAD OF triggers can only appear on views and BEFORE triggers
dvander@1203
   162
  ** cannot appear on views.  So we might as well translate every
dvander@1203
   163
  ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code
dvander@1203
   164
  ** elsewhere.
dvander@1203
   165
  */
dvander@1203
   166
  if (tr_tm == TK_INSTEAD){
dvander@1203
   167
    tr_tm = TK_BEFORE;
dvander@1203
   168
  }
dvander@1203
   169
dvander@1203
   170
  /* Build the Trigger object */
dvander@1203
   171
  pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger));
dvander@1203
   172
  if( pTrigger==0 ) goto trigger_cleanup;
dvander@1203
   173
  pTrigger->name = zName;
dvander@1203
   174
  zName = 0;
dvander@1203
   175
  pTrigger->table = sqliteStrDup(pTableName->a[0].zName);
dvander@1203
   176
  pTrigger->pSchema = db->aDb[iDb].pSchema;
dvander@1203
   177
  pTrigger->pTabSchema = pTab->pSchema;
dvander@1203
   178
  pTrigger->op = op;
dvander@1203
   179
  pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
dvander@1203
   180
  pTrigger->pWhen = sqlite3ExprDup(pWhen);
dvander@1203
   181
  pTrigger->pColumns = sqlite3IdListDup(pColumns);
dvander@1203
   182
  sqlite3TokenCopy(&pTrigger->nameToken,pName);
dvander@1203
   183
  assert( pParse->pNewTrigger==0 );
dvander@1203
   184
  pParse->pNewTrigger = pTrigger;
dvander@1203
   185
dvander@1203
   186
trigger_cleanup:
dvander@1203
   187
  sqliteFree(zName);
dvander@1203
   188
  sqlite3SrcListDelete(pTableName);
dvander@1203
   189
  sqlite3IdListDelete(pColumns);
dvander@1203
   190
  sqlite3ExprDelete(pWhen);
dvander@1203
   191
  if( !pParse->pNewTrigger ){
dvander@1203
   192
    sqlite3DeleteTrigger(pTrigger);
dvander@1203
   193
  }else{
dvander@1203
   194
    assert( pParse->pNewTrigger==pTrigger );
dvander@1203
   195
  }
dvander@1203
   196
}
dvander@1203
   197
dvander@1203
   198
/*
dvander@1203
   199
** This routine is called after all of the trigger actions have been parsed
dvander@1203
   200
** in order to complete the process of building the trigger.
dvander@1203
   201
*/
dvander@1203
   202
void sqlite3FinishTrigger(
dvander@1203
   203
  Parse *pParse,          /* Parser context */
dvander@1203
   204
  TriggerStep *pStepList, /* The triggered program */
dvander@1203
   205
  Token *pAll             /* Token that describes the complete CREATE TRIGGER */
dvander@1203
   206
){
dvander@1203
   207
  Trigger *pTrig = 0;     /* The trigger whose construction is finishing up */
dvander@1203
   208
  sqlite3 *db = pParse->db;  /* The database */
dvander@1203
   209
  DbFixer sFix;
dvander@1203
   210
  int iDb;                   /* Database containing the trigger */
dvander@1203
   211
dvander@1203
   212
  pTrig = pParse->pNewTrigger;
dvander@1203
   213
  pParse->pNewTrigger = 0;
dvander@1203
   214
  if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
dvander@1203
   215
  iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
dvander@1203
   216
  pTrig->step_list = pStepList;
dvander@1203
   217
  while( pStepList ){
dvander@1203
   218
    pStepList->pTrig = pTrig;
dvander@1203
   219
    pStepList = pStepList->pNext;
dvander@1203
   220
  }
dvander@1203
   221
  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) 
dvander@1203
   222
          && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
dvander@1203
   223
    goto triggerfinish_cleanup;
dvander@1203
   224
  }
dvander@1203
   225
dvander@1203
   226
  /* if we are not initializing, and this trigger is not on a TEMP table, 
dvander@1203
   227
  ** build the sqlite_master entry
dvander@1203
   228
  */
dvander@1203
   229
  if( !db->init.busy ){
dvander@1203
   230
    static const VdbeOpList insertTrig[] = {
dvander@1203
   231
      { OP_NewRowid,   0, 0,  0          },
dvander@1203
   232
      { OP_String8,    0, 0,  "trigger"  },
dvander@1203
   233
      { OP_String8,    0, 0,  0          },  /* 2: trigger name */
dvander@1203
   234
      { OP_String8,    0, 0,  0          },  /* 3: table name */
dvander@1203
   235
      { OP_Integer,    0, 0,  0          },
dvander@1203
   236
      { OP_String8,    0, 0,  "CREATE TRIGGER "},
dvander@1203
   237
      { OP_String8,    0, 0,  0          },  /* 6: SQL */
dvander@1203
   238
      { OP_Concat,     0, 0,  0          }, 
dvander@1203
   239
      { OP_MakeRecord, 5, 0,  "aaada"    },
dvander@1203
   240
      { OP_Insert,     0, 0,  0          },
dvander@1203
   241
    };
dvander@1203
   242
    int addr;
dvander@1203
   243
    Vdbe *v;
dvander@1203
   244
dvander@1203
   245
    /* Make an entry in the sqlite_master table */
dvander@1203
   246
    v = sqlite3GetVdbe(pParse);
dvander@1203
   247
    if( v==0 ) goto triggerfinish_cleanup;
dvander@1203
   248
    sqlite3BeginWriteOperation(pParse, 0, iDb);
dvander@1203
   249
    sqlite3OpenMasterTable(pParse, iDb);
dvander@1203
   250
    addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
dvander@1203
   251
    sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); 
dvander@1203
   252
    sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); 
dvander@1203
   253
    sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n);
dvander@1203
   254
    sqlite3ChangeCookie(db, v, iDb);
dvander@1203
   255
    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
dvander@1203
   256
    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, 
dvander@1203
   257
       sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
dvander@1203
   258
  }
dvander@1203
   259
dvander@1203
   260
  if( db->init.busy ){
dvander@1203
   261
    int n;
dvander@1203
   262
    Table *pTab;
dvander@1203
   263
    Trigger *pDel;
dvander@1203
   264
    pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, 
dvander@1203
   265
                     pTrig->name, strlen(pTrig->name), pTrig);
dvander@1203
   266
    if( pDel ){
dvander@1203
   267
      assert( sqlite3MallocFailed() && pDel==pTrig );
dvander@1203
   268
      goto triggerfinish_cleanup;
dvander@1203
   269
    }
dvander@1203
   270
    n = strlen(pTrig->table) + 1;
dvander@1203
   271
    pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
dvander@1203
   272
    assert( pTab!=0 );
dvander@1203
   273
    pTrig->pNext = pTab->pTrigger;
dvander@1203
   274
    pTab->pTrigger = pTrig;
dvander@1203
   275
    pTrig = 0;
dvander@1203
   276
  }
dvander@1203
   277
dvander@1203
   278
triggerfinish_cleanup:
dvander@1203
   279
  sqlite3DeleteTrigger(pTrig);
dvander@1203
   280
  assert( !pParse->pNewTrigger );
dvander@1203
   281
  sqlite3DeleteTriggerStep(pStepList);
dvander@1203
   282
}
dvander@1203
   283
dvander@1203
   284
/*
dvander@1203
   285
** Make a copy of all components of the given trigger step.  This has
dvander@1203
   286
** the effect of copying all Expr.token.z values into memory obtained
dvander@1203
   287
** from sqliteMalloc().  As initially created, the Expr.token.z values
dvander@1203
   288
** all point to the input string that was fed to the parser.  But that
dvander@1203
   289
** string is ephemeral - it will go away as soon as the sqlite3_exec()
dvander@1203
   290
** call that started the parser exits.  This routine makes a persistent
dvander@1203
   291
** copy of all the Expr.token.z strings so that the TriggerStep structure
dvander@1203
   292
** will be valid even after the sqlite3_exec() call returns.
dvander@1203
   293
*/
dvander@1203
   294
static void sqlitePersistTriggerStep(TriggerStep *p){
dvander@1203
   295
  if( p->target.z ){
dvander@1203
   296
    p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n);
dvander@1203
   297
    p->target.dyn = 1;
dvander@1203
   298
  }
dvander@1203
   299
  if( p->pSelect ){
dvander@1203
   300
    Select *pNew = sqlite3SelectDup(p->pSelect);
dvander@1203
   301
    sqlite3SelectDelete(p->pSelect);
dvander@1203
   302
    p->pSelect = pNew;
dvander@1203
   303
  }
dvander@1203
   304
  if( p->pWhere ){
dvander@1203
   305
    Expr *pNew = sqlite3ExprDup(p->pWhere);
dvander@1203
   306
    sqlite3ExprDelete(p->pWhere);
dvander@1203
   307
    p->pWhere = pNew;
dvander@1203
   308
  }
dvander@1203
   309
  if( p->pExprList ){
dvander@1203
   310
    ExprList *pNew = sqlite3ExprListDup(p->pExprList);
dvander@1203
   311
    sqlite3ExprListDelete(p->pExprList);
dvander@1203
   312
    p->pExprList = pNew;
dvander@1203
   313
  }
dvander@1203
   314
  if( p->pIdList ){
dvander@1203
   315
    IdList *pNew = sqlite3IdListDup(p->pIdList);
dvander@1203
   316
    sqlite3IdListDelete(p->pIdList);
dvander@1203
   317
    p->pIdList = pNew;
dvander@1203
   318
  }
dvander@1203
   319
}
dvander@1203
   320
dvander@1203
   321
/*
dvander@1203
   322
** Turn a SELECT statement (that the pSelect parameter points to) into
dvander@1203
   323
** a trigger step.  Return a pointer to a TriggerStep structure.
dvander@1203
   324
**
dvander@1203
   325
** The parser calls this routine when it finds a SELECT statement in
dvander@1203
   326
** body of a TRIGGER.  
dvander@1203
   327
*/
dvander@1203
   328
TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
dvander@1203
   329
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
dvander@1203
   330
  if( pTriggerStep==0 ) {
dvander@1203
   331
    sqlite3SelectDelete(pSelect);
dvander@1203
   332
    return 0;
dvander@1203
   333
  }
dvander@1203
   334
dvander@1203
   335
  pTriggerStep->op = TK_SELECT;
dvander@1203
   336
  pTriggerStep->pSelect = pSelect;
dvander@1203
   337
  pTriggerStep->orconf = OE_Default;
dvander@1203
   338
  sqlitePersistTriggerStep(pTriggerStep);
dvander@1203
   339
dvander@1203
   340
  return pTriggerStep;
dvander@1203
   341
}
dvander@1203
   342
dvander@1203
   343
/*
dvander@1203
   344
** Build a trigger step out of an INSERT statement.  Return a pointer
dvander@1203
   345
** to the new trigger step.
dvander@1203
   346
**
dvander@1203
   347
** The parser calls this routine when it sees an INSERT inside the
dvander@1203
   348
** body of a trigger.
dvander@1203
   349
*/
dvander@1203
   350
TriggerStep *sqlite3TriggerInsertStep(
dvander@1203
   351
  Token *pTableName,  /* Name of the table into which we insert */
dvander@1203
   352
  IdList *pColumn,    /* List of columns in pTableName to insert into */
dvander@1203
   353
  ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
dvander@1203
   354
  Select *pSelect,    /* A SELECT statement that supplies values */
dvander@1203
   355
  int orconf          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
dvander@1203
   356
){
dvander@1203
   357
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
dvander@1203
   358
dvander@1203
   359
  assert(pEList == 0 || pSelect == 0);
dvander@1203
   360
  assert(pEList != 0 || pSelect != 0);
dvander@1203
   361
dvander@1203
   362
  if( pTriggerStep ){
dvander@1203
   363
    pTriggerStep->op = TK_INSERT;
dvander@1203
   364
    pTriggerStep->pSelect = pSelect;
dvander@1203
   365
    pTriggerStep->target  = *pTableName;
dvander@1203
   366
    pTriggerStep->pIdList = pColumn;
dvander@1203
   367
    pTriggerStep->pExprList = pEList;
dvander@1203
   368
    pTriggerStep->orconf = orconf;
dvander@1203
   369
    sqlitePersistTriggerStep(pTriggerStep);
dvander@1203
   370
  }else{
dvander@1203
   371
    sqlite3IdListDelete(pColumn);
dvander@1203
   372
    sqlite3ExprListDelete(pEList);
dvander@1203
   373
    sqlite3SelectDup(pSelect);
dvander@1203
   374
  }
dvander@1203
   375
dvander@1203
   376
  return pTriggerStep;
dvander@1203
   377
}
dvander@1203
   378
dvander@1203
   379
/*
dvander@1203
   380
** Construct a trigger step that implements an UPDATE statement and return
dvander@1203
   381
** a pointer to that trigger step.  The parser calls this routine when it
dvander@1203
   382
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
dvander@1203
   383
*/
dvander@1203
   384
TriggerStep *sqlite3TriggerUpdateStep(
dvander@1203
   385
  Token *pTableName,   /* Name of the table to be updated */
dvander@1203
   386
  ExprList *pEList,    /* The SET clause: list of column and new values */
dvander@1203
   387
  Expr *pWhere,        /* The WHERE clause */
dvander@1203
   388
  int orconf           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
dvander@1203
   389
){
dvander@1203
   390
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
dvander@1203
   391
  if( pTriggerStep==0 ){
dvander@1203
   392
     sqlite3ExprListDelete(pEList);
dvander@1203
   393
     sqlite3ExprDelete(pWhere);
dvander@1203
   394
     return 0;
dvander@1203
   395
  }
dvander@1203
   396
dvander@1203
   397
  pTriggerStep->op = TK_UPDATE;
dvander@1203
   398
  pTriggerStep->target  = *pTableName;
dvander@1203
   399
  pTriggerStep->pExprList = pEList;
dvander@1203
   400
  pTriggerStep->pWhere = pWhere;
dvander@1203
   401
  pTriggerStep->orconf = orconf;
dvander@1203
   402
  sqlitePersistTriggerStep(pTriggerStep);
dvander@1203
   403
dvander@1203
   404
  return pTriggerStep;
dvander@1203
   405
}
dvander@1203
   406
dvander@1203
   407
/*
dvander@1203
   408
** Construct a trigger step that implements a DELETE statement and return
dvander@1203
   409
** a pointer to that trigger step.  The parser calls this routine when it
dvander@1203
   410
** sees a DELETE statement inside the body of a CREATE TRIGGER.
dvander@1203
   411
*/
dvander@1203
   412
TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
dvander@1203
   413
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
dvander@1203
   414
  if( pTriggerStep==0 ){
dvander@1203
   415
    sqlite3ExprDelete(pWhere);
dvander@1203
   416
    return 0;
dvander@1203
   417
  }
dvander@1203
   418
dvander@1203
   419
  pTriggerStep->op = TK_DELETE;
dvander@1203
   420
  pTriggerStep->target  = *pTableName;
dvander@1203
   421
  pTriggerStep->pWhere = pWhere;
dvander@1203
   422
  pTriggerStep->orconf = OE_Default;
dvander@1203
   423
  sqlitePersistTriggerStep(pTriggerStep);
dvander@1203
   424
dvander@1203
   425
  return pTriggerStep;
dvander@1203
   426
}
dvander@1203
   427
dvander@1203
   428
/* 
dvander@1203
   429
** Recursively delete a Trigger structure
dvander@1203
   430
*/
dvander@1203
   431
void sqlite3DeleteTrigger(Trigger *pTrigger){
dvander@1203
   432
  if( pTrigger==0 ) return;
dvander@1203
   433
  sqlite3DeleteTriggerStep(pTrigger->step_list);
dvander@1203
   434
  sqliteFree(pTrigger->name);
dvander@1203
   435
  sqliteFree(pTrigger->table);
dvander@1203
   436
  sqlite3ExprDelete(pTrigger->pWhen);
dvander@1203
   437
  sqlite3IdListDelete(pTrigger->pColumns);
dvander@1203
   438
  if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
dvander@1203
   439
  sqliteFree(pTrigger);
dvander@1203
   440
}
dvander@1203
   441
dvander@1203
   442
/*
dvander@1203
   443
** This function is called to drop a trigger from the database schema. 
dvander@1203
   444
**
dvander@1203
   445
** This may be called directly from the parser and therefore identifies
dvander@1203
   446
** the trigger by name.  The sqlite3DropTriggerPtr() routine does the
dvander@1203
   447
** same job as this routine except it takes a pointer to the trigger
dvander@1203
   448
** instead of the trigger name.
dvander@1203
   449
**/
dvander@1203
   450
void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
dvander@1203
   451
  Trigger *pTrigger = 0;
dvander@1203
   452
  int i;
dvander@1203
   453
  const char *zDb;
dvander@1203
   454
  const char *zName;
dvander@1203
   455
  int nName;
dvander@1203
   456
  sqlite3 *db = pParse->db;
dvander@1203
   457
dvander@1203
   458
  if( sqlite3MallocFailed() ) goto drop_trigger_cleanup;
dvander@1203
   459
  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
dvander@1203
   460
    goto drop_trigger_cleanup;
dvander@1203
   461
  }
dvander@1203
   462
dvander@1203
   463
  assert( pName->nSrc==1 );
dvander@1203
   464
  zDb = pName->a[0].zDatabase;
dvander@1203
   465
  zName = pName->a[0].zName;
dvander@1203
   466
  nName = strlen(zName);
dvander@1203
   467
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
dvander@1203
   468
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
dvander@1203
   469
    if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
dvander@1203
   470
    pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
dvander@1203
   471
    if( pTrigger ) break;
dvander@1203
   472
  }
dvander@1203
   473
  if( !pTrigger ){
dvander@1203
   474
    if( !noErr ){
dvander@1203
   475
      sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
dvander@1203
   476
    }
dvander@1203
   477
    goto drop_trigger_cleanup;
dvander@1203
   478
  }
dvander@1203
   479
  sqlite3DropTriggerPtr(pParse, pTrigger);
dvander@1203
   480
dvander@1203
   481
drop_trigger_cleanup:
dvander@1203
   482
  sqlite3SrcListDelete(pName);
dvander@1203
   483
}
dvander@1203
   484
dvander@1203
   485
/*
dvander@1203
   486
** Return a pointer to the Table structure for the table that a trigger
dvander@1203
   487
** is set on.
dvander@1203
   488
*/
dvander@1203
   489
static Table *tableOfTrigger(Trigger *pTrigger){
dvander@1203
   490
  int n = strlen(pTrigger->table) + 1;
dvander@1203
   491
  return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
dvander@1203
   492
}
dvander@1203
   493
dvander@1203
   494
dvander@1203
   495
/*
dvander@1203
   496
** Drop a trigger given a pointer to that trigger. 
dvander@1203
   497
*/
dvander@1203
   498
void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
dvander@1203
   499
  Table   *pTable;
dvander@1203
   500
  Vdbe *v;
dvander@1203
   501
  sqlite3 *db = pParse->db;
dvander@1203
   502
  int iDb;
dvander@1203
   503
dvander@1203
   504
  iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
dvander@1203
   505
  assert( iDb>=0 && iDb<db->nDb );
dvander@1203
   506
  pTable = tableOfTrigger(pTrigger);
dvander@1203
   507
  assert( pTable );
dvander@1203
   508
  assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
dvander@1203
   509
#ifndef SQLITE_OMIT_AUTHORIZATION
dvander@1203
   510
  {
dvander@1203
   511
    int code = SQLITE_DROP_TRIGGER;
dvander@1203
   512
    const char *zDb = db->aDb[iDb].zName;
dvander@1203
   513
    const char *zTab = SCHEMA_TABLE(iDb);
dvander@1203
   514
    if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
dvander@1203
   515
    if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
dvander@1203
   516
      sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
dvander@1203
   517
      return;
dvander@1203
   518
    }
dvander@1203
   519
  }
dvander@1203
   520
#endif
dvander@1203
   521
dvander@1203
   522
  /* Generate code to destroy the database record of the trigger.
dvander@1203
   523
  */
dvander@1203
   524
  assert( pTable!=0 );
dvander@1203
   525
  if( (v = sqlite3GetVdbe(pParse))!=0 ){
dvander@1203
   526
    int base;
dvander@1203
   527
    static const VdbeOpList dropTrigger[] = {
dvander@1203
   528
      { OP_Rewind,     0, ADDR(9),  0},
dvander@1203
   529
      { OP_String8,    0, 0,        0}, /* 1 */
dvander@1203
   530
      { OP_Column,     0, 1,        0},
dvander@1203
   531
      { OP_Ne,         0, ADDR(8),  0},
dvander@1203
   532
      { OP_String8,    0, 0,        "trigger"},
dvander@1203
   533
      { OP_Column,     0, 0,        0},
dvander@1203
   534
      { OP_Ne,         0, ADDR(8),  0},
dvander@1203
   535
      { OP_Delete,     0, 0,        0},
dvander@1203
   536
      { OP_Next,       0, ADDR(1),  0}, /* 8 */
dvander@1203
   537
    };
dvander@1203
   538
dvander@1203
   539
    sqlite3BeginWriteOperation(pParse, 0, iDb);
dvander@1203
   540
    sqlite3OpenMasterTable(pParse, iDb);
dvander@1203
   541
    base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
dvander@1203
   542
    sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
dvander@1203
   543
    sqlite3ChangeCookie(db, v, iDb);
dvander@1203
   544
    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
dvander@1203
   545
    sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0);
dvander@1203
   546
  }
dvander@1203
   547
}
dvander@1203
   548
dvander@1203
   549
/*
dvander@1203
   550
** Remove a trigger from the hash tables of the sqlite* pointer.
dvander@1203
   551
*/
dvander@1203
   552
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
dvander@1203
   553
  Trigger *pTrigger;
dvander@1203
   554
  int nName = strlen(zName);
dvander@1203
   555
  pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash),
dvander@1203
   556
                               zName, nName, 0);
dvander@1203
   557
  if( pTrigger ){
dvander@1203
   558
    Table *pTable = tableOfTrigger(pTrigger);
dvander@1203
   559
    assert( pTable!=0 );
dvander@1203
   560
    if( pTable->pTrigger == pTrigger ){
dvander@1203
   561
      pTable->pTrigger = pTrigger->pNext;
dvander@1203
   562
    }else{
dvander@1203
   563
      Trigger *cc = pTable->pTrigger;
dvander@1203
   564
      while( cc ){ 
dvander@1203
   565
        if( cc->pNext == pTrigger ){
dvander@1203
   566
          cc->pNext = cc->pNext->pNext;
dvander@1203
   567
          break;
dvander@1203
   568
        }
dvander@1203
   569
        cc = cc->pNext;
dvander@1203
   570
      }
dvander@1203
   571
      assert(cc);
dvander@1203
   572
    }
dvander@1203
   573
    sqlite3DeleteTrigger(pTrigger);
dvander@1203
   574
    db->flags |= SQLITE_InternChanges;
dvander@1203
   575
  }
dvander@1203
   576
}
dvander@1203
   577
dvander@1203
   578
/*
dvander@1203
   579
** pEList is the SET clause of an UPDATE statement.  Each entry
dvander@1203
   580
** in pEList is of the format <id>=<expr>.  If any of the entries
dvander@1203
   581
** in pEList have an <id> which matches an identifier in pIdList,
dvander@1203
   582
** then return TRUE.  If pIdList==NULL, then it is considered a
dvander@1203
   583
** wildcard that matches anything.  Likewise if pEList==NULL then
dvander@1203
   584
** it matches anything so always return true.  Return false only
dvander@1203
   585
** if there is no match.
dvander@1203
   586
*/
dvander@1203
   587
static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
dvander@1203
   588
  int e;
dvander@1203
   589
  if( !pIdList || !pEList ) return 1;
dvander@1203
   590
  for(e=0; e<pEList->nExpr; e++){
dvander@1203
   591
    if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
dvander@1203
   592
  }
dvander@1203
   593
  return 0; 
dvander@1203
   594
}
dvander@1203
   595
dvander@1203
   596
/*
dvander@1203
   597
** Return a bit vector to indicate what kind of triggers exist for operation
dvander@1203
   598
** "op" on table pTab.  If pChanges is not NULL then it is a list of columns
dvander@1203
   599
** that are being updated.  Triggers only match if the ON clause of the
dvander@1203
   600
** trigger definition overlaps the set of columns being updated.
dvander@1203
   601
**
dvander@1203
   602
** The returned bit vector is some combination of TRIGGER_BEFORE and
dvander@1203
   603
** TRIGGER_AFTER.
dvander@1203
   604
*/
dvander@1203
   605
int sqlite3TriggersExist(
dvander@1203
   606
  Parse *pParse,          /* Used to check for recursive triggers */
dvander@1203
   607
  Table *pTab,            /* The table the contains the triggers */
dvander@1203
   608
  int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
dvander@1203
   609
  ExprList *pChanges      /* Columns that change in an UPDATE statement */
dvander@1203
   610
){
dvander@1203
   611
  Trigger *pTrigger;
dvander@1203
   612
  int mask = 0;
dvander@1203
   613
dvander@1203
   614
  pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger;
dvander@1203
   615
  while( pTrigger ){
dvander@1203
   616
    if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
dvander@1203
   617
      mask |= pTrigger->tr_tm;
dvander@1203
   618
    }
dvander@1203
   619
    pTrigger = pTrigger->pNext;
dvander@1203
   620
  }
dvander@1203
   621
  return mask;
dvander@1203
   622
}
dvander@1203
   623
dvander@1203
   624
/*
dvander@1203
   625
** Convert the pStep->target token into a SrcList and return a pointer
dvander@1203
   626
** to that SrcList.
dvander@1203
   627
**
dvander@1203
   628
** This routine adds a specific database name, if needed, to the target when
dvander@1203
   629
** forming the SrcList.  This prevents a trigger in one database from
dvander@1203
   630
** referring to a target in another database.  An exception is when the
dvander@1203
   631
** trigger is in TEMP in which case it can refer to any other database it
dvander@1203
   632
** wants.
dvander@1203
   633
*/
dvander@1203
   634
static SrcList *targetSrcList(
dvander@1203
   635
  Parse *pParse,       /* The parsing context */
dvander@1203
   636
  TriggerStep *pStep   /* The trigger containing the target token */
dvander@1203
   637
){
dvander@1203
   638
  Token sDb;           /* Dummy database name token */
dvander@1203
   639
  int iDb;             /* Index of the database to use */
dvander@1203
   640
  SrcList *pSrc;       /* SrcList to be returned */
dvander@1203
   641
dvander@1203
   642
  iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
dvander@1203
   643
  if( iDb==0 || iDb>=2 ){
dvander@1203
   644
    assert( iDb<pParse->db->nDb );
dvander@1203
   645
    sDb.z = (u8*)pParse->db->aDb[iDb].zName;
dvander@1203
   646
    sDb.n = strlen((char*)sDb.z);
dvander@1203
   647
    pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target);
dvander@1203
   648
  } else {
dvander@1203
   649
    pSrc = sqlite3SrcListAppend(0, &pStep->target, 0);
dvander@1203
   650
  }
dvander@1203
   651
  return pSrc;
dvander@1203
   652
}
dvander@1203
   653
dvander@1203
   654
/*
dvander@1203
   655
** Generate VDBE code for zero or more statements inside the body of a
dvander@1203
   656
** trigger.  
dvander@1203
   657
*/
dvander@1203
   658
static int codeTriggerProgram(
dvander@1203
   659
  Parse *pParse,            /* The parser context */
dvander@1203
   660
  TriggerStep *pStepList,   /* List of statements inside the trigger body */
dvander@1203
   661
  int orconfin              /* Conflict algorithm. (OE_Abort, etc) */  
dvander@1203
   662
){
dvander@1203
   663
  TriggerStep * pTriggerStep = pStepList;
dvander@1203
   664
  int orconf;
dvander@1203
   665
  Vdbe *v = pParse->pVdbe;
dvander@1203
   666
dvander@1203
   667
  assert( pTriggerStep!=0 );
dvander@1203
   668
  assert( v!=0 );
dvander@1203
   669
  sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0);
dvander@1203
   670
  VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name));
dvander@1203
   671
  while( pTriggerStep ){
dvander@1203
   672
    orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
dvander@1203
   673
    pParse->trigStack->orconf = orconf;
dvander@1203
   674
    switch( pTriggerStep->op ){
dvander@1203
   675
      case TK_SELECT: {
dvander@1203
   676
	Select *ss = sqlite3SelectDup(pTriggerStep->pSelect);
dvander@1203
   677
        if( ss ){
dvander@1203
   678
          sqlite3SelectResolve(pParse, ss, 0);
dvander@1203
   679
          sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
dvander@1203
   680
          sqlite3SelectDelete(ss);
dvander@1203
   681
        }
dvander@1203
   682
	break;
dvander@1203
   683
      }
dvander@1203
   684
      case TK_UPDATE: {
dvander@1203
   685
        SrcList *pSrc;
dvander@1203
   686
        pSrc = targetSrcList(pParse, pTriggerStep);
dvander@1203
   687
        sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
dvander@1203
   688
        sqlite3Update(pParse, pSrc,
dvander@1203
   689
		sqlite3ExprListDup(pTriggerStep->pExprList), 
dvander@1203
   690
		sqlite3ExprDup(pTriggerStep->pWhere), orconf);
dvander@1203
   691
        sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
dvander@1203
   692
        break;
dvander@1203
   693
      }
dvander@1203
   694
      case TK_INSERT: {
dvander@1203
   695
        SrcList *pSrc;
dvander@1203
   696
        pSrc = targetSrcList(pParse, pTriggerStep);
dvander@1203
   697
        sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
dvander@1203
   698
        sqlite3Insert(pParse, pSrc,
dvander@1203
   699
          sqlite3ExprListDup(pTriggerStep->pExprList), 
dvander@1203
   700
          sqlite3SelectDup(pTriggerStep->pSelect), 
dvander@1203
   701
          sqlite3IdListDup(pTriggerStep->pIdList), orconf);
dvander@1203
   702
        sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
dvander@1203
   703
        break;
dvander@1203
   704
      }
dvander@1203
   705
      case TK_DELETE: {
dvander@1203
   706
        SrcList *pSrc;
dvander@1203
   707
        sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
dvander@1203
   708
        pSrc = targetSrcList(pParse, pTriggerStep);
dvander@1203
   709
        sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere));
dvander@1203
   710
        sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
dvander@1203
   711
        break;
dvander@1203
   712
      }
dvander@1203
   713
      default:
dvander@1203
   714
        assert(0);
dvander@1203
   715
    } 
dvander@1203
   716
    pTriggerStep = pTriggerStep->pNext;
dvander@1203
   717
  }
dvander@1203
   718
  sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
dvander@1203
   719
  VdbeComment((v, "# end trigger %s", pStepList->pTrig->name));
dvander@1203
   720
dvander@1203
   721
  return 0;
dvander@1203
   722
}
dvander@1203
   723
dvander@1203
   724
/*
dvander@1203
   725
** This is called to code FOR EACH ROW triggers.
dvander@1203
   726
**
dvander@1203
   727
** When the code that this function generates is executed, the following 
dvander@1203
   728
** must be true:
dvander@1203
   729
**
dvander@1203
   730
** 1. No cursors may be open in the main database.  (But newIdx and oldIdx
dvander@1203
   731
**    can be indices of cursors in temporary tables.  See below.)
dvander@1203
   732
**
dvander@1203
   733
** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
dvander@1203
   734
**    a temporary vdbe cursor (index newIdx) must be open and pointing at
dvander@1203
   735
**    a row containing values to be substituted for new.* expressions in the
dvander@1203
   736
**    trigger program(s).
dvander@1203
   737
**
dvander@1203
   738
** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
dvander@1203
   739
**    a temporary vdbe cursor (index oldIdx) must be open and pointing at
dvander@1203
   740
**    a row containing values to be substituted for old.* expressions in the
dvander@1203
   741
**    trigger program(s).
dvander@1203
   742
**
dvander@1203
   743
*/
dvander@1203
   744
int sqlite3CodeRowTrigger(
dvander@1203
   745
  Parse *pParse,       /* Parse context */
dvander@1203
   746
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
dvander@1203
   747
  ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
dvander@1203
   748
  int tr_tm,           /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
dvander@1203
   749
  Table *pTab,         /* The table to code triggers from */
dvander@1203
   750
  int newIdx,          /* The indice of the "new" row to access */
dvander@1203
   751
  int oldIdx,          /* The indice of the "old" row to access */
dvander@1203
   752
  int orconf,          /* ON CONFLICT policy */
dvander@1203
   753
  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */
dvander@1203
   754
){
dvander@1203
   755
  Trigger *p;
dvander@1203
   756
  TriggerStack trigStackEntry;
dvander@1203
   757
dvander@1203
   758
  assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
dvander@1203
   759
  assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
dvander@1203
   760
dvander@1203
   761
  assert(newIdx != -1 || oldIdx != -1);
dvander@1203
   762
dvander@1203
   763
  for(p=pTab->pTrigger; p; p=p->pNext){
dvander@1203
   764
    int fire_this = 0;
dvander@1203
   765
dvander@1203
   766
    /* Determine whether we should code this trigger */
dvander@1203
   767
    if( 
dvander@1203
   768
      p->op==op && 
dvander@1203
   769
      p->tr_tm==tr_tm && 
dvander@1203
   770
      (p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) &&
dvander@1203
   771
      (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges))
dvander@1203
   772
    ){
dvander@1203
   773
      TriggerStack *pS;      /* Pointer to trigger-stack entry */
dvander@1203
   774
      for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}
dvander@1203
   775
      if( !pS ){
dvander@1203
   776
        fire_this = 1;
dvander@1203
   777
      }
dvander@1203
   778
#if 0    /* Give no warning for recursive triggers.  Just do not do them */
dvander@1203
   779
      else{
dvander@1203
   780
        sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)",
dvander@1203
   781
            p->name);
dvander@1203
   782
        return SQLITE_ERROR;
dvander@1203
   783
      }
dvander@1203
   784
#endif
dvander@1203
   785
    }
dvander@1203
   786
 
dvander@1203
   787
    if( fire_this ){
dvander@1203
   788
      int endTrigger;
dvander@1203
   789
      Expr * whenExpr;
dvander@1203
   790
      AuthContext sContext;
dvander@1203
   791
      NameContext sNC;
dvander@1203
   792
dvander@1203
   793
      memset(&sNC, 0, sizeof(sNC));
dvander@1203
   794
      sNC.pParse = pParse;
dvander@1203
   795
dvander@1203
   796
      /* Push an entry on to the trigger stack */
dvander@1203
   797
      trigStackEntry.pTrigger = p;
dvander@1203
   798
      trigStackEntry.newIdx = newIdx;
dvander@1203
   799
      trigStackEntry.oldIdx = oldIdx;
dvander@1203
   800
      trigStackEntry.pTab = pTab;
dvander@1203
   801
      trigStackEntry.pNext = pParse->trigStack;
dvander@1203
   802
      trigStackEntry.ignoreJump = ignoreJump;
dvander@1203
   803
      pParse->trigStack = &trigStackEntry;
dvander@1203
   804
      sqlite3AuthContextPush(pParse, &sContext, p->name);
dvander@1203
   805
dvander@1203
   806
      /* code the WHEN clause */
dvander@1203
   807
      endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
dvander@1203
   808
      whenExpr = sqlite3ExprDup(p->pWhen);
dvander@1203
   809
      if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
dvander@1203
   810
        pParse->trigStack = trigStackEntry.pNext;
dvander@1203
   811
        sqlite3ExprDelete(whenExpr);
dvander@1203
   812
        return 1;
dvander@1203
   813
      }
dvander@1203
   814
      sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1);
dvander@1203
   815
      sqlite3ExprDelete(whenExpr);
dvander@1203
   816
dvander@1203
   817
      codeTriggerProgram(pParse, p->step_list, orconf); 
dvander@1203
   818
dvander@1203
   819
      /* Pop the entry off the trigger stack */
dvander@1203
   820
      pParse->trigStack = trigStackEntry.pNext;
dvander@1203
   821
      sqlite3AuthContextPop(&sContext);
dvander@1203
   822
dvander@1203
   823
      sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
dvander@1203
   824
    }
dvander@1203
   825
  }
dvander@1203
   826
  return 0;
dvander@1203
   827
}
dvander@1203
   828
#endif /* !defined(SQLITE_OMIT_TRIGGER) */