Annotation of embedaddon/sqlite3/src/delete.c, revision 1.1.1.1
1.1 misho 1: /*
2: ** 2001 September 15
3: **
4: ** The author disclaims copyright to this source code. In place of
5: ** a legal notice, here is a blessing:
6: **
7: ** May you do good and not evil.
8: ** May you find forgiveness for yourself and forgive others.
9: ** May you share freely, never taking more than you give.
10: **
11: *************************************************************************
12: ** This file contains C code routines that are called by the parser
13: ** in order to generate code for DELETE FROM statements.
14: */
15: #include "sqliteInt.h"
16:
17: /*
18: ** While a SrcList can in general represent multiple tables and subqueries
19: ** (as in the FROM clause of a SELECT statement) in this case it contains
20: ** the name of a single table, as one might find in an INSERT, DELETE,
21: ** or UPDATE statement. Look up that table in the symbol table and
22: ** return a pointer. Set an error message and return NULL if the table
23: ** name is not found or if any other error occurs.
24: **
25: ** The following fields are initialized appropriate in pSrc:
26: **
27: ** pSrc->a[0].pTab Pointer to the Table object
28: ** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
29: **
30: */
31: Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
32: struct SrcList_item *pItem = pSrc->a;
33: Table *pTab;
34: assert( pItem && pSrc->nSrc==1 );
35: pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
36: sqlite3DeleteTable(pParse->db, pItem->pTab);
37: pItem->pTab = pTab;
38: if( pTab ){
39: pTab->nRef++;
40: }
41: if( sqlite3IndexedByLookup(pParse, pItem) ){
42: pTab = 0;
43: }
44: return pTab;
45: }
46:
47: /*
48: ** Check to make sure the given table is writable. If it is not
49: ** writable, generate an error message and return 1. If it is
50: ** writable return 0;
51: */
52: int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
53: /* A table is not writable under the following circumstances:
54: **
55: ** 1) It is a virtual table and no implementation of the xUpdate method
56: ** has been provided, or
57: ** 2) It is a system table (i.e. sqlite_master), this call is not
58: ** part of a nested parse and writable_schema pragma has not
59: ** been specified.
60: **
61: ** In either case leave an error message in pParse and return non-zero.
62: */
63: if( ( IsVirtual(pTab)
64: && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
65: || ( (pTab->tabFlags & TF_Readonly)!=0
66: && (pParse->db->flags & SQLITE_WriteSchema)==0
67: && pParse->nested==0 )
68: ){
69: sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
70: return 1;
71: }
72:
73: #ifndef SQLITE_OMIT_VIEW
74: if( !viewOk && pTab->pSelect ){
75: sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
76: return 1;
77: }
78: #endif
79: return 0;
80: }
81:
82:
83: #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
84: /*
85: ** Evaluate a view and store its result in an ephemeral table. The
86: ** pWhere argument is an optional WHERE clause that restricts the
87: ** set of rows in the view that are to be added to the ephemeral table.
88: */
89: void sqlite3MaterializeView(
90: Parse *pParse, /* Parsing context */
91: Table *pView, /* View definition */
92: Expr *pWhere, /* Optional WHERE clause to be added */
93: int iCur /* Cursor number for ephemerial table */
94: ){
95: SelectDest dest;
96: Select *pDup;
97: sqlite3 *db = pParse->db;
98:
99: pDup = sqlite3SelectDup(db, pView->pSelect, 0);
100: if( pWhere ){
101: SrcList *pFrom;
102:
103: pWhere = sqlite3ExprDup(db, pWhere, 0);
104: pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
105: if( pFrom ){
106: assert( pFrom->nSrc==1 );
107: pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName);
108: pFrom->a[0].pSelect = pDup;
109: assert( pFrom->a[0].pOn==0 );
110: assert( pFrom->a[0].pUsing==0 );
111: }else{
112: sqlite3SelectDelete(db, pDup);
113: }
114: pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
115: }
116: sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
117: sqlite3Select(pParse, pDup, &dest);
118: sqlite3SelectDelete(db, pDup);
119: }
120: #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
121:
122: #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
123: /*
124: ** Generate an expression tree to implement the WHERE, ORDER BY,
125: ** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
126: **
127: ** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
128: ** \__________________________/
129: ** pLimitWhere (pInClause)
130: */
131: Expr *sqlite3LimitWhere(
132: Parse *pParse, /* The parser context */
133: SrcList *pSrc, /* the FROM clause -- which tables to scan */
134: Expr *pWhere, /* The WHERE clause. May be null */
135: ExprList *pOrderBy, /* The ORDER BY clause. May be null */
136: Expr *pLimit, /* The LIMIT clause. May be null */
137: Expr *pOffset, /* The OFFSET clause. May be null */
138: char *zStmtType /* Either DELETE or UPDATE. For error messages. */
139: ){
140: Expr *pWhereRowid = NULL; /* WHERE rowid .. */
141: Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
142: Expr *pSelectRowid = NULL; /* SELECT rowid ... */
143: ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
144: SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
145: Select *pSelect = NULL; /* Complete SELECT tree */
146:
147: /* Check that there isn't an ORDER BY without a LIMIT clause.
148: */
149: if( pOrderBy && (pLimit == 0) ) {
150: sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
151: goto limit_where_cleanup_2;
152: }
153:
154: /* We only need to generate a select expression if there
155: ** is a limit/offset term to enforce.
156: */
157: if( pLimit == 0 ) {
158: /* if pLimit is null, pOffset will always be null as well. */
159: assert( pOffset == 0 );
160: return pWhere;
161: }
162:
163: /* Generate a select expression tree to enforce the limit/offset
164: ** term for the DELETE or UPDATE statement. For example:
165: ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
166: ** becomes:
167: ** DELETE FROM table_a WHERE rowid IN (
168: ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
169: ** );
170: */
171:
172: pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
173: if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
174: pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
175: if( pEList == 0 ) goto limit_where_cleanup_2;
176:
177: /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
178: ** and the SELECT subtree. */
179: pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
180: if( pSelectSrc == 0 ) {
181: sqlite3ExprListDelete(pParse->db, pEList);
182: goto limit_where_cleanup_2;
183: }
184:
185: /* generate the SELECT expression tree. */
186: pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
187: pOrderBy,0,pLimit,pOffset);
188: if( pSelect == 0 ) return 0;
189:
190: /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
191: pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
192: if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
193: pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
194: if( pInClause == 0 ) goto limit_where_cleanup_1;
195:
196: pInClause->x.pSelect = pSelect;
197: pInClause->flags |= EP_xIsSelect;
198: sqlite3ExprSetHeight(pParse, pInClause);
199: return pInClause;
200:
201: /* something went wrong. clean up anything allocated. */
202: limit_where_cleanup_1:
203: sqlite3SelectDelete(pParse->db, pSelect);
204: return 0;
205:
206: limit_where_cleanup_2:
207: sqlite3ExprDelete(pParse->db, pWhere);
208: sqlite3ExprListDelete(pParse->db, pOrderBy);
209: sqlite3ExprDelete(pParse->db, pLimit);
210: sqlite3ExprDelete(pParse->db, pOffset);
211: return 0;
212: }
213: #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
214:
215: /*
216: ** Generate code for a DELETE FROM statement.
217: **
218: ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
219: ** \________/ \________________/
220: ** pTabList pWhere
221: */
222: void sqlite3DeleteFrom(
223: Parse *pParse, /* The parser context */
224: SrcList *pTabList, /* The table from which we should delete things */
225: Expr *pWhere /* The WHERE clause. May be null */
226: ){
227: Vdbe *v; /* The virtual database engine */
228: Table *pTab; /* The table from which records will be deleted */
229: const char *zDb; /* Name of database holding pTab */
230: int end, addr = 0; /* A couple addresses of generated code */
231: int i; /* Loop counter */
232: WhereInfo *pWInfo; /* Information about the WHERE clause */
233: Index *pIdx; /* For looping over indices of the table */
234: int iCur; /* VDBE Cursor number for pTab */
235: sqlite3 *db; /* Main database structure */
236: AuthContext sContext; /* Authorization context */
237: NameContext sNC; /* Name context to resolve expressions in */
238: int iDb; /* Database number */
239: int memCnt = -1; /* Memory cell used for change counting */
240: int rcauth; /* Value returned by authorization callback */
241:
242: #ifndef SQLITE_OMIT_TRIGGER
243: int isView; /* True if attempting to delete from a view */
244: Trigger *pTrigger; /* List of table triggers, if required */
245: #endif
246:
247: memset(&sContext, 0, sizeof(sContext));
248: db = pParse->db;
249: if( pParse->nErr || db->mallocFailed ){
250: goto delete_from_cleanup;
251: }
252: assert( pTabList->nSrc==1 );
253:
254: /* Locate the table which we want to delete. This table has to be
255: ** put in an SrcList structure because some of the subroutines we
256: ** will be calling are designed to work with multiple tables and expect
257: ** an SrcList* parameter instead of just a Table* parameter.
258: */
259: pTab = sqlite3SrcListLookup(pParse, pTabList);
260: if( pTab==0 ) goto delete_from_cleanup;
261:
262: /* Figure out if we have any triggers and if the table being
263: ** deleted from is a view
264: */
265: #ifndef SQLITE_OMIT_TRIGGER
266: pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
267: isView = pTab->pSelect!=0;
268: #else
269: # define pTrigger 0
270: # define isView 0
271: #endif
272: #ifdef SQLITE_OMIT_VIEW
273: # undef isView
274: # define isView 0
275: #endif
276:
277: /* If pTab is really a view, make sure it has been initialized.
278: */
279: if( sqlite3ViewGetColumnNames(pParse, pTab) ){
280: goto delete_from_cleanup;
281: }
282:
283: if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
284: goto delete_from_cleanup;
285: }
286: iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
287: assert( iDb<db->nDb );
288: zDb = db->aDb[iDb].zName;
289: rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
290: assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
291: if( rcauth==SQLITE_DENY ){
292: goto delete_from_cleanup;
293: }
294: assert(!isView || pTrigger);
295:
296: /* Assign cursor number to the table and all its indices.
297: */
298: assert( pTabList->nSrc==1 );
299: iCur = pTabList->a[0].iCursor = pParse->nTab++;
300: for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
301: pParse->nTab++;
302: }
303:
304: /* Start the view context
305: */
306: if( isView ){
307: sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
308: }
309:
310: /* Begin generating code.
311: */
312: v = sqlite3GetVdbe(pParse);
313: if( v==0 ){
314: goto delete_from_cleanup;
315: }
316: if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
317: sqlite3BeginWriteOperation(pParse, 1, iDb);
318:
319: /* If we are trying to delete from a view, realize that view into
320: ** a ephemeral table.
321: */
322: #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
323: if( isView ){
324: sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
325: }
326: #endif
327:
328: /* Resolve the column names in the WHERE clause.
329: */
330: memset(&sNC, 0, sizeof(sNC));
331: sNC.pParse = pParse;
332: sNC.pSrcList = pTabList;
333: if( sqlite3ResolveExprNames(&sNC, pWhere) ){
334: goto delete_from_cleanup;
335: }
336:
337: /* Initialize the counter of the number of rows deleted, if
338: ** we are counting rows.
339: */
340: if( db->flags & SQLITE_CountRows ){
341: memCnt = ++pParse->nMem;
342: sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
343: }
344:
345: #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
346: /* Special case: A DELETE without a WHERE clause deletes everything.
347: ** It is easier just to erase the whole table. Prior to version 3.6.5,
348: ** this optimization caused the row change count (the value returned by
349: ** API function sqlite3_count_changes) to be set incorrectly. */
350: if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
351: && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
352: ){
353: assert( !isView );
354: sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
355: pTab->zName, P4_STATIC);
356: for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
357: assert( pIdx->pSchema==pTab->pSchema );
358: sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
359: }
360: }else
361: #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
362: /* The usual case: There is a WHERE clause so we have to scan through
363: ** the table and pick which records to delete.
364: */
365: {
366: int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
367: int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
368: int regRowid; /* Actual register containing rowids */
369:
370: /* Collect rowids of every row to be deleted.
371: */
372: sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
373: pWInfo = sqlite3WhereBegin(
374: pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
375: );
376: if( pWInfo==0 ) goto delete_from_cleanup;
377: regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
378: sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
379: if( db->flags & SQLITE_CountRows ){
380: sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
381: }
382: sqlite3WhereEnd(pWInfo);
383:
384: /* Delete every item whose key was written to the list during the
385: ** database scan. We have to delete items after the scan is complete
386: ** because deleting an item can change the scan order. */
387: end = sqlite3VdbeMakeLabel(v);
388:
389: /* Unless this is a view, open cursors for the table we are
390: ** deleting from and all its indices. If this is a view, then the
391: ** only effect this statement has is to fire the INSTEAD OF
392: ** triggers. */
393: if( !isView ){
394: sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
395: }
396:
397: addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
398:
399: /* Delete the row */
400: #ifndef SQLITE_OMIT_VIRTUALTABLE
401: if( IsVirtual(pTab) ){
402: const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
403: sqlite3VtabMakeWritable(pParse, pTab);
404: sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
405: sqlite3VdbeChangeP5(v, OE_Abort);
406: sqlite3MayAbort(pParse);
407: }else
408: #endif
409: {
410: int count = (pParse->nested==0); /* True to count changes */
411: sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default);
412: }
413:
414: /* End of the delete loop */
415: sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
416: sqlite3VdbeResolveLabel(v, end);
417:
418: /* Close the cursors open on the table and its indexes. */
419: if( !isView && !IsVirtual(pTab) ){
420: for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
421: sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);
422: }
423: sqlite3VdbeAddOp1(v, OP_Close, iCur);
424: }
425: }
426:
427: /* Update the sqlite_sequence table by storing the content of the
428: ** maximum rowid counter values recorded while inserting into
429: ** autoincrement tables.
430: */
431: if( pParse->nested==0 && pParse->pTriggerTab==0 ){
432: sqlite3AutoincrementEnd(pParse);
433: }
434:
435: /* Return the number of rows that were deleted. If this routine is
436: ** generating code because of a call to sqlite3NestedParse(), do not
437: ** invoke the callback function.
438: */
439: if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){
440: sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
441: sqlite3VdbeSetNumCols(v, 1);
442: sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
443: }
444:
445: delete_from_cleanup:
446: sqlite3AuthContextPop(&sContext);
447: sqlite3SrcListDelete(db, pTabList);
448: sqlite3ExprDelete(db, pWhere);
449: return;
450: }
451: /* Make sure "isView" and other macros defined above are undefined. Otherwise
452: ** thely may interfere with compilation of other functions in this file
453: ** (or in another file, if this file becomes part of the amalgamation). */
454: #ifdef isView
455: #undef isView
456: #endif
457: #ifdef pTrigger
458: #undef pTrigger
459: #endif
460:
461: /*
462: ** This routine generates VDBE code that causes a single row of a
463: ** single table to be deleted.
464: **
465: ** The VDBE must be in a particular state when this routine is called.
466: ** These are the requirements:
467: **
468: ** 1. A read/write cursor pointing to pTab, the table containing the row
469: ** to be deleted, must be opened as cursor number $iCur.
470: **
471: ** 2. Read/write cursors for all indices of pTab must be open as
472: ** cursor number base+i for the i-th index.
473: **
474: ** 3. The record number of the row to be deleted must be stored in
475: ** memory cell iRowid.
476: **
477: ** This routine generates code to remove both the table record and all
478: ** index entries that point to that record.
479: */
480: void sqlite3GenerateRowDelete(
481: Parse *pParse, /* Parsing context */
482: Table *pTab, /* Table containing the row to be deleted */
483: int iCur, /* Cursor number for the table */
484: int iRowid, /* Memory cell that contains the rowid to delete */
485: int count, /* If non-zero, increment the row change counter */
486: Trigger *pTrigger, /* List of triggers to (potentially) fire */
487: int onconf /* Default ON CONFLICT policy for triggers */
488: ){
489: Vdbe *v = pParse->pVdbe; /* Vdbe */
490: int iOld = 0; /* First register in OLD.* array */
491: int iLabel; /* Label resolved to end of generated code */
492:
493: /* Vdbe is guaranteed to have been allocated by this stage. */
494: assert( v );
495:
496: /* Seek cursor iCur to the row to delete. If this row no longer exists
497: ** (this can happen if a trigger program has already deleted it), do
498: ** not attempt to delete it or fire any DELETE triggers. */
499: iLabel = sqlite3VdbeMakeLabel(v);
500: sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
501:
502: /* If there are any triggers to fire, allocate a range of registers to
503: ** use for the old.* references in the triggers. */
504: if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
505: u32 mask; /* Mask of OLD.* columns in use */
506: int iCol; /* Iterator used while populating OLD.* */
507:
508: /* TODO: Could use temporary registers here. Also could attempt to
509: ** avoid copying the contents of the rowid register. */
510: mask = sqlite3TriggerColmask(
511: pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
512: );
513: mask |= sqlite3FkOldmask(pParse, pTab);
514: iOld = pParse->nMem+1;
515: pParse->nMem += (1 + pTab->nCol);
516:
517: /* Populate the OLD.* pseudo-table register array. These values will be
518: ** used by any BEFORE and AFTER triggers that exist. */
519: sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
520: for(iCol=0; iCol<pTab->nCol; iCol++){
521: if( mask==0xffffffff || mask&(1<<iCol) ){
522: sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
523: }
524: }
525:
526: /* Invoke BEFORE DELETE trigger programs. */
527: sqlite3CodeRowTrigger(pParse, pTrigger,
528: TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
529: );
530:
531: /* Seek the cursor to the row to be deleted again. It may be that
532: ** the BEFORE triggers coded above have already removed the row
533: ** being deleted. Do not attempt to delete the row a second time, and
534: ** do not fire AFTER triggers. */
535: sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
536:
537: /* Do FK processing. This call checks that any FK constraints that
538: ** refer to this table (i.e. constraints attached to other tables)
539: ** are not violated by deleting this row. */
540: sqlite3FkCheck(pParse, pTab, iOld, 0);
541: }
542:
543: /* Delete the index and table entries. Skip this step if pTab is really
544: ** a view (in which case the only effect of the DELETE statement is to
545: ** fire the INSTEAD OF triggers). */
546: if( pTab->pSelect==0 ){
547: sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
548: sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
549: if( count ){
550: sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
551: }
552: }
553:
554: /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
555: ** handle rows (possibly in other tables) that refer via a foreign key
556: ** to the row just deleted. */
557: sqlite3FkActions(pParse, pTab, 0, iOld);
558:
559: /* Invoke AFTER DELETE trigger programs. */
560: sqlite3CodeRowTrigger(pParse, pTrigger,
561: TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
562: );
563:
564: /* Jump here if the row had already been deleted before any BEFORE
565: ** trigger programs were invoked. Or if a trigger program throws a
566: ** RAISE(IGNORE) exception. */
567: sqlite3VdbeResolveLabel(v, iLabel);
568: }
569:
570: /*
571: ** This routine generates VDBE code that causes the deletion of all
572: ** index entries associated with a single row of a single table.
573: **
574: ** The VDBE must be in a particular state when this routine is called.
575: ** These are the requirements:
576: **
577: ** 1. A read/write cursor pointing to pTab, the table containing the row
578: ** to be deleted, must be opened as cursor number "iCur".
579: **
580: ** 2. Read/write cursors for all indices of pTab must be open as
581: ** cursor number iCur+i for the i-th index.
582: **
583: ** 3. The "iCur" cursor must be pointing to the row that is to be
584: ** deleted.
585: */
586: void sqlite3GenerateRowIndexDelete(
587: Parse *pParse, /* Parsing and code generating context */
588: Table *pTab, /* Table containing the row to be deleted */
589: int iCur, /* Cursor number for the table */
590: int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
591: ){
592: int i;
593: Index *pIdx;
594: int r1;
595:
596: for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
597: if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
598: r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
599: sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
600: }
601: }
602:
603: /*
604: ** Generate code that will assemble an index key and put it in register
605: ** regOut. The key with be for index pIdx which is an index on pTab.
606: ** iCur is the index of a cursor open on the pTab table and pointing to
607: ** the entry that needs indexing.
608: **
609: ** Return a register number which is the first in a block of
610: ** registers that holds the elements of the index key. The
611: ** block of registers has already been deallocated by the time
612: ** this routine returns.
613: */
614: int sqlite3GenerateIndexKey(
615: Parse *pParse, /* Parsing context */
616: Index *pIdx, /* The index for which to generate a key */
617: int iCur, /* Cursor number for the pIdx->pTable table */
618: int regOut, /* Write the new index key to this register */
619: int doMakeRec /* Run the OP_MakeRecord instruction if true */
620: ){
621: Vdbe *v = pParse->pVdbe;
622: int j;
623: Table *pTab = pIdx->pTable;
624: int regBase;
625: int nCol;
626:
627: nCol = pIdx->nColumn;
628: regBase = sqlite3GetTempRange(pParse, nCol+1);
629: sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
630: for(j=0; j<nCol; j++){
631: int idx = pIdx->aiColumn[j];
632: if( idx==pTab->iPKey ){
633: sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
634: }else{
635: sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
636: sqlite3ColumnDefault(v, pTab, idx, -1);
637: }
638: }
639: if( doMakeRec ){
640: const char *zAff;
641: if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
642: zAff = 0;
643: }else{
644: zAff = sqlite3IndexAffinityStr(v, pIdx);
645: }
646: sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
647: sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
648: }
649: sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
650: return regBase;
651: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>