/*
 ** Recursively delete a Trigger structure
 */
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
    if( pTrigger==0 ) return;
    sqlite3DeleteTriggerStep(db, pTrigger->step_list);
    sqlite3DbFree(db, pTrigger->zName);
    sqlite3DbFree(db, pTrigger->table);
    sqlite3ExprDelete(db, pTrigger->pWhen);
    sqlite3IdListDelete(db, pTrigger->pColumns);
    sqlite3DbFree(db, pTrigger);
}
Beispiel #2
0
/* 
** Recursively delete a Trigger structure
*/
void sqlite3DeleteTrigger(Trigger *pTrigger){
  if( pTrigger==0 ) return;
  sqlite3DeleteTriggerStep(pTrigger->step_list);
  sqliteFree(pTrigger->name);
  sqliteFree(pTrigger->table);
  sqlite3ExprDelete(pTrigger->pWhen);
  sqlite3IdListDelete(pTrigger->pColumns);
  if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
  sqliteFree(pTrigger);
}
Beispiel #3
0
/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqlite3FinishTrigger(
  Parse *pParse,          /* Parser context */
  TriggerStep *pStepList, /* The triggered program */
  Token *pAll             /* Token that describes the complete CREATE TRIGGER */
){
  Trigger *nt = 0;          /* The trigger whose construction is finishing up */
  sqlite *db = pParse->db;  /* The database */
  DbFixer sFix;

  if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
  nt = pParse->pNewTrigger;
  pParse->pNewTrigger = 0;
  nt->step_list = pStepList;
  while( pStepList ){
    pStepList->pTrig = nt;
    pStepList = pStepList->pNext;
  }
  if( sqlite3FixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) 
          && sqlite3FixTriggerStep(&sFix, nt->step_list) ){
    goto triggerfinish_cleanup;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !db->init.busy ){
    static VdbeOpList insertTrig[] = {
      { OP_NewRecno,   0, 0,  0          },
      { OP_String8,     0, 0,  "trigger"  },
      { OP_String8,     0, 0,  0          },  /* 2: trigger name */
      { OP_String8,     0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String8,     0, 0,  "CREATE TRIGGER "},
      { OP_String8,     0, 0,  0          },  /* 6: SQL */
      { OP_Concat8,     2, 0,  0          }, 
      { OP_MakeRecord, 5, 0,  "tttit"    },
      { OP_PutIntKey,  0, 0,  0          },
    };
    int addr;
    Vdbe *v;

    /* Make an entry in the sqlite_master table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite3BeginWriteOperation(pParse, 0, nt->iDb);
    sqlite3OpenMasterTable(v, nt->iDb);
    addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); 
    sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); 
    sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n);
    if( nt->iDb!=0 ){
      sqlite3ChangeCookie(db, v, nt->iDb);
    }
    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
    sqlite3EndWriteOperation(pParse);
  }

  if( !pParse->explain ){
    Table *pTab;
    sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, 
                     nt->name, strlen(nt->name)+1, nt);
    pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
    assert( pTab!=0 );
    nt->pNext = pTab->pTrigger;
    pTab->pTrigger = nt;
    nt = 0;
  }

triggerfinish_cleanup:
  sqlite3DeleteTrigger(nt);
  sqlite3DeleteTrigger(pParse->pNewTrigger);
  pParse->pNewTrigger = 0;
  sqlite3DeleteTriggerStep(pStepList);
}
/*
 ** This routine is called after all of the trigger actions have been parsed
 ** in order to complete the process of building the trigger.
 */
SQLITE_PRIVATE void sqlite3FinishTrigger(
                                         Parse *pParse,          /* Parser context */
                                         TriggerStep *pStepList, /* The triggered program */
                                         Token *pAll             /* Token that describes the complete CREATE TRIGGER */
){
    Trigger *pTrig = pParse->pNewTrigger;   /* Trigger being finished */
    char *zName;                            /* Name of trigger */
    sqlite3 *db = pParse->db;               /* The database */
    DbFixer sFix;                           /* Fixer object */
    int iDb;                                /* Database containing the trigger */
    Token nameToken;                        /* Trigger name for error reporting */
    
    pParse->pNewTrigger = 0;
    if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
    zName = pTrig->zName;
    iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
    pTrig->step_list = pStepList;
    while( pStepList ){
        pStepList->pTrig = pTrig;
        pStepList = pStepList->pNext;
    }
    nameToken.z = pTrig->zName;
    nameToken.n = sqlite3Strlen30(nameToken.z);
    sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
    if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
       || sqlite3FixExpr(&sFix, pTrig->pWhen)
       ){
        goto triggerfinish_cleanup;
    }
    
    /* if we are not initializing,
     ** build the sqlite_master entry
     */
    if( !db->init.busy ){
        Vdbe *v;
        char *z;
        
        /* Make an entry in the sqlite_master table */
        v = sqlite3GetVdbe(pParse);
        if( v==0 ) goto triggerfinish_cleanup;
        sqlite3BeginWriteOperation(pParse, 0, iDb);
        z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
        sqlite3NestedParse(pParse,
                           "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
                           db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
                           pTrig->table, z);
        sqlite3DbFree(db, z);
        sqlite3ChangeCookie(pParse, iDb);
        sqlite3VdbeAddParseSchemaOp(v, iDb,
                                    sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
    }
    
    if( db->init.busy ){
        Trigger *pLink = pTrig;
        Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
        assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
        pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig);
        if( pTrig ){
            db->mallocFailed = 1;
        }else if( pLink->pSchema==pLink->pTabSchema ){
            Table *pTab;
            int n = sqlite3Strlen30(pLink->table);
            pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n);
            assert( pTab!=0 );
            pLink->pNext = pTab->pTrigger;
            pTab->pTrigger = pLink;
        }
    }
    
triggerfinish_cleanup:
    sqlite3DeleteTrigger(db, pTrig);
    assert( !pParse->pNewTrigger );
    sqlite3DeleteTriggerStep(db, pStepList);
}
Beispiel #5
0
/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqlite3FinishTrigger(
  Parse *pParse,          /* Parser context */
  TriggerStep *pStepList, /* The triggered program */
  Token *pAll             /* Token that describes the complete CREATE TRIGGER */
){
  Trigger *pTrig = 0;     /* The trigger whose construction is finishing up */
  sqlite3 *db = pParse->db;  /* The database */
  DbFixer sFix;
  int iDb;                   /* Database containing the trigger */

  pTrig = pParse->pNewTrigger;
  pParse->pNewTrigger = 0;
  if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
  iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
  pTrig->step_list = pStepList;
  while( pStepList ){
    pStepList->pTrig = pTrig;
    pStepList = pStepList->pNext;
  }
  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) 
          && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
    goto triggerfinish_cleanup;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !db->init.busy ){
    static const VdbeOpList insertTrig[] = {
      { OP_NewRowid,   0, 0,  0          },
      { OP_String8,    0, 0,  "trigger"  },
      { OP_String8,    0, 0,  0          },  /* 2: trigger name */
      { OP_String8,    0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String8,    0, 0,  "CREATE TRIGGER "},
      { OP_String8,    0, 0,  0          },  /* 6: SQL */
      { OP_Concat,     0, 0,  0          }, 
      { OP_MakeRecord, 5, 0,  "aaada"    },
      { OP_Insert,     0, 0,  0          },
    };
    int addr;
    Vdbe *v;

    /* Make an entry in the sqlite_master table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite3BeginWriteOperation(pParse, 0, iDb);
    sqlite3OpenMasterTable(pParse, iDb);
    addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); 
    sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); 
    sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n);
    sqlite3ChangeCookie(db, v, iDb);
    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, sqlite3MPrintf(
        db, "type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC
    );
  }

  if( db->init.busy ){
    int n;
    Table *pTab;
    Trigger *pDel;
    pDel = (Trigger*)sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, 
                     pTrig->name, strlen(pTrig->name), pTrig);
    if( pDel ){
      assert( pDel==pTrig );
      db->mallocFailed = 1;
      goto triggerfinish_cleanup;
    }
    n = strlen(pTrig->table) + 1;
    pTab = (Table*)sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
    assert( pTab!=0 );
    pTrig->pNext = pTab->pTrigger;
    pTab->pTrigger = pTrig;
    pTrig = 0;
  }

triggerfinish_cleanup:
  sqlite3DeleteTrigger(pTrig);
  assert( !pParse->pNewTrigger );
  sqlite3DeleteTriggerStep(pStepList);
}
/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqlite3FinishTrigger(
  Parse *pParse,          /* Parser context */
  TriggerStep *pStepList, /* The triggered program */
  Token *pAll             /* Token that describes the complete CREATE TRIGGER */
){
  Trigger *pTrig = 0;     /* The trigger whose construction is finishing up */
  sqlite3 *db = pParse->db;  /* The database */
  DbFixer sFix;
  int iDb;                   /* Database containing the trigger */

  pTrig = pParse->pNewTrigger;
  pParse->pNewTrigger = 0;
  if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
  iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
  pTrig->step_list = pStepList;
  while( pStepList ){
    pStepList->pTrig = pTrig;
    pStepList = pStepList->pNext;
  }
  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) 
          && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
    goto triggerfinish_cleanup;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !db->init.busy ){
    Vdbe *v;
    char *z;

    /* Make an entry in the sqlite_master table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite3BeginWriteOperation(pParse, 0, iDb);
    z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
    sqlite3NestedParse(pParse,
       "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name,
       pTrig->table, z);
    sqlite3DbFree(db, z);
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
        db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
    );
  }

  if( db->init.busy ){
    int n;
    Table *pTab;
    Trigger *pDel;
    pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, 
                     pTrig->name, sqlite3Strlen30(pTrig->name), pTrig);
    if( pDel ){
      assert( pDel==pTrig );
      db->mallocFailed = 1;
      goto triggerfinish_cleanup;
    }
    n = sqlite3Strlen30(pTrig->table) + 1;
    pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
    assert( pTab!=0 );
    pTrig->pNext = pTab->pTrigger;
    pTab->pTrigger = pTrig;
    pTrig = 0;
  }

triggerfinish_cleanup:
  sqlite3DeleteTrigger(db, pTrig);
  assert( !pParse->pNewTrigger );
  sqlite3DeleteTriggerStep(db, pStepList);
}