wasCSharpSQLite – Blame information for rev 4

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Diagnostics;
3 using System.Text;
4  
5 using u8 = System.Byte;
6 using u32 = System.UInt32;
7 namespace Community.CsharpSqlite
8 {
9 public partial class Sqlite3
10 {
11 /*
12 **
13 ** The author disclaims copyright to this source code. In place of
14 ** a legal notice, here is a blessing:
15 **
16 ** May you do good and not evil.
17 ** May you find forgiveness for yourself and forgive others.
18 ** May you share freely, never taking more than you give.
19 **
20 *************************************************************************
21 ** This file contains the implementation for TRIGGERs
22 *************************************************************************
23 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
24 ** C#-SQLite is an independent reimplementation of the SQLite software library
25 **
26 ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
27 **
28 *************************************************************************
29 */
30 //#include "sqliteInt.h"
31  
32 #if !SQLITE_OMIT_TRIGGER
33 /*
34 ** Delete a linked list of TriggerStep structures.
35 */
36 static void sqlite3DeleteTriggerStep( sqlite3 db, ref TriggerStep pTriggerStep )
37 {
38 while ( pTriggerStep != null )
39 {
40 TriggerStep pTmp = pTriggerStep;
41 pTriggerStep = pTriggerStep.pNext;
42  
43 sqlite3ExprDelete( db, ref pTmp.pWhere );
44 sqlite3ExprListDelete( db, ref pTmp.pExprList );
45 sqlite3SelectDelete( db, ref pTmp.pSelect );
46 sqlite3IdListDelete( db, ref pTmp.pIdList );
47  
48 pTriggerStep = null;
49 sqlite3DbFree( db, ref pTmp );
50 }
51 }
52  
53 /*
54 ** Given table pTab, return a list of all the triggers attached to
55 ** the table. The list is connected by Trigger.pNext pointers.
56 **
57 ** All of the triggers on pTab that are in the same database as pTab
58 ** are already attached to pTab.pTrigger. But there might be additional
59 ** triggers on pTab in the TEMP schema. This routine prepends all
60 ** TEMP triggers on pTab to the beginning of the pTab.pTrigger list
61 ** and returns the combined list.
62 **
63 ** To state it another way: This routine returns a list of all triggers
64 ** that fire off of pTab. The list will include any TEMP triggers on
65 ** pTab as well as the triggers lised in pTab.pTrigger.
66 */
67 static Trigger sqlite3TriggerList( Parse pParse, Table pTab )
68 {
69 Schema pTmpSchema = pParse.db.aDb[1].pSchema;
70 Trigger pList = null; /* List of triggers to return */
71  
72 if ( pParse.disableTriggers != 0 )
73 {
74 return null;
75 }
76  
77 if ( pTmpSchema != pTab.pSchema )
78 {
79 HashElem p;
80 Debug.Assert( sqlite3SchemaMutexHeld( pParse.db, 0, pTmpSchema ) );
81 for ( p = sqliteHashFirst( pTmpSchema.trigHash ); p != null; p = sqliteHashNext( p ) )
82 {
83 Trigger pTrig = (Trigger)sqliteHashData( p );
84 if ( pTrig.pTabSchema == pTab.pSchema
85 && pTrig.table.Equals( pTab.zName, StringComparison.OrdinalIgnoreCase ) )
86 {
87 pTrig.pNext = ( pList != null ? pList : pTab.pTrigger );
88 pList = pTrig;
89 }
90 }
91 }
92  
93 return ( pList != null ? pList : pTab.pTrigger );
94 }
95  
96 /*
97 ** This is called by the parser when it sees a CREATE TRIGGER statement
98 ** up to the point of the BEGIN before the trigger actions. A Trigger
99 ** structure is generated based on the information available and stored
100 ** in pParse.pNewTrigger. After the trigger actions have been parsed, the
101 ** sqlite3FinishTrigger() function is called to complete the trigger
102 ** construction process.
103 */
104 static void sqlite3BeginTrigger(
105 Parse pParse, /* The parse context of the CREATE TRIGGER statement */
106 Token pName1, /* The name of the trigger */
107 Token pName2, /* The name of the trigger */
108 int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
109 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
110 IdList pColumns, /* column list if this is an UPDATE OF trigger */
111 SrcList pTableName,/* The name of the table/view the trigger applies to */
112 Expr pWhen, /* WHEN clause */
113 int isTemp, /* True if the TEMPORARY keyword is present */
114 int noErr /* Suppress errors if the trigger already exists */
115 )
116 {
117 Trigger pTrigger = null; /* The new trigger */
118 Table pTab; /* Table that the trigger fires off of */
119 string zName = null; /* Name of the trigger */
120 sqlite3 db = pParse.db; /* The database connection */
121 int iDb; /* The database to store the trigger in */
122 Token pName = null; /* The unqualified db name */
123 DbFixer sFix = new DbFixer(); /* State vector for the DB fixer */
124  
125 Debug.Assert( pName1 != null ); /* pName1.z might be NULL, but not pName1 itself */
126 Debug.Assert( pName2 != null );
127 Debug.Assert( op == TK_INSERT || op == TK_UPDATE || op == TK_DELETE );
128 Debug.Assert( op > 0 && op < 0xff );
129 if ( isTemp != 0 )
130 {
131 /* If TEMP was specified, then the trigger name may not be qualified. */
132 if ( pName2.n > 0 )
133 {
134 sqlite3ErrorMsg( pParse, "temporary trigger may not have qualified name" );
135 goto trigger_cleanup;
136 }
137 iDb = 1;
138 pName = pName1;
139 }
140 else
141 {
142 /* Figure out the db that the the trigger will be created in */
143 iDb = sqlite3TwoPartName( pParse, pName1, pName2, ref pName );
144 if ( iDb < 0 )
145 {
146 goto trigger_cleanup;
147 }
148 }
149 if ( null == pTableName ) //|| db.mallocFailed
150 {
151 goto trigger_cleanup;
152 }
153  
154 /* A long-standing parser bug is that this syntax was allowed:
155 **
156 ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
157 ** ^^^^^^^^
158 **
159 ** To maintain backwards compatibility, ignore the database
160 ** name on pTableName if we are reparsing our of SQLITE_MASTER.
161 */
162 if ( db.init.busy != 0 && iDb != 1 )
163 {
164 //sqlite3DbFree( db, pTableName.a[0].zDatabase );
165 pTableName.a[0].zDatabase = null;
166 }
167  
168 /* If the trigger name was unqualified, and the table is a temp table,
169 ** then set iDb to 1 to create the trigger in the temporary database.
170 ** If sqlite3SrcListLookup() returns 0, indicating the table does not
171 ** exist, the error is caught by the block below.
172 */
173 if ( pTableName == null /*|| db.mallocFailed != 0 */ )
174 {
175 goto trigger_cleanup;
176 }
177 pTab = sqlite3SrcListLookup( pParse, pTableName );
178 if ( db.init.busy == 0 && pName2.n == 0 && pTab != null
179 && pTab.pSchema == db.aDb[1].pSchema )
180 {
181 iDb = 1;
182 }
183  
184 /* Ensure the table name matches database name and that the table exists */
185 // if ( db.mallocFailed != 0 ) goto trigger_cleanup;
186 Debug.Assert( pTableName.nSrc == 1 );
187 if ( sqlite3FixInit( sFix, pParse, iDb, "trigger", pName ) != 0 &&
188 sqlite3FixSrcList( sFix, pTableName ) != 0 )
189 {
190 goto trigger_cleanup;
191 }
192 pTab = sqlite3SrcListLookup( pParse, pTableName );
193 if ( pTab == null )
194 {
195 /* The table does not exist. */
196 if ( db.init.iDb == 1 )
197 {
198 /* Ticket #3810.
199 ** Normally, whenever a table is dropped, all associated triggers are
200 ** dropped too. But if a TEMP trigger is created on a non-TEMP table
201 ** and the table is dropped by a different database connection, the
202 ** trigger is not visible to the database connection that does the
203 ** drop so the trigger cannot be dropped. This results in an
204 ** "orphaned trigger" - a trigger whose associated table is missing.
205 */
206 db.init.orphanTrigger = 1;
207 }
208 goto trigger_cleanup;
209 }
210 if ( IsVirtual( pTab ) )
211 {
212 sqlite3ErrorMsg( pParse, "cannot create triggers on virtual tables" );
213 goto trigger_cleanup;
214 }
215  
216 /* Check that the trigger name is not reserved and that no trigger of the
217 ** specified name exists */
218 zName = sqlite3NameFromToken( db, pName );
219 if ( zName == null || SQLITE_OK != sqlite3CheckObjectName( pParse, zName ) )
220 {
221 goto trigger_cleanup;
222 }
223 Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
224 if ( sqlite3HashFind( ( db.aDb[iDb].pSchema.trigHash ),
225 zName, sqlite3Strlen30( zName ), (Trigger)null ) != null )
226 {
227 if ( noErr == 0 )
228 {
229 sqlite3ErrorMsg( pParse, "trigger %T already exists", pName );
230 }
231 else
232 {
233 Debug.Assert( 0==db.init.busy );
234 sqlite3CodeVerifySchema( pParse, iDb );
235 }
236 goto trigger_cleanup;
237 }
238  
239 /* Do not create a trigger on a system table */
240 if ( pTab.zName.StartsWith( "sqlite_", System.StringComparison.OrdinalIgnoreCase ) )
241 {
242 sqlite3ErrorMsg( pParse, "cannot create trigger on system table" );
243 pParse.nErr++;
244 goto trigger_cleanup;
245 }
246  
247 /* INSTEAD of triggers are only for views and views only support INSTEAD
248 ** of triggers.
249 */
250 if ( pTab.pSelect != null && tr_tm != TK_INSTEAD )
251 {
252 sqlite3ErrorMsg( pParse, "cannot create %s trigger on view: %S",
253 ( tr_tm == TK_BEFORE ) ? "BEFORE" : "AFTER", pTableName, 0 );
254 goto trigger_cleanup;
255 }
256 if ( pTab.pSelect == null && tr_tm == TK_INSTEAD )
257 {
258 sqlite3ErrorMsg( pParse, "cannot create INSTEAD OF" +
259 " trigger on table: %S", pTableName, 0 );
260 goto trigger_cleanup;
261 }
262  
263 #if !SQLITE_OMIT_AUTHORIZATION
264 {
265 int iTabDb = sqlite3SchemaToIndex( db, pTab.pSchema );
266 int code = SQLITE_CREATE_TRIGGER;
267 string zDb = db.aDb[iTabDb].zName;
268 string zDbTrig = isTemp ? db.aDb[1].zName : zDb;
269 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
270 if( sqlite3AuthCheck(pParse, code, zName, pTab.zName, zDbTrig) ){
271 goto trigger_cleanup;
272 }
273 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
274 goto trigger_cleanup;
275 }
276 }
277 #endif
278  
279 /* INSTEAD OF triggers can only appear on views and BEFORE triggers
280 ** cannot appear on views. So we might as well translate every
281 ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code
282 ** elsewhere.
283 */
284 if ( tr_tm == TK_INSTEAD )
285 {
286 tr_tm = TK_BEFORE;
287 }
288  
289 /* Build the Trigger object */
290 pTrigger = new Trigger();// (Trigger*)sqlite3DbMallocZero( db, sizeof(Trigger ))
291 if ( pTrigger == null )
292 goto trigger_cleanup;
293 pTrigger.zName = zName;
294 pTrigger.table = pTableName.a[0].zName;// sqlite3DbStrDup( db, pTableName.a[0].zName );
295 pTrigger.pSchema = db.aDb[iDb].pSchema;
296 pTrigger.pTabSchema = pTab.pSchema;
297 pTrigger.op = (u8)op;
298 pTrigger.tr_tm = tr_tm == TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
299 pTrigger.pWhen = sqlite3ExprDup( db, pWhen, EXPRDUP_REDUCE );
300 pTrigger.pColumns = sqlite3IdListDup( db, pColumns );
301 Debug.Assert( pParse.pNewTrigger == null );
302 pParse.pNewTrigger = pTrigger;
303  
304 trigger_cleanup:
305 sqlite3DbFree( db, ref zName );
306 sqlite3SrcListDelete( db, ref pTableName );
307 sqlite3IdListDelete( db, ref pColumns );
308 sqlite3ExprDelete( db, ref pWhen );
309 if ( pParse.pNewTrigger == null )
310 {
311 sqlite3DeleteTrigger( db, ref pTrigger );
312 }
313 else
314 {
315 Debug.Assert( pParse.pNewTrigger == pTrigger );
316 }
317 }
318  
319 /*
320 ** This routine is called after all of the trigger actions have been parsed
321 ** in order to complete the process of building the trigger.
322 */
323 static void sqlite3FinishTrigger(
324 Parse pParse, /* Parser context */
325 TriggerStep pStepList, /* The triggered program */
326 Token pAll /* Token that describes the complete CREATE TRIGGER */
327 )
328 {
329 Trigger pTrig = pParse.pNewTrigger; /* Trigger being finished */
330 string zName; /* Name of trigger */
331  
332 sqlite3 db = pParse.db; /* The database */
333 DbFixer sFix = new DbFixer(); /* Fixer object */
334 int iDb; /* Database containing the trigger */
335 Token nameToken = new Token(); /* Trigger name for error reporting */
336  
337 pParse.pNewTrigger = null;
338 if ( NEVER( pParse.nErr != 0 ) || pTrig == null )
339 goto triggerfinish_cleanup;
340 zName = pTrig.zName;
341 iDb = sqlite3SchemaToIndex( pParse.db, pTrig.pSchema );
342 pTrig.step_list = pStepList;
343 while ( pStepList != null )
344 {
345 pStepList.pTrig = pTrig;
346 pStepList = pStepList.pNext;
347 }
348 nameToken.z = pTrig.zName;
349 nameToken.n = sqlite3Strlen30( nameToken.z );
350 if ( sqlite3FixInit( sFix, pParse, iDb, "trigger", nameToken ) != 0
351 && sqlite3FixTriggerStep( sFix, pTrig.step_list ) != 0 )
352 {
353 goto triggerfinish_cleanup;
354 }
355  
356 /* if we are not initializing,
357 ** build the sqlite_master entry
358 */
359 if ( 0 == db.init.busy )
360 {
361 Vdbe v;
362 string z;
363  
364 /* Make an entry in the sqlite_master table */
365 v = sqlite3GetVdbe( pParse );
366 if ( v == null )
367 goto triggerfinish_cleanup;
368 sqlite3BeginWriteOperation( pParse, 0, iDb );
369 z = pAll.z.Substring( 0, pAll.n );//sqlite3DbStrNDup( db, (char*)pAll.z, pAll.n );
370 sqlite3NestedParse( pParse,
371 "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
372 db.aDb[iDb].zName, SCHEMA_TABLE( iDb ), zName,
373 pTrig.table, z );
374 sqlite3DbFree( db, ref z );
375 sqlite3ChangeCookie( pParse, iDb );
376 sqlite3VdbeAddParseSchemaOp( v, iDb,
377 sqlite3MPrintf( db, "type='trigger' AND name='%q'", zName ) );
378 }
379  
380 if ( db.init.busy != 0 )
381 {
382 Trigger pLink = pTrig;
383 Hash pHash = db.aDb[iDb].pSchema.trigHash;
384 Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
385 pTrig = sqlite3HashInsert( ref pHash, zName, sqlite3Strlen30( zName ), pTrig );
386 if ( pTrig != null )
387 {
388 //db.mallocFailed = 1;
389 }
390 else if ( pLink.pSchema == pLink.pTabSchema )
391 {
392 Table pTab;
393 int n = sqlite3Strlen30( pLink.table );
394 pTab = sqlite3HashFind( pLink.pTabSchema.tblHash, pLink.table, n, (Table)null );
395 Debug.Assert( pTab != null );
396 pLink.pNext = pTab.pTrigger;
397 pTab.pTrigger = pLink;
398 }
399 }
400  
401 triggerfinish_cleanup:
402 sqlite3DeleteTrigger( db, ref pTrig );
403 Debug.Assert( pParse.pNewTrigger == null );
404 sqlite3DeleteTriggerStep( db, ref pStepList );
405 }
406  
407 /*
408 ** Turn a SELECT statement (that the pSelect parameter points to) into
409 ** a trigger step. Return a pointer to a TriggerStep structure.
410 **
411 ** The parser calls this routine when it finds a SELECT statement in
412 ** body of a TRIGGER.
413 */
414 static TriggerStep sqlite3TriggerSelectStep( sqlite3 db, Select pSelect )
415 {
416 TriggerStep pTriggerStep = new TriggerStep();// sqlite3DbMallocZero( db, sizeof(TriggerStep ))
417 if ( pTriggerStep == null )
418 {
419 sqlite3SelectDelete( db, ref pSelect );
420 return null;
421 }
422  
423 pTriggerStep.op = TK_SELECT;
424 pTriggerStep.pSelect = pSelect;
425 pTriggerStep.orconf = OE_Default;
426 return pTriggerStep;
427 }
428  
429 /*
430 ** Allocate space to hold a new trigger step. The allocated space
431 ** holds both the TriggerStep object and the TriggerStep.target.z string.
432 **
433 ** If an OOM error occurs, NULL is returned and db.mallocFailed is set.
434 */
435 static TriggerStep triggerStepAllocate(
436 sqlite3 db, /* Database connection */
437 u8 op, /* Trigger opcode */
438 Token pName /* The target name */
439 )
440 {
441 TriggerStep pTriggerStep;
442  
443 pTriggerStep = new TriggerStep();// sqlite3DbMallocZero( db, sizeof( TriggerStep ) + pName.n );
444 //if ( pTriggerStep != null )
445 //{
446 string z;// = (char*)&pTriggerStep[1];
447 z = pName.z;// memcpy( z, pName.z, pName.n );
448 pTriggerStep.target.z = z;
449 pTriggerStep.target.n = pName.n;
450 pTriggerStep.op = op;
451 //}
452 return pTriggerStep;
453 }
454  
455 /*
456 ** Build a trigger step out of an INSERT statement. Return a pointer
457 ** to the new trigger step.
458 **
459 ** The parser calls this routine when it sees an INSERT inside the
460 ** body of a trigger.
461 */
462 // OVERLOADS, so I don't need to rewrite parse.c
463 static TriggerStep sqlite3TriggerInsertStep( sqlite3 db, Token pTableName, IdList pColumn, int null_4, int null_5, u8 orconf )
464 {
465 return sqlite3TriggerInsertStep( db, pTableName, pColumn, null, null, orconf );
466 }
467 static TriggerStep sqlite3TriggerInsertStep( sqlite3 db, Token pTableName, IdList pColumn, ExprList pEList, int null_5, u8 orconf )
468 {
469 return sqlite3TriggerInsertStep( db, pTableName, pColumn, pEList, null, orconf );
470 }
471 static TriggerStep sqlite3TriggerInsertStep( sqlite3 db, Token pTableName, IdList pColumn, int null_4, Select pSelect, u8 orconf )
472 {
473 return sqlite3TriggerInsertStep( db, pTableName, pColumn, null, pSelect, orconf );
474 }
475 static TriggerStep sqlite3TriggerInsertStep(
476 sqlite3 db, /* The database connection */
477 Token pTableName, /* Name of the table into which we insert */
478 IdList pColumn, /* List of columns in pTableName to insert into */
479 ExprList pEList, /* The VALUE clause: a list of values to be inserted */
480 Select pSelect, /* A SELECT statement that supplies values */
481 u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
482 )
483 {
484 TriggerStep pTriggerStep;
485  
486 Debug.Assert( pEList == null || pSelect == null );
487 Debug.Assert( pEList != null || pSelect != null /*|| db.mallocFailed != 0 */ );
488  
489 pTriggerStep = triggerStepAllocate( db, TK_INSERT, pTableName );
490 //if ( pTriggerStep != null )
491 //{
492 pTriggerStep.pSelect = sqlite3SelectDup( db, pSelect, EXPRDUP_REDUCE );
493 pTriggerStep.pIdList = pColumn;
494 pTriggerStep.pExprList = sqlite3ExprListDup( db, pEList, EXPRDUP_REDUCE );
495 pTriggerStep.orconf = orconf;
496 //}
497 //else
498 //{
499 // sqlite3IdListDelete( db, ref pColumn );
500 //}
501 sqlite3ExprListDelete( db, ref pEList );
502 sqlite3SelectDelete( db, ref pSelect );
503  
504 return pTriggerStep;
505 }
506  
507 /*
508 ** Construct a trigger step that implements an UPDATE statement and return
509 ** a pointer to that trigger step. The parser calls this routine when it
510 ** sees an UPDATE statement inside the body of a CREATE TRIGGER.
511 */
512 static TriggerStep sqlite3TriggerUpdateStep(
513 sqlite3 db, /* The database connection */
514 Token pTableName, /* Name of the table to be updated */
515 ExprList pEList, /* The SET clause: list of column and new values */
516 Expr pWhere, /* The WHERE clause */
517 u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
518 )
519 {
520 TriggerStep pTriggerStep;
521  
522 pTriggerStep = triggerStepAllocate( db, TK_UPDATE, pTableName );
523 //if ( pTriggerStep != null )
524 //{
525 pTriggerStep.pExprList = sqlite3ExprListDup( db, pEList, EXPRDUP_REDUCE );
526 pTriggerStep.pWhere = sqlite3ExprDup( db, pWhere, EXPRDUP_REDUCE );
527 pTriggerStep.orconf = orconf;
528 //}
529 sqlite3ExprListDelete( db, ref pEList );
530 sqlite3ExprDelete( db, ref pWhere );
531 return pTriggerStep;
532 }
533  
534 /*
535 ** Construct a trigger step that implements a DELETE statement and return
536 ** a pointer to that trigger step. The parser calls this routine when it
537 ** sees a DELETE statement inside the body of a CREATE TRIGGER.
538 */
539 static TriggerStep sqlite3TriggerDeleteStep(
540 sqlite3 db, /* Database connection */
541 Token pTableName, /* The table from which rows are deleted */
542 Expr pWhere /* The WHERE clause */
543 )
544 {
545 TriggerStep pTriggerStep;
546  
547 pTriggerStep = triggerStepAllocate( db, TK_DELETE, pTableName );
548 //if ( pTriggerStep != null )
549 //{
550 pTriggerStep.pWhere = sqlite3ExprDup( db, pWhere, EXPRDUP_REDUCE );
551 pTriggerStep.orconf = OE_Default;
552 //}
553 sqlite3ExprDelete( db, ref pWhere );
554 return pTriggerStep;
555 }
556  
557  
558  
559 /*
560 ** Recursively delete a Trigger structure
561 */
562 static void sqlite3DeleteTrigger( sqlite3 db, ref Trigger pTrigger )
563 {
564 if ( pTrigger == null )
565 return;
566 sqlite3DeleteTriggerStep( db, ref pTrigger.step_list );
567 sqlite3DbFree( db, ref pTrigger.zName );
568 sqlite3DbFree( db, ref pTrigger.table );
569 sqlite3ExprDelete( db, ref pTrigger.pWhen );
570 sqlite3IdListDelete( db, ref pTrigger.pColumns );
571 pTrigger = null;
572 sqlite3DbFree( db, ref pTrigger );
573 }
574  
575 /*
576 ** This function is called to drop a trigger from the database schema.
577 **
578 ** This may be called directly from the parser and therefore identifies
579 ** the trigger by name. The sqlite3DropTriggerPtr() routine does the
580 ** same job as this routine except it takes a pointer to the trigger
581 ** instead of the trigger name.
582 **/
583 static void sqlite3DropTrigger( Parse pParse, SrcList pName, int noErr )
584 {
585 Trigger pTrigger = null;
586 int i;
587 string zDb;
588 string zName;
589 int nName;
590 sqlite3 db = pParse.db;
591  
592 // if ( db.mallocFailed != 0 ) goto drop_trigger_cleanup;
593 if ( SQLITE_OK != sqlite3ReadSchema( pParse ) )
594 {
595 goto drop_trigger_cleanup;
596 }
597  
598 Debug.Assert( pName.nSrc == 1 );
599 zDb = pName.a[0].zDatabase;
600 zName = pName.a[0].zName;
601 nName = sqlite3Strlen30( zName );
602 Debug.Assert( zDb != null || sqlite3BtreeHoldsAllMutexes( db ) );
603 for ( i = OMIT_TEMPDB; i < db.nDb; i++ )
604 {
605 int j = ( i < 2 ) ? i ^ 1 : i; /* Search TEMP before MAIN */
606 if ( zDb != null && !db.aDb[j].zName.Equals( zDb ,StringComparison.OrdinalIgnoreCase ) )
607 continue;
608 Debug.Assert( sqlite3SchemaMutexHeld( db, j, null ) );
609 pTrigger = sqlite3HashFind( ( db.aDb[j].pSchema.trigHash ), zName, nName, (Trigger)null );
610 if ( pTrigger != null )
611 break;
612 }
613 if ( pTrigger == null )
614 {
615 if ( noErr == 0 )
616 {
617 sqlite3ErrorMsg( pParse, "no such trigger: %S", pName, 0 );
618 }
619 else
620 {
621 sqlite3CodeVerifyNamedSchema( pParse, zDb );
622 }
623 pParse.checkSchema = 1;
624 goto drop_trigger_cleanup;
625 }
626 sqlite3DropTriggerPtr( pParse, pTrigger );
627  
628 drop_trigger_cleanup:
629 sqlite3SrcListDelete( db, ref pName );
630 }
631  
632 /*
633 ** Return a pointer to the Table structure for the table that a trigger
634 ** is set on.
635 */
636 static Table tableOfTrigger( Trigger pTrigger )
637 {
638 int n = sqlite3Strlen30( pTrigger.table );
639 return sqlite3HashFind( pTrigger.pTabSchema.tblHash, pTrigger.table, n, (Table)null );
640 }
641  
642  
643 /*
644 ** Drop a trigger given a pointer to that trigger.
645 */
646 static void sqlite3DropTriggerPtr( Parse pParse, Trigger pTrigger )
647 {
648 Table pTable;
649 Vdbe v;
650 sqlite3 db = pParse.db;
651 int iDb;
652  
653 iDb = sqlite3SchemaToIndex( pParse.db, pTrigger.pSchema );
654 Debug.Assert( iDb >= 0 && iDb < db.nDb );
655 pTable = tableOfTrigger( pTrigger );
656 Debug.Assert( pTable != null );
657 Debug.Assert( pTable.pSchema == pTrigger.pSchema || iDb == 1 );
658 #if !SQLITE_OMIT_AUTHORIZATION
659 {
660 int code = SQLITE_DROP_TRIGGER;
661 string zDb = db.aDb[iDb].zName;
662 string zTab = SCHEMA_TABLE(iDb);
663 if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
664 if( sqlite3AuthCheck(pParse, code, pTrigger.name, pTable.zName, zDb) ||
665 sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
666 return;
667 }
668 }
669 #endif
670  
671 /* Generate code to destroy the database record of the trigger.
672 */
673 Debug.Assert( pTable != null );
674 if ( ( v = sqlite3GetVdbe( pParse ) ) != null )
675 {
676 int _base;
677 VdbeOpList[] dropTrigger = new VdbeOpList[] {
678 new VdbeOpList( OP_Rewind, 0, ADDR(9), 0),
679 new VdbeOpList( OP_String8, 0, 1, 0), /* 1 */
680 new VdbeOpList( OP_Column, 0, 1, 2),
681 new VdbeOpList( OP_Ne, 2, ADDR(8), 1),
682 new VdbeOpList( OP_String8, 0, 1, 0), /* 4: "trigger" */
683 new VdbeOpList( OP_Column, 0, 0, 2),
684 new VdbeOpList( OP_Ne, 2, ADDR(8), 1),
685 new VdbeOpList( OP_Delete, 0, 0, 0),
686 new VdbeOpList( OP_Next, 0, ADDR(1), 0), /* 8 */
687 };
688  
689 sqlite3BeginWriteOperation( pParse, 0, iDb );
690 sqlite3OpenMasterTable( pParse, iDb );
691 _base = sqlite3VdbeAddOpList( v, dropTrigger.Length, dropTrigger );
692 sqlite3VdbeChangeP4( v, _base + 1, pTrigger.zName, P4_TRANSIENT );
693 sqlite3VdbeChangeP4( v, _base + 4, "trigger", P4_STATIC );
694 sqlite3ChangeCookie( pParse, iDb );
695 sqlite3VdbeAddOp2( v, OP_Close, 0, 0 );
696 sqlite3VdbeAddOp4( v, OP_DropTrigger, iDb, 0, 0, pTrigger.zName, 0 );
697 if ( pParse.nMem < 3 )
698 {
699 pParse.nMem = 3;
700 }
701 }
702 }
703  
704 /*
705 ** Remove a trigger from the hash tables of the sqlite* pointer.
706 */
707 static void sqlite3UnlinkAndDeleteTrigger( sqlite3 db, int iDb, string zName )
708 {
709 Trigger pTrigger;
710 Hash pHash;
711  
712 Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
713 pHash = ( db.aDb[iDb].pSchema.trigHash );
714 pTrigger = sqlite3HashInsert( ref pHash, zName, sqlite3Strlen30( zName ), (Trigger)null );
715 if ( ALWAYS( pTrigger != null ) )
716 {
717 if ( pTrigger.pSchema == pTrigger.pTabSchema )
718 {
719 Table pTab = tableOfTrigger( pTrigger );
720 //Trigger** pp;
721 //for ( pp = &pTab.pTrigger ; *pp != pTrigger ; pp = &( (*pp).pNext ) ) ;
722 //*pp = (*pp).pNext;
723 if ( pTab.pTrigger == pTrigger )
724 {
725 pTab.pTrigger = pTrigger.pNext;
726 }
727 else
728 {
729 Trigger cc = pTab.pTrigger;
730 while ( cc != null )
731 {
732 if ( cc.pNext == pTrigger )
733 {
734 cc.pNext = cc.pNext.pNext;
735 break;
736 }
737 cc = cc.pNext;
738 }
739 Debug.Assert( cc != null );
740 }
741 }
742 sqlite3DeleteTrigger( db, ref pTrigger );
743 db.flags |= SQLITE_InternChanges;
744 }
745 }
746  
747 /*
748 ** pEList is the SET clause of an UPDATE statement. Each entry
749 ** in pEList is of the format <id>=<expr>. If any of the entries
750 ** in pEList have an <id> which matches an identifier in pIdList,
751 ** then return TRUE. If pIdList==NULL, then it is considered a
752 ** wildcard that matches anything. Likewise if pEList==NULL then
753 ** it matches anything so always return true. Return false only
754 ** if there is no match.
755 */
756 static int checkColumnOverlap( IdList pIdList, ExprList pEList )
757 {
758 int e;
759 if ( pIdList == null || NEVER( pEList == null ) )
760 return 1;
761 for ( e = 0; e < pEList.nExpr; e++ )
762 {
763 if ( sqlite3IdListIndex( pIdList, pEList.a[e].zName ) >= 0 )
764 return 1;
765 }
766 return 0;
767 }
768  
769 /*
770 ** Return a list of all triggers on table pTab if there exists at least
771 ** one trigger that must be fired when an operation of type 'op' is
772 ** performed on the table, and, if that operation is an UPDATE, if at
773 ** least one of the columns in pChanges is being modified.
774 */
775 static Trigger sqlite3TriggersExist(
776 Parse pParse, /* Parse context */
777 Table pTab, /* The table the contains the triggers */
778 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
779 ExprList pChanges, /* Columns that change in an UPDATE statement */
780 out int pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
781 )
782 {
783 int mask = 0;
784 Trigger pList = null;
785 Trigger p;
786  
787 if ( ( pParse.db.flags & SQLITE_EnableTrigger ) != 0 )
788 {
789 pList = sqlite3TriggerList( pParse, pTab );
790 }
791 Debug.Assert( pList == null || IsVirtual( pTab ) == false );
792 for ( p = pList; p != null; p = p.pNext )
793 {
794 if ( p.op == op && checkColumnOverlap( p.pColumns, pChanges ) != 0 )
795 {
796 mask |= p.tr_tm;
797 }
798 }
799 //if ( pMask != 0 )
800 {
801 pMask = mask;
802 }
803 return ( mask != 0 ? pList : null );
804 }
805  
806  
807 /*
808 ** Convert the pStep.target token into a SrcList and return a pointer
809 ** to that SrcList.
810 **
811 ** This routine adds a specific database name, if needed, to the target when
812 ** forming the SrcList. This prevents a trigger in one database from
813 ** referring to a target in another database. An exception is when the
814 ** trigger is in TEMP in which case it can refer to any other database it
815 ** wants.
816 */
817 static SrcList targetSrcList(
818 Parse pParse, /* The parsing context */
819 TriggerStep pStep /* The trigger containing the target token */
820 )
821 {
822 int iDb; /* Index of the database to use */
823 SrcList pSrc; /* SrcList to be returned */
824  
825 pSrc = sqlite3SrcListAppend( pParse.db, 0, pStep.target, 0 );
826 //if ( pSrc != null )
827 //{
828 Debug.Assert( pSrc.nSrc > 0 );
829 Debug.Assert( pSrc.a != null );
830 iDb = sqlite3SchemaToIndex( pParse.db, pStep.pTrig.pSchema );
831 if ( iDb == 0 || iDb >= 2 )
832 {
833 sqlite3 db = pParse.db;
834 Debug.Assert( iDb < pParse.db.nDb );
835 pSrc.a[pSrc.nSrc - 1].zDatabase = db.aDb[iDb].zName;// sqlite3DbStrDup( db, db.aDb[iDb].zName );
836 }
837 //}
838 return pSrc;
839 }
840  
841 /*
842 ** Generate VDBE code for the statements inside the body of a single
843 ** trigger.
844 */
845 static int codeTriggerProgram(
846 Parse pParse, /* The parser context */
847 TriggerStep pStepList, /* List of statements inside the trigger body */
848 int orconf /* Conflict algorithm. (OE_Abort, etc) */
849 )
850 {
851 TriggerStep pStep;
852 Vdbe v = pParse.pVdbe;
853 sqlite3 db = pParse.db;
854  
855 Debug.Assert( pParse.pTriggerTab != null && pParse.pToplevel != null );
856 Debug.Assert( pStepList != null );
857 Debug.Assert( v != null );
858 for ( pStep = pStepList; pStep != null; pStep = pStep.pNext )
859 {
860 /* Figure out the ON CONFLICT policy that will be used for this step
861 ** of the trigger program. If the statement that caused this trigger
862 ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
863 ** the ON CONFLICT policy that was specified as part of the trigger
864 ** step statement. Example:
865 **
866 ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
867 ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
868 ** END;
869 **
870 ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy
871 ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
872 */
873 pParse.eOrconf = ( orconf == OE_Default ) ? pStep.orconf : (u8)orconf;
874  
875 switch ( pStep.op )
876 {
877 case TK_UPDATE:
878 {
879 sqlite3Update( pParse,
880 targetSrcList( pParse, pStep ),
881 sqlite3ExprListDup( db, pStep.pExprList, 0 ),
882 sqlite3ExprDup( db, pStep.pWhere, 0 ),
883 pParse.eOrconf
884 );
885 break;
886 }
887 case TK_INSERT:
888 {
889 sqlite3Insert( pParse,
890 targetSrcList( pParse, pStep ),
891 sqlite3ExprListDup( db, pStep.pExprList, 0 ),
892 sqlite3SelectDup( db, pStep.pSelect, 0 ),
893 sqlite3IdListDup( db, pStep.pIdList ),
894 pParse.eOrconf
895 );
896 break;
897 }
898 case TK_DELETE:
899 {
900 sqlite3DeleteFrom( pParse,
901 targetSrcList( pParse, pStep ),
902 sqlite3ExprDup( db, pStep.pWhere, 0 )
903 );
904 break;
905 }
906 default:
907 Debug.Assert( pStep.op == TK_SELECT );
908 {
909 SelectDest sDest = new SelectDest();
910 Select pSelect = sqlite3SelectDup( db, pStep.pSelect, 0 );
911 sqlite3SelectDestInit( sDest, SRT_Discard, 0 );
912 sqlite3Select( pParse, pSelect, ref sDest );
913 sqlite3SelectDelete( db, ref pSelect );
914 break;
915 }
916 }
917 if ( pStep.op != TK_SELECT )
918 {
919 sqlite3VdbeAddOp0( v, OP_ResetCount );
920 }
921 }
922  
923 return 0;
924 }
925  
926 #if SQLITE_DEBUG
927 /*
928 ** This function is used to add VdbeComment() annotations to a VDBE
929 ** program. It is not used in production code, only for debugging.
930 */
931 static string onErrorText( int onError )
932 {
933 switch ( onError )
934 {
935 case OE_Abort:
936 return "abort";
937 case OE_Rollback:
938 return "rollback";
939 case OE_Fail:
940 return "fail";
941 case OE_Replace:
942 return "replace";
943 case OE_Ignore:
944 return "ignore";
945 case OE_Default:
946 return "default";
947 }
948 return "n/a";
949 }
950 #endif
951  
952 /*
953 ** Parse context structure pFrom has just been used to create a sub-vdbe
954 ** (trigger program). If an error has occurred, transfer error information
955 ** from pFrom to pTo.
956 */
957 static void transferParseError( Parse pTo, Parse pFrom )
958 {
959 Debug.Assert( string.IsNullOrEmpty( pFrom.zErrMsg ) || pFrom.nErr != 0 );
960 Debug.Assert( string.IsNullOrEmpty( pTo.zErrMsg ) || pTo.nErr != 0 );
961 if ( pTo.nErr == 0 )
962 {
963 pTo.zErrMsg = pFrom.zErrMsg;
964 pTo.nErr = pFrom.nErr;
965 }
966 else
967 {
968 sqlite3DbFree( pFrom.db, ref pFrom.zErrMsg );
969 }
970 }
971  
972 /*
973 ** Create and populate a new TriggerPrg object with a sub-program
974 ** implementing trigger pTrigger with ON CONFLICT policy orconf.
975 */
976 static TriggerPrg codeRowTrigger(
977 Parse pParse, /* Current parse context */
978 Trigger pTrigger, /* Trigger to code */
979 Table pTab, /* The table pTrigger is attached to */
980 int orconf /* ON CONFLICT policy to code trigger program with */
981 )
982 {
983 Parse pTop = sqlite3ParseToplevel( pParse );
984 sqlite3 db = pParse.db; /* Database handle */
985 TriggerPrg pPrg; /* Value to return */
986 Expr pWhen = null; /* Duplicate of trigger WHEN expression */
987 Vdbe v; /* Temporary VM */
988 NameContext sNC; /* Name context for sub-vdbe */
989 SubProgram pProgram = null; /* Sub-vdbe for trigger program */
990 Parse pSubParse; /* Parse context for sub-vdbe */
991 int iEndTrigger = 0; /* Label to jump to if WHEN is false */
992  
993 Debug.Assert( pTrigger.zName == null || pTab == tableOfTrigger( pTrigger ) );
994 Debug.Assert( pTop.pVdbe != null );
995  
996 /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
997 ** are freed if an error occurs, link them into the Parse.pTriggerPrg
998 ** list of the top-level Parse object sooner rather than later. */
999 pPrg = new TriggerPrg();// sqlite3DbMallocZero( db, sizeof( TriggerPrg ) );
1000 //if ( null == pPrg ) return 0;
1001 pPrg.pNext = pTop.pTriggerPrg;
1002 pTop.pTriggerPrg = pPrg;
1003 pPrg.pProgram = pProgram = new SubProgram();// sqlite3DbMallocZero( db, sizeof( SubProgram ) );
1004 //if( null==pProgram ) return 0;
1005 sqlite3VdbeLinkSubProgram( pTop.pVdbe, pProgram );
1006 pPrg.pTrigger = pTrigger;
1007 pPrg.orconf = orconf;
1008 pPrg.aColmask[0] = 0xffffffff;
1009 pPrg.aColmask[1] = 0xffffffff;
1010  
1011  
1012 /* Allocate and populate a new Parse context to use for coding the
1013 ** trigger sub-program. */
1014 pSubParse = new Parse();// sqlite3StackAllocZero( db, sizeof( Parse ) );
1015 //if ( null == pSubParse ) return null;
1016 sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
1017 sNC.pParse = pSubParse;
1018 pSubParse.db = db;
1019 pSubParse.pTriggerTab = pTab;
1020 pSubParse.pToplevel = pTop;
1021 pSubParse.zAuthContext = pTrigger.zName;
1022 pSubParse.eTriggerOp = pTrigger.op;
1023 pSubParse.nQueryLoop = pParse.nQueryLoop;
1024  
1025 v = sqlite3GetVdbe( pSubParse );
1026 if ( v != null )
1027 {
1028 #if SQLITE_DEBUG
1029 VdbeComment( v, "Start: %s.%s (%s %s%s%s ON %s)",
1030 pTrigger.zName ?? string.Empty, onErrorText( orconf ),
1031 ( pTrigger.tr_tm == TRIGGER_BEFORE ? "BEFORE" : "AFTER" ),
1032 ( pTrigger.op == TK_UPDATE ? "UPDATE" : string.Empty ),
1033 ( pTrigger.op == TK_INSERT ? "INSERT" : string.Empty ),
1034 ( pTrigger.op == TK_DELETE ? "DELETE" : string.Empty ),
1035 pTab.zName
1036 );
1037 #endif
1038 #if !SQLITE_OMIT_TRACE
1039 sqlite3VdbeChangeP4( v, -1,
1040 sqlite3MPrintf( db, "-- TRIGGER %s", pTrigger.zName ), P4_DYNAMIC
1041 );
1042 #endif
1043  
1044 /* If one was specified, code the WHEN clause. If it evaluates to false
1045 ** (or NULL) the sub-vdbe is immediately halted by jumping to the
1046 ** OP_Halt inserted at the end of the program. */
1047 if ( pTrigger.pWhen != null )
1048 {
1049 pWhen = sqlite3ExprDup( db, pTrigger.pWhen, 0 );
1050 if ( SQLITE_OK == sqlite3ResolveExprNames( sNC, ref pWhen )
1051 //&& db.mallocFailed==0
1052 )
1053 {
1054 iEndTrigger = sqlite3VdbeMakeLabel( v );
1055 sqlite3ExprIfFalse( pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL );
1056 }
1057 sqlite3ExprDelete( db, ref pWhen );
1058 }
1059  
1060 /* Code the trigger program into the sub-vdbe. */
1061 codeTriggerProgram( pSubParse, pTrigger.step_list, orconf );
1062  
1063 /* Insert an OP_Halt at the end of the sub-program. */
1064 if ( iEndTrigger != 0 )
1065 {
1066 sqlite3VdbeResolveLabel( v, iEndTrigger );
1067 }
1068 sqlite3VdbeAddOp0( v, OP_Halt );
1069 #if SQLITE_DEBUG
1070 VdbeComment( v, "End: %s.%s", pTrigger.zName, onErrorText( orconf ) );
1071 #endif
1072 transferParseError( pParse, pSubParse );
1073 //if( db.mallocFailed==0 ){
1074 pProgram.aOp = sqlite3VdbeTakeOpArray( v, ref pProgram.nOp, ref pTop.nMaxArg );
1075 //}
1076 pProgram.nMem = pSubParse.nMem;
1077 pProgram.nCsr = pSubParse.nTab;
1078 pProgram.token = pTrigger.GetHashCode();
1079 pPrg.aColmask[0] = pSubParse.oldmask;
1080 pPrg.aColmask[1] = pSubParse.newmask;
1081 sqlite3VdbeDelete( ref v );
1082 }
1083  
1084 Debug.Assert( null == pSubParse.pAinc && null == pSubParse.pZombieTab );
1085 Debug.Assert( null == pSubParse.pTriggerPrg && 0 == pSubParse.nMaxArg );
1086 //sqlite3StackFree(db, pSubParse);
1087  
1088 return pPrg;
1089 }
1090  
1091 /*
1092 ** Return a pointer to a TriggerPrg object containing the sub-program for
1093 ** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
1094 ** TriggerPrg object exists, a new object is allocated and populated before
1095 ** being returned.
1096 */
1097 static TriggerPrg getRowTrigger(
1098 Parse pParse, /* Current parse context */
1099 Trigger pTrigger, /* Trigger to code */
1100 Table pTab, /* The table trigger pTrigger is attached to */
1101 int orconf /* ON CONFLICT algorithm. */
1102 )
1103 {
1104 Parse pRoot = sqlite3ParseToplevel( pParse );
1105 TriggerPrg pPrg;
1106  
1107 Debug.Assert( pTrigger.zName == null || pTab == tableOfTrigger( pTrigger ) );
1108  
1109 /* It may be that this trigger has already been coded (or is in the
1110 ** process of being coded). If this is the case, then an entry with
1111 ** a matching TriggerPrg.pTrigger field will be present somewhere
1112 ** in the Parse.pTriggerPrg list. Search for such an entry. */
1113 for ( pPrg = pRoot.pTriggerPrg;
1114 pPrg != null && ( pPrg.pTrigger != pTrigger || pPrg.orconf != orconf );
1115 pPrg = pPrg.pNext
1116 )
1117 ;
1118  
1119 /* If an existing TriggerPrg could not be located, create a new one. */
1120 if ( null == pPrg )
1121 {
1122 pPrg = codeRowTrigger( pParse, pTrigger, pTab, orconf );
1123 }
1124  
1125 return pPrg;
1126 }
1127  
1128 /*
1129 ** Generate code for the trigger program associated with trigger p on
1130 ** table pTab. The reg, orconf and ignoreJump parameters passed to this
1131 ** function are the same as those described in the header function for
1132 ** sqlite3CodeRowTrigger()
1133 */
1134 static void sqlite3CodeRowTriggerDirect(
1135 Parse pParse, /* Parse context */
1136 Trigger p, /* Trigger to code */
1137 Table pTab, /* The table to code triggers from */
1138 int reg, /* Reg array containing OLD.* and NEW.* values */
1139 int orconf, /* ON CONFLICT policy */
1140 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
1141 )
1142 {
1143 Vdbe v = sqlite3GetVdbe( pParse ); /* Main VM */
1144 TriggerPrg pPrg;
1145 pPrg = getRowTrigger( pParse, p, pTab, orconf );
1146 Debug.Assert( pPrg != null || pParse.nErr != 0 );//|| pParse.db.mallocFailed );
1147  
1148 /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
1149 ** is a pointer to the sub-vdbe containing the trigger program. */
1150 if ( pPrg != null )
1151 {
1152 bool bRecursive = ( !string.IsNullOrEmpty( p.zName ) && 0 == ( pParse.db.flags & SQLITE_RecTriggers ) );
1153 sqlite3VdbeAddOp3( v, OP_Program, reg, ignoreJump, ++pParse.nMem );
1154 sqlite3VdbeChangeP4( v, -1, pPrg.pProgram, P4_SUBPROGRAM );
1155 #if SQLITE_DEBUG
1156 VdbeComment
1157 ( v, "Call: %s.%s", ( !string.IsNullOrEmpty( p.zName ) ? p.zName : "fkey" ), onErrorText( orconf ) );
1158 #endif
1159  
1160 /* Set the P5 operand of the OP_Program instruction to non-zero if
1161 ** recursive invocation of this trigger program is disallowed. Recursive
1162 ** invocation is disallowed if (a) the sub-program is really a trigger,
1163 ** not a foreign key action, and (b) the flag to enable recursive triggers
1164 ** is clear. */
1165 sqlite3VdbeChangeP5( v, (u8)( bRecursive ? 1 : 0 ) );
1166 }
1167 }
1168  
1169 /*
1170 ** This is called to code the required FOR EACH ROW triggers for an operation
1171 ** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
1172 ** is given by the op paramater. The tr_tm parameter determines whether the
1173 ** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
1174 ** parameter pChanges is passed the list of columns being modified.
1175 **
1176 ** If there are no triggers that fire at the specified time for the specified
1177 ** operation on pTab, this function is a no-op.
1178 **
1179 ** The reg argument is the address of the first in an array of registers
1180 ** that contain the values substituted for the new.* and old.* references
1181 ** in the trigger program. If N is the number of columns in table pTab
1182 ** (a copy of pTab.nCol), then registers are populated as follows:
1183 **
1184 ** Register Contains
1185 ** ------------------------------------------------------
1186 ** reg+0 OLD.rowid
1187 ** reg+1 OLD.* value of left-most column of pTab
1188 ** ... ...
1189 ** reg+N OLD.* value of right-most column of pTab
1190 ** reg+N+1 NEW.rowid
1191 ** reg+N+2 OLD.* value of left-most column of pTab
1192 ** ... ...
1193 ** reg+N+N+1 NEW.* value of right-most column of pTab
1194 **
1195 ** For ON DELETE triggers, the registers containing the NEW.* values will
1196 ** never be accessed by the trigger program, so they are not allocated or
1197 ** populated by the caller (there is no data to populate them with anyway).
1198 ** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
1199 ** are never accessed, and so are not allocated by the caller. So, for an
1200 ** ON INSERT trigger, the value passed to this function as parameter reg
1201 ** is not a readable register, although registers (reg+N) through
1202 ** (reg+N+N+1) are.
1203 **
1204 ** Parameter orconf is the default conflict resolution algorithm for the
1205 ** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump
1206 ** is the instruction that control should jump to if a trigger program
1207 ** raises an IGNORE exception.
1208 */
1209 static void sqlite3CodeRowTrigger(
1210 Parse pParse, /* Parse context */
1211 Trigger pTrigger, /* List of triggers on table pTab */
1212 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
1213 ExprList pChanges, /* Changes list for any UPDATE OF triggers */
1214 int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
1215 Table pTab, /* The table to code triggers from */
1216 int reg, /* The first in an array of registers (see above) */
1217 int orconf, /* ON CONFLICT policy */
1218 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
1219 )
1220 {
1221 Trigger p; /* Used to iterate through pTrigger list */
1222  
1223 Debug.Assert( op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE );
1224 Debug.Assert( tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
1225 Debug.Assert( ( op == TK_UPDATE ) == ( pChanges != null ) );
1226  
1227 for ( p = pTrigger; p != null; p = p.pNext )
1228 {
1229  
1230 /* Sanity checking: The schema for the trigger and for the table are
1231 ** always defined. The trigger must be in the same schema as the table
1232 ** or else it must be a TEMP trigger. */
1233 Debug.Assert( p.pSchema != null );
1234 Debug.Assert( p.pTabSchema != null );
1235 Debug.Assert( p.pSchema == p.pTabSchema
1236 || p.pSchema == pParse.db.aDb[1].pSchema );
1237  
1238 /* Determine whether we should code this trigger */
1239 if ( p.op == op
1240 && p.tr_tm == tr_tm
1241 && checkColumnOverlap( p.pColumns, pChanges ) != 0
1242 )
1243 {
1244 sqlite3CodeRowTriggerDirect( pParse, p, pTab, reg, orconf, ignoreJump );
1245 }
1246 }
1247 }
1248  
1249 /*
1250 ** Triggers may access values stored in the old.* or new.* pseudo-table.
1251 ** This function returns a 32-bit bitmask indicating which columns of the
1252 ** old.* or new.* tables actually are used by triggers. This information
1253 ** may be used by the caller, for example, to avoid having to load the entire
1254 ** old.* record into memory when executing an UPDATE or DELETE command.
1255 **
1256 ** Bit 0 of the returned mask is set if the left-most column of the
1257 ** table may be accessed using an [old|new].<col> reference. Bit 1 is set if
1258 ** the second leftmost column value is required, and so on. If there
1259 ** are more than 32 columns in the table, and at least one of the columns
1260 ** with an index greater than 32 may be accessed, 0xffffffff is returned.
1261 **
1262 ** It is not possible to determine if the old.rowid or new.rowid column is
1263 ** accessed by triggers. The caller must always assume that it is.
1264 **
1265 ** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned
1266 ** applies to the old.* table. If 1, the new.* table.
1267 **
1268 ** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE
1269 ** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only
1270 ** included in the returned mask if the TRIGGER_BEFORE bit is set in the
1271 ** tr_tm parameter. Similarly, values accessed by AFTER triggers are only
1272 ** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm.
1273 */
1274 static u32 sqlite3TriggerColmask(
1275 Parse pParse, /* Parse context */
1276 Trigger pTrigger, /* List of triggers on table pTab */
1277 ExprList pChanges, /* Changes list for any UPDATE OF triggers */
1278 int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */
1279 int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
1280 Table pTab, /* The table to code triggers from */
1281 int orconf /* Default ON CONFLICT policy for trigger steps */
1282 )
1283 {
1284 int op = pChanges != null ? TK_UPDATE : TK_DELETE;
1285 u32 mask = 0;
1286 Trigger p;
1287  
1288 Debug.Assert( isNew == 1 || isNew == 0 );
1289 for ( p = pTrigger; p != null; p = p.pNext )
1290 {
1291 if ( p.op == op && ( tr_tm & p.tr_tm ) != 0
1292 && checkColumnOverlap( p.pColumns, pChanges ) != 0
1293 )
1294 {
1295 TriggerPrg pPrg;
1296 pPrg = getRowTrigger( pParse, p, pTab, orconf );
1297 if ( pPrg != null )
1298 {
1299 mask |= pPrg.aColmask[isNew];
1300 }
1301 }
1302 }
1303  
1304 return mask;
1305 }
1306 #endif // * !SQLITE_OMIT_TRIGGER) */
1307  
1308 }
1309 }