| Index: third_party/sqlite/src/src/delete.c
 | 
| diff --git a/third_party/sqlite/src/src/delete.c b/third_party/sqlite/src/src/delete.c
 | 
| index 7e5b7bfc4f643f9e30a90c51b7df2b93e8081dec..bd7ac3d1f38c9b2fffe9d178f0a65921a2c34597 100644
 | 
| --- a/third_party/sqlite/src/src/delete.c
 | 
| +++ b/third_party/sqlite/src/src/delete.c
 | 
| @@ -11,8 +11,6 @@
 | 
|  *************************************************************************
 | 
|  ** This file contains C code routines that are called by the parser
 | 
|  ** in order to generate code for DELETE FROM statements.
 | 
| -**
 | 
| -** $Id: delete.c,v 1.207 2009/08/08 18:01:08 drh Exp $
 | 
|  */
 | 
|  #include "sqliteInt.h"
 | 
|  
 | 
| @@ -26,7 +24,7 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
 | 
|    Table *pTab;
 | 
|    assert( pItem && pSrc->nSrc==1 );
 | 
|    pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
 | 
| -  sqlite3DeleteTable(pItem->pTab);
 | 
| +  sqlite3DeleteTable(pParse->db, pItem->pTab);
 | 
|    pItem->pTab = pTab;
 | 
|    if( pTab ){
 | 
|      pTab->nRef++;
 | 
| @@ -308,7 +306,7 @@ void sqlite3DeleteFrom(
 | 
|      goto delete_from_cleanup;
 | 
|    }
 | 
|    if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
 | 
| -  sqlite3BeginWriteOperation(pParse, (pTrigger?1:0), iDb);
 | 
| +  sqlite3BeginWriteOperation(pParse, 1, iDb);
 | 
|  
 | 
|    /* If we are trying to delete from a view, realize that view into
 | 
|    ** a ephemeral table.
 | 
| @@ -341,7 +339,9 @@ void sqlite3DeleteFrom(
 | 
|    ** It is easier just to erase the whole table. Prior to version 3.6.5,
 | 
|    ** this optimization caused the row change count (the value returned by 
 | 
|    ** API function sqlite3_count_changes) to be set incorrectly.  */
 | 
| -  if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) ){
 | 
| +  if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
 | 
| +   && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
 | 
| +  ){
 | 
|      assert( !isView );
 | 
|      sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
 | 
|                        pTab->zName, P4_STATIC);
 | 
| @@ -364,7 +364,7 @@ void sqlite3DeleteFrom(
 | 
|      sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
 | 
|      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
 | 
|      if( pWInfo==0 ) goto delete_from_cleanup;
 | 
| -    regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
 | 
| +    regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
 | 
|      sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
 | 
|      if( db->flags & SQLITE_CountRows ){
 | 
|        sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
 | 
| @@ -437,6 +437,15 @@ delete_from_cleanup:
 | 
|    sqlite3ExprDelete(db, pWhere);
 | 
|    return;
 | 
|  }
 | 
| +/* Make sure "isView" and other macros defined above are undefined. Otherwise
 | 
| +** thely may interfere with compilation of other functions in this file
 | 
| +** (or in another file, if this file becomes part of the amalgamation).  */
 | 
| +#ifdef isView
 | 
| + #undef isView
 | 
| +#endif
 | 
| +#ifdef pTrigger
 | 
| + #undef pTrigger
 | 
| +#endif
 | 
|  
 | 
|  /*
 | 
|  ** This routine generates VDBE code that causes a single row of a
 | 
| @@ -446,7 +455,7 @@ delete_from_cleanup:
 | 
|  ** These are the requirements:
 | 
|  **
 | 
|  **   1.  A read/write cursor pointing to pTab, the table containing the row
 | 
| -**       to be deleted, must be opened as cursor number "base".
 | 
| +**       to be deleted, must be opened as cursor number $iCur.
 | 
|  **
 | 
|  **   2.  Read/write cursors for all indices of pTab must be open as
 | 
|  **       cursor number base+i for the i-th index.
 | 
| @@ -481,13 +490,16 @@ void sqlite3GenerateRowDelete(
 | 
|   
 | 
|    /* If there are any triggers to fire, allocate a range of registers to
 | 
|    ** use for the old.* references in the triggers.  */
 | 
| -  if( pTrigger ){
 | 
| +  if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
 | 
|      u32 mask;                     /* Mask of OLD.* columns in use */
 | 
|      int iCol;                     /* Iterator used while populating OLD.* */
 | 
|  
 | 
|      /* TODO: Could use temporary registers here. Also could attempt to
 | 
|      ** avoid copying the contents of the rowid register.  */
 | 
| -    mask = sqlite3TriggerOldmask(pParse, pTrigger, TK_DELETE, 0, pTab, onconf);
 | 
| +    mask = sqlite3TriggerColmask(
 | 
| +        pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
 | 
| +    );
 | 
| +    mask |= sqlite3FkOldmask(pParse, pTab);
 | 
|      iOld = pParse->nMem+1;
 | 
|      pParse->nMem += (1 + pTab->nCol);
 | 
|  
 | 
| @@ -496,15 +508,13 @@ void sqlite3GenerateRowDelete(
 | 
|      sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
 | 
|      for(iCol=0; iCol<pTab->nCol; iCol++){
 | 
|        if( mask==0xffffffff || mask&(1<<iCol) ){
 | 
| -        int iTarget = iOld + iCol + 1;
 | 
| -        sqlite3VdbeAddOp3(v, OP_Column, iCur, iCol, iTarget);
 | 
| -        sqlite3ColumnDefault(v, pTab, iCol, iTarget);
 | 
| +        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
 | 
|        }
 | 
|      }
 | 
|  
 | 
| -    /* Invoke any BEFORE trigger programs */
 | 
| +    /* Invoke BEFORE DELETE trigger programs. */
 | 
|      sqlite3CodeRowTrigger(pParse, pTrigger, 
 | 
| -        TK_DELETE, 0, TRIGGER_BEFORE, pTab, -1, iOld, onconf, iLabel
 | 
| +        TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
 | 
|      );
 | 
|  
 | 
|      /* Seek the cursor to the row to be deleted again. It may be that
 | 
| @@ -512,6 +522,11 @@ void sqlite3GenerateRowDelete(
 | 
|      ** being deleted. Do not attempt to delete the row a second time, and 
 | 
|      ** do not fire AFTER triggers.  */
 | 
|      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
 | 
| +
 | 
| +    /* Do FK processing. This call checks that any FK constraints that
 | 
| +    ** refer to this table (i.e. constraints attached to other tables) 
 | 
| +    ** are not violated by deleting this row.  */
 | 
| +    sqlite3FkCheck(pParse, pTab, iOld, 0);
 | 
|    }
 | 
|  
 | 
|    /* Delete the index and table entries. Skip this step if pTab is really
 | 
| @@ -525,12 +540,15 @@ void sqlite3GenerateRowDelete(
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  /* Invoke AFTER triggers. */
 | 
| -  if( pTrigger ){
 | 
| -    sqlite3CodeRowTrigger(pParse, pTrigger, 
 | 
| -        TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, iOld, onconf, iLabel
 | 
| -    );
 | 
| -  }
 | 
| +  /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
 | 
| +  ** handle rows (possibly in other tables) that refer via a foreign key
 | 
| +  ** to the row just deleted. */ 
 | 
| +  sqlite3FkActions(pParse, pTab, 0, iOld);
 | 
| +
 | 
| +  /* Invoke AFTER DELETE trigger programs. */
 | 
| +  sqlite3CodeRowTrigger(pParse, pTrigger, 
 | 
| +      TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
 | 
| +  );
 | 
|  
 | 
|    /* Jump here if the row had already been deleted before any BEFORE
 | 
|    ** trigger programs were invoked. Or if a trigger program throws a 
 | 
| @@ -610,13 +628,7 @@ int sqlite3GenerateIndexKey(
 | 
|    if( doMakeRec ){
 | 
|      sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
 | 
|      sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
 | 
| -    sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
 | 
|    }
 | 
|    sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
 | 
|    return regBase;
 | 
|  }
 | 
| -
 | 
| -/* Make sure "isView" gets undefined in case this file becomes part of
 | 
| -** the amalgamation - so that subsequent files do not see isView as a
 | 
| -** macro. */
 | 
| -#undef isView
 | 
| 
 |