From 9ab4c2e88062dd16574c85ee37b81afc1f9e5e8b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 9 May 2009 00:18:38 +0000 Subject: [PATCH] Changes to the trigger.c module that facilitate full coverage testing. (CVS 6621) FossilOrigin-Name: 567ccc68cc8c73b952a91c71a0e00b08bb25c689 --- manifest | 16 +++++++------- manifest.uuid | 2 +- src/expr.c | 3 ++- src/trigger.c | 61 ++++++++++++++++++++++++++++++++------------------- 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index 1c09e2947d..aa5cac784c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\swarning\sin\sthe\sosx-specific\spart\sof\sos_unix.c.\sTicket\s#3847.\s(CVS\s6620) -D 2009-05-08T11:34:37 +C Changes\sto\sthe\strigger.c\smodule\sthat\sfacilitate\sfull\scoverage\stesting.\s(CVS\s6621) +D 2009-05-09T00:18:38 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -114,7 +114,7 @@ F src/callback.c c54a923b06a17a2f965e5c3a6f87a3a963209a4c F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3 F src/delete.c a0a0932eea77471ab243337026abbce444024c43 -F src/expr.c 8426ef8b80c754691b6e83f97756eab5364b005b +F src/expr.c d2297420722d6ce17f967f22401233b3af878bb3 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff F src/func.c f667fe886309707c7178542073bb0ced00a9fae7 F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c @@ -198,7 +198,7 @@ F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4 F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241 F src/tokenize.c 286ce8a4bffe5ec81ad893e6243684d8f8846ed9 -F src/trigger.c 5dcdcf5c719bfd1a58f98265d7c024b8c12e2dc1 +F src/trigger.c 853bb30f957c636a00b6437de755830213a9ee07 F src/update.c deb930324dd67b7ad98234e1258a0ebcdd1ca0f9 F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff F src/util.c 71c2d9d6befc0405377744585461246c30a4474b @@ -729,7 +729,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 88211ceeec01ee0d3e55231512be26dd672db099 -R 1496f8e77346601ffa77288043e57397 -U danielk1977 -Z 5271daa20456c0819a5a6b09124c54dd +P 254ca3273cfbd833de82296b4859e1ec5535e8be +R 29c312f4710fcc89e520e552563a8498 +U drh +Z 4d4c05b89d8d2f3c2da064b74794e76b diff --git a/manifest.uuid b/manifest.uuid index 3b8382422c..ea665f6b8d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -254ca3273cfbd833de82296b4859e1ec5535e8be \ No newline at end of file +567ccc68cc8c73b952a91c71a0e00b08bb25c689 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 1e3e4b3ef6..9ec98b04b6 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.432 2009/05/06 18:57:10 shane Exp $ +** $Id: expr.c,v 1.433 2009/05/09 00:18:38 drh Exp $ */ #include "sqliteInt.h" @@ -866,6 +866,7 @@ void sqlite3TokenCopy(sqlite3 *db, Token *pTo, const Token *pFrom){ pTo->n = pFrom->n; pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n); pTo->dyn = 1; + pTo->quoted = pFrom->quoted; }else{ pTo->z = 0; } diff --git a/src/trigger.c b/src/trigger.c index 70d2facc42..131b67599d 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -10,7 +10,7 @@ ************************************************************************* ** ** -** $Id: trigger.c,v 1.138 2009/05/06 18:42:21 drh Exp $ +** $Id: trigger.c,v 1.139 2009/05/09 00:18:38 drh Exp $ */ #include "sqliteInt.h" @@ -36,6 +36,16 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ /* ** Given table pTab, return a list of all the triggers attached to ** the table. The list is connected by Trigger.pNext pointers. +** +** All of the triggers on pTab that are in the same database as pTab +** are already attached to pTab->pTrigger. But there might be additional +** triggers on pTab in the TEMP schema. This routine prepends all +** TEMP triggers on pTab to the beginning of the pTab->pTrigger list +** and returns the combined list. +** +** To state it another way: This routine returns a list of all triggers +** that fire off of pTab. The list will include any TEMP triggers on +** pTab as well as the triggers lised in pTab->pTrigger. */ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ Schema * const pTmpSchema = pParse->db->aDb[1].pSchema; @@ -208,7 +218,7 @@ void sqlite3BeginTrigger( pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); pTrigger->pColumns = sqlite3IdListDup(db, pColumns); - sqlite3TokenCopy(db, &pTrigger->nameToken,pName); + sqlite3TokenCopy(db, &pTrigger->nameToken, pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; @@ -241,7 +251,7 @@ void sqlite3FinishTrigger( pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; - if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; + if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->name; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); pTrig->step_list = pStepList; @@ -460,7 +470,8 @@ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ sqlite3DbFree(db, pTrigger->table); sqlite3ExprDelete(db, pTrigger->pWhen); sqlite3IdListDelete(db, pTrigger->pColumns); - if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z); + assert( pTrigger->nameToken.dyn ); + sqlite3DbFree(db, (char*)pTrigger->nameToken.z); sqlite3DbFree(db, pTrigger); } @@ -582,7 +593,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ Hash *pHash = &(db->aDb[iDb].pSchema->trigHash); Trigger *pTrigger; pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); - if( pTrigger ){ + if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); Trigger **pp; @@ -603,9 +614,9 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ ** it matches anything so always return true. Return false only ** if there is no match. */ -static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ +static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){ int e; - if( !pIdList || !pEList ) return 1; + if( pIdList==0 || NEVER(pEList==0) ) return 1; for(e=0; enExpr; e++){ if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; } @@ -630,7 +641,7 @@ Trigger *sqlite3TriggersExist( Trigger *p; assert( pList==0 || IsVirtual(pTab)==0 ); for(p=pList; p; p=p->pNext){ - if( p->op==op && checkColumnOverLap(p->pColumns, pChanges) ){ + if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){ mask |= p->tr_tm; } } @@ -694,17 +705,6 @@ static int codeTriggerProgram( orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ - case TK_SELECT: { - Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect, 0); - if( ss ){ - SelectDest dest; - - sqlite3SelectDestInit(&dest, SRT_Discard, 0); - sqlite3Select(pParse, ss, &dest); - sqlite3SelectDelete(db, ss); - } - break; - } case TK_UPDATE: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); @@ -735,8 +735,17 @@ static int codeTriggerProgram( sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); break; } - default: - assert(0); + default: assert( pTriggerStep->op==TK_SELECT ); { + Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect, 0); + if( ss ){ + SelectDest dest; + + sqlite3SelectDestInit(&dest, SRT_Discard, 0); + sqlite3Select(pParse, ss, &dest); + sqlite3SelectDelete(db, ss); + } + break; + } } pTriggerStep = pTriggerStep->pNext; } @@ -802,12 +811,18 @@ int sqlite3CodeRowTrigger( for(p=pTrigger; p; p=p->pNext){ int fire_this = 0; + /* Sanity checking: The schema for the trigger and for the table are + ** always defined. The trigger must be in the same schema as the table + ** or else it must be a TEMP trigger. */ + assert( p->pSchema!=0 ); + assert( p->pTabSchema!=0 ); + assert( p->pSchema==p->pTabSchema || p->pSchema==db->aDb[1].pSchema ); + /* Determine whether we should code this trigger */ if( p->op==op && p->tr_tm==tr_tm && - (p->pSchema==p->pTabSchema || p->pSchema==db->aDb[1].pSchema) && - (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) + checkColumnOverlap(p->pColumns,pChanges) ){ TriggerStack *pS; /* Pointer to trigger-stack entry */ for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}