| Index: third_party/sqlite/src/src/trigger.c
|
| diff --git a/third_party/sqlite/src/src/trigger.c b/third_party/sqlite/src/src/trigger.c
|
| index 0f3f5bad394e35819f77733acc26d1533f844109..d2e7b5a1e6580b0b1be26ac5278dfad763b10fd0 100644
|
| --- a/third_party/sqlite/src/src/trigger.c
|
| +++ b/third_party/sqlite/src/src/trigger.c
|
| @@ -111,21 +111,34 @@ void sqlite3BeginTrigger(
|
| iDb = 1;
|
| pName = pName1;
|
| }else{
|
| - /* Figure out the db that the the trigger will be created in */
|
| + /* Figure out the db that the trigger will be created in */
|
| iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
| if( iDb<0 ){
|
| goto trigger_cleanup;
|
| }
|
| }
|
| + if( !pTableName || db->mallocFailed ){
|
| + goto trigger_cleanup;
|
| + }
|
| +
|
| + /* A long-standing parser bug is that this syntax was allowed:
|
| + **
|
| + ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
|
| + ** ^^^^^^^^
|
| + **
|
| + ** To maintain backwards compatibility, ignore the database
|
| + ** name on pTableName if we are reparsing out of SQLITE_MASTER.
|
| + */
|
| + if( db->init.busy && iDb!=1 ){
|
| + sqlite3DbFree(db, pTableName->a[0].zDatabase);
|
| + pTableName->a[0].zDatabase = 0;
|
| + }
|
|
|
| /* If the trigger name was unqualified, and the table is a temp table,
|
| ** then set iDb to 1 to create the trigger in the temporary database.
|
| ** If sqlite3SrcListLookup() returns 0, indicating the table does not
|
| ** exist, the error is caught by the block below.
|
| */
|
| - if( !pTableName || db->mallocFailed ){
|
| - goto trigger_cleanup;
|
| - }
|
| pTab = sqlite3SrcListLookup(pParse, pTableName);
|
| if( db->init.busy==0 && pName2->n==0 && pTab
|
| && pTab->pSchema==db->aDb[1].pSchema ){
|
| @@ -135,8 +148,8 @@ void sqlite3BeginTrigger(
|
| /* Ensure the table name matches database name and that the table exists */
|
| if( db->mallocFailed ) goto trigger_cleanup;
|
| assert( pTableName->nSrc==1 );
|
| - if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
|
| - sqlite3FixSrcList(&sFix, pTableName) ){
|
| + sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
|
| + if( sqlite3FixSrcList(&sFix, pTableName) ){
|
| goto trigger_cleanup;
|
| }
|
| pTab = sqlite3SrcListLookup(pParse, pTableName);
|
| @@ -167,8 +180,7 @@ void sqlite3BeginTrigger(
|
| goto trigger_cleanup;
|
| }
|
| assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
| - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
|
| - zName, sqlite3Strlen30(zName)) ){
|
| + if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
|
| if( !noErr ){
|
| sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
|
| }else{
|
| @@ -278,8 +290,10 @@ void sqlite3FinishTrigger(
|
| }
|
| nameToken.z = pTrig->zName;
|
| nameToken.n = sqlite3Strlen30(nameToken.z);
|
| - if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
|
| - && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
|
| + sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
|
| + if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
|
| + || sqlite3FixExpr(&sFix, pTrig->pWhen)
|
| + ){
|
| goto triggerfinish_cleanup;
|
| }
|
|
|
| @@ -301,22 +315,20 @@ void sqlite3FinishTrigger(
|
| pTrig->table, z);
|
| sqlite3DbFree(db, z);
|
| sqlite3ChangeCookie(pParse, iDb);
|
| - sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
|
| - db, "type='trigger' AND name='%q'", zName), P4_DYNAMIC
|
| - );
|
| + 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);
|
| + pTrig = sqlite3HashInsert(pHash, 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);
|
| + pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table);
|
| assert( pTab!=0 );
|
| pLink->pNext = pTab->pTrigger;
|
| pTab->pTrigger = pLink;
|
| @@ -383,25 +395,21 @@ TriggerStep *sqlite3TriggerInsertStep(
|
| sqlite3 *db, /* The database connection */
|
| Token *pTableName, /* Name of the table into which we insert */
|
| IdList *pColumn, /* List of columns in pTableName to insert into */
|
| - ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
|
| Select *pSelect, /* A SELECT statement that supplies values */
|
| u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
|
| ){
|
| TriggerStep *pTriggerStep;
|
|
|
| - assert(pEList == 0 || pSelect == 0);
|
| - assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
|
| + assert(pSelect != 0 || db->mallocFailed);
|
|
|
| pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
|
| if( pTriggerStep ){
|
| pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
|
| pTriggerStep->pIdList = pColumn;
|
| - pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
|
| pTriggerStep->orconf = orconf;
|
| }else{
|
| sqlite3IdListDelete(db, pColumn);
|
| }
|
| - sqlite3ExprListDelete(db, pEList);
|
| sqlite3SelectDelete(db, pSelect);
|
|
|
| return pTriggerStep;
|
| @@ -479,7 +487,6 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
|
| int i;
|
| const char *zDb;
|
| const char *zName;
|
| - int nName;
|
| sqlite3 *db = pParse->db;
|
|
|
| if( db->mallocFailed ) goto drop_trigger_cleanup;
|
| @@ -490,13 +497,12 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
|
| assert( pName->nSrc==1 );
|
| zDb = pName->a[0].zDatabase;
|
| zName = pName->a[0].zName;
|
| - nName = sqlite3Strlen30(zName);
|
| assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
| for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
| int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
| if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
|
| assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
| - pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
|
| + pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
|
| if( pTrigger ) break;
|
| }
|
| if( !pTrigger ){
|
| @@ -519,8 +525,7 @@ drop_trigger_cleanup:
|
| ** is set on.
|
| */
|
| static Table *tableOfTrigger(Trigger *pTrigger){
|
| - int n = sqlite3Strlen30(pTrigger->table);
|
| - return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
|
| + return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table);
|
| }
|
|
|
|
|
| @@ -556,6 +561,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
| assert( pTable!=0 );
|
| if( (v = sqlite3GetVdbe(pParse))!=0 ){
|
| int base;
|
| + static const int iLn = VDBE_OFFSET_LINENO(2);
|
| static const VdbeOpList dropTrigger[] = {
|
| { OP_Rewind, 0, ADDR(9), 0},
|
| { OP_String8, 0, 1, 0}, /* 1 */
|
| @@ -570,7 +576,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
|
|
| sqlite3BeginWriteOperation(pParse, 0, iDb);
|
| sqlite3OpenMasterTable(pParse, iDb);
|
| - base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
|
| + base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger, iLn);
|
| sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT);
|
| sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
|
| sqlite3ChangeCookie(pParse, iDb);
|
| @@ -591,7 +597,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
|
|
|
| assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
| pHash = &(db->aDb[iDb].pSchema->trigHash);
|
| - pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0);
|
| + pTrigger = sqlite3HashInsert(pHash, zName, 0);
|
| if( ALWAYS(pTrigger) ){
|
| if( pTrigger->pSchema==pTrigger->pTabSchema ){
|
| Table *pTab = tableOfTrigger(pTrigger);
|
| @@ -716,6 +722,7 @@ static int codeTriggerProgram(
|
| ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
|
| */
|
| pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
|
| + assert( pParse->okConstFactor==0 );
|
|
|
| switch( pStep->op ){
|
| case TK_UPDATE: {
|
| @@ -730,7 +737,6 @@ static int codeTriggerProgram(
|
| case TK_INSERT: {
|
| sqlite3Insert(pParse,
|
| targetSrcList(pParse, pStep),
|
| - sqlite3ExprListDup(db, pStep->pExprList, 0),
|
| sqlite3SelectDup(db, pStep->pSelect, 0),
|
| sqlite3IdListDup(db, pStep->pIdList),
|
| pParse->eOrconf
|
| @@ -761,7 +767,7 @@ static int codeTriggerProgram(
|
| return 0;
|
| }
|
|
|
| -#ifdef SQLITE_DEBUG
|
| +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
| /*
|
| ** This function is used to add VdbeComment() annotations to a VDBE
|
| ** program. It is not used in production code, only for debugging.
|
| @@ -892,6 +898,7 @@ static TriggerPrg *codeRowTrigger(
|
| }
|
| pProgram->nMem = pSubParse->nMem;
|
| pProgram->nCsr = pSubParse->nTab;
|
| + pProgram->nOnce = pSubParse->nOnce;
|
| pProgram->token = (void *)pTrigger;
|
| pPrg->aColmask[0] = pSubParse->oldmask;
|
| pPrg->aColmask[1] = pSubParse->newmask;
|
| @@ -900,6 +907,7 @@ static TriggerPrg *codeRowTrigger(
|
|
|
| assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
|
| assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
|
| + sqlite3ParserReset(pSubParse);
|
| sqlite3StackFree(db, pSubParse);
|
|
|
| return pPrg;
|
| @@ -980,7 +988,7 @@ void sqlite3CodeRowTriggerDirect(
|
| /*
|
| ** This is called to code the required FOR EACH ROW triggers for an operation
|
| ** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
|
| -** is given by the op paramater. The tr_tm parameter determines whether the
|
| +** is given by the op parameter. The tr_tm parameter determines whether the
|
| ** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
|
| ** parameter pChanges is passed the list of columns being modified.
|
| **
|
|
|