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. |
** |