| Index: third_party/sqlite/src/src/insert.c
|
| diff --git a/third_party/sqlite/src/src/insert.c b/third_party/sqlite/src/src/insert.c
|
| index f27d50f23eb344cc1d8dce4a8e316d5bc234a22e..adf6ef2ed41eb2ad38b224c5cc32c91c4f61772d 100644
|
| --- a/third_party/sqlite/src/src/insert.c
|
| +++ b/third_party/sqlite/src/src/insert.c
|
| @@ -11,8 +11,6 @@
|
| *************************************************************************
|
| ** This file contains C code routines that are called by the parser
|
| ** to handle INSERT statements in SQLite.
|
| -**
|
| -** $Id: insert.c,v 1.270 2009/07/24 17:58:53 danielk1977 Exp $
|
| */
|
| #include "sqliteInt.h"
|
|
|
| @@ -69,7 +67,7 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
| int n;
|
| Table *pTab = pIdx->pTable;
|
| sqlite3 *db = sqlite3VdbeDb(v);
|
| - pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2);
|
| + pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2);
|
| if( !pIdx->zColAff ){
|
| db->mallocFailed = 1;
|
| return 0;
|
| @@ -111,7 +109,7 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
|
| int i;
|
| sqlite3 *db = sqlite3VdbeDb(v);
|
|
|
| - zColAff = (char *)sqlite3Malloc(pTab->nCol+1);
|
| + zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
|
| if( !zColAff ){
|
| db->mallocFailed = 1;
|
| return;
|
| @@ -729,7 +727,7 @@ void sqlite3Insert(
|
| }else{
|
| sqlite3ErrorMsg(pParse, "table %S has no column named %s",
|
| pTabList, 0, pColumn->a[i].zName);
|
| - pParse->nErr++;
|
| + pParse->checkSchema = 1;
|
| goto insert_cleanup;
|
| }
|
| }
|
| @@ -848,7 +846,7 @@ void sqlite3Insert(
|
| if( pColumn->a[j].idx==i ) break;
|
| }
|
| }
|
| - if( pColumn && j>=pColumn->nId ){
|
| + if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){
|
| sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
|
| }else if( useTempTable ){
|
| sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
|
| @@ -870,7 +868,7 @@ void sqlite3Insert(
|
|
|
| /* Fire BEFORE or INSTEAD OF triggers */
|
| sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
|
| - pTab, -1, regCols-pTab->nCol-1, onError, endOfLoop);
|
| + pTab, regCols-pTab->nCol-1, onError, endOfLoop);
|
|
|
| sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
|
| }
|
| @@ -979,6 +977,7 @@ void sqlite3Insert(
|
| sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
|
| keyColumn>=0, 0, onError, endOfLoop, &isReplace
|
| );
|
| + sqlite3FkCheck(pParse, pTab, 0, regIns);
|
| sqlite3CompleteInsertion(
|
| pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0
|
| );
|
| @@ -994,7 +993,7 @@ void sqlite3Insert(
|
| if( pTrigger ){
|
| /* Code AFTER triggers */
|
| sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
|
| - pTab, -1, regData-2-pTab->nCol, onError, endOfLoop);
|
| + pTab, regData-2-pTab->nCol, onError, endOfLoop);
|
| }
|
|
|
| /* The bottom of the main insertion loop, if the data source
|
| @@ -1046,6 +1045,20 @@ insert_cleanup:
|
| sqlite3DbFree(db, aRegIdx);
|
| }
|
|
|
| +/* 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
|
| +#ifdef tmask
|
| + #undef tmask
|
| +#endif
|
| +
|
| +
|
| /*
|
| ** Generate code to do constraint checks prior to an INSERT or an UPDATE.
|
| **
|
| @@ -1207,6 +1220,7 @@ void sqlite3GenerateConstraintChecks(
|
| if( onError==OE_Ignore ){
|
| sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
| }else{
|
| + if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
|
| sqlite3HaltConstraint(pParse, onError, 0, 0);
|
| }
|
| sqlite3VdbeResolveLabel(v, allOk);
|
| @@ -1225,58 +1239,71 @@ void sqlite3GenerateConstraintChecks(
|
| onError = OE_Abort;
|
| }
|
|
|
| - if( onError!=OE_Replace || pTab->pIndex ){
|
| - if( isUpdate ){
|
| - j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
|
| + if( isUpdate ){
|
| + j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
|
| + }
|
| + j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
| + switch( onError ){
|
| + default: {
|
| + onError = OE_Abort;
|
| + /* Fall thru into the next case */
|
| }
|
| - j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
| - switch( onError ){
|
| - default: {
|
| - onError = OE_Abort;
|
| - /* Fall thru into the next case */
|
| - }
|
| - case OE_Rollback:
|
| - case OE_Abort:
|
| - case OE_Fail: {
|
| - sqlite3HaltConstraint(
|
| - pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
|
| - break;
|
| - }
|
| - case OE_Replace: {
|
| - /* If there are DELETE triggers on this table and the
|
| - ** recursive-triggers flag is set, call GenerateRowDelete() to
|
| - ** remove the conflicting row from the the table. This will fire
|
| - ** the triggers and remove both the table and index b-tree entries.
|
| - **
|
| - ** Otherwise, if there are no triggers or the recursive-triggers
|
| - ** flag is not set, call GenerateRowIndexDelete(). This removes
|
| - ** the index b-tree entries only. The table b-tree entry will be
|
| - ** replaced by the new entry when it is inserted. */
|
| - Trigger *pTrigger = 0;
|
| - if( pParse->db->flags&SQLITE_RecTriggers ){
|
| - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
| - }
|
| - if( pTrigger ){
|
| - sqlite3GenerateRowDelete(
|
| - pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
|
| - );
|
| - }else{
|
| - sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
|
| - }
|
| - seenReplace = 1;
|
| - break;
|
| + case OE_Rollback:
|
| + case OE_Abort:
|
| + case OE_Fail: {
|
| + sqlite3HaltConstraint(
|
| + pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
|
| + break;
|
| + }
|
| + case OE_Replace: {
|
| + /* If there are DELETE triggers on this table and the
|
| + ** recursive-triggers flag is set, call GenerateRowDelete() to
|
| + ** remove the conflicting row from the the table. This will fire
|
| + ** the triggers and remove both the table and index b-tree entries.
|
| + **
|
| + ** Otherwise, if there are no triggers or the recursive-triggers
|
| + ** flag is not set, but the table has one or more indexes, call
|
| + ** GenerateRowIndexDelete(). This removes the index b-tree entries
|
| + ** only. The table b-tree entry will be replaced by the new entry
|
| + ** when it is inserted.
|
| + **
|
| + ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
|
| + ** also invoke MultiWrite() to indicate that this VDBE may require
|
| + ** statement rollback (if the statement is aborted after the delete
|
| + ** takes place). Earlier versions called sqlite3MultiWrite() regardless,
|
| + ** but being more selective here allows statements like:
|
| + **
|
| + ** REPLACE INTO t(rowid) VALUES($newrowid)
|
| + **
|
| + ** to run without a statement journal if there are no indexes on the
|
| + ** table.
|
| + */
|
| + Trigger *pTrigger = 0;
|
| + if( pParse->db->flags&SQLITE_RecTriggers ){
|
| + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
| }
|
| - case OE_Ignore: {
|
| - assert( seenReplace==0 );
|
| - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
| - break;
|
| + if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
| + sqlite3MultiWrite(pParse);
|
| + sqlite3GenerateRowDelete(
|
| + pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
|
| + );
|
| + }else if( pTab->pIndex ){
|
| + sqlite3MultiWrite(pParse);
|
| + sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
|
| }
|
| + seenReplace = 1;
|
| + break;
|
| }
|
| - sqlite3VdbeJumpHere(v, j3);
|
| - if( isUpdate ){
|
| - sqlite3VdbeJumpHere(v, j2);
|
| + case OE_Ignore: {
|
| + assert( seenReplace==0 );
|
| + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
| + break;
|
| }
|
| }
|
| + sqlite3VdbeJumpHere(v, j3);
|
| + if( isUpdate ){
|
| + sqlite3VdbeJumpHere(v, j2);
|
| + }
|
| }
|
|
|
| /* Test all UNIQUE constraints by creating entries for each UNIQUE
|
| @@ -1364,6 +1391,7 @@ void sqlite3GenerateConstraintChecks(
|
| default: {
|
| Trigger *pTrigger = 0;
|
| assert( onError==OE_Replace );
|
| + sqlite3MultiWrite(pParse);
|
| if( pParse->db->flags&SQLITE_RecTriggers ){
|
| pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
| }
|
| @@ -1377,7 +1405,7 @@ void sqlite3GenerateConstraintChecks(
|
| sqlite3VdbeJumpHere(v, j3);
|
| sqlite3ReleaseTempReg(pParse, regR);
|
| }
|
| -
|
| +
|
| if( pbMayReplace ){
|
| *pbMayReplace = seenReplace;
|
| }
|
| @@ -1702,7 +1730,7 @@ static int xferOptimization(
|
| }
|
| }
|
| #ifndef SQLITE_OMIT_CHECK
|
| - if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
|
| + if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
|
| return 0; /* Tables have different CHECK constraints. Ticket #2252 */
|
| }
|
| #endif
|
| @@ -1800,8 +1828,3 @@ static int xferOptimization(
|
| }
|
| }
|
| #endif /* SQLITE_OMIT_XFER_OPT */
|
| -
|
| -/* 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
|
|
|