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