| Index: third_party/sqlite/src/src/update.c | 
| diff --git a/third_party/sqlite/src/src/update.c b/third_party/sqlite/src/src/update.c | 
| index 315034d86f5e5638c17a56dc707eb4cbb8add95f..3af4017f1ba9a3143bbe2c9d0dd78b50aab3bd54 100644 | 
| --- a/third_party/sqlite/src/src/update.c | 
| +++ b/third_party/sqlite/src/src/update.c | 
| @@ -23,7 +23,8 @@ static void updateVirtualTable( | 
| ExprList *pChanges,  /* The columns to change in the UPDATE statement */ | 
| Expr *pRowidExpr,    /* Expression used to recompute the rowid */ | 
| int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */ | 
| -  Expr *pWhere         /* WHERE clause of the UPDATE statement */ | 
| +  Expr *pWhere,        /* WHERE clause of the UPDATE statement */ | 
| +  int onError          /* ON CONFLICT strategy */ | 
| ); | 
| #endif /* SQLITE_OMIT_VIRTUALTABLE */ | 
|  | 
| @@ -60,7 +61,7 @@ static void updateVirtualTable( | 
| void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ | 
| assert( pTab!=0 ); | 
| if( !pTab->pSelect ){ | 
| -    sqlite3_value *pValue; | 
| +    sqlite3_value *pValue = 0; | 
| u8 enc = ENC(sqlite3VdbeDb(v)); | 
| Column *pCol = &pTab->aCol[i]; | 
| VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); | 
| @@ -71,7 +72,7 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ | 
| sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); | 
| } | 
| #ifndef SQLITE_OMIT_FLOATING_POINT | 
| -    if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ | 
| +    if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ | 
| sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); | 
| } | 
| #endif | 
| @@ -94,25 +95,32 @@ void sqlite3Update( | 
| ){ | 
| int i, j;              /* Loop counters */ | 
| Table *pTab;           /* The table to be updated */ | 
| -  int addr = 0;          /* VDBE instruction address of the start of the loop */ | 
| +  int addrTop = 0;       /* VDBE instruction address of the start of the loop */ | 
| WhereInfo *pWInfo;     /* Information about the WHERE clause */ | 
| Vdbe *v;               /* The virtual database engine */ | 
| Index *pIdx;           /* For looping over indices */ | 
| +  Index *pPk;            /* The PRIMARY KEY index for WITHOUT ROWID tables */ | 
| int nIdx;              /* Number of indices that need updating */ | 
| -  int iCur;              /* VDBE Cursor number of pTab */ | 
| +  int iBaseCur;          /* Base cursor number */ | 
| +  int iDataCur;          /* Cursor for the canonical data btree */ | 
| +  int iIdxCur;           /* Cursor for the first index */ | 
| sqlite3 *db;           /* The database structure */ | 
| int *aRegIdx = 0;      /* One register assigned to each index to be updated */ | 
| int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the | 
| ** an expression for the i-th column of the table. | 
| ** aXRef[i]==-1 if the i-th column is not changed. */ | 
| -  int chngRowid;         /* True if the record number is being changed */ | 
| +  u8 *aToOpen;           /* 1 for tables and indices to be opened */ | 
| +  u8 chngPk;             /* PRIMARY KEY changed in a WITHOUT ROWID table */ | 
| +  u8 chngRowid;          /* Rowid changed in a normal table */ | 
| +  u8 chngKey;            /* Either chngPk or chngRowid */ | 
| Expr *pRowidExpr = 0;  /* Expression defining the new record number */ | 
| -  int openAll = 0;       /* True if all indices need to be opened */ | 
| AuthContext sContext;  /* The authorization context */ | 
| NameContext sNC;       /* The name-context to resolve expressions in */ | 
| int iDb;               /* Database containing the table being updated */ | 
| int okOnePass;         /* True for one-pass algorithm without the FIFO */ | 
| int hasFK;             /* True if foreign key processing is required */ | 
| +  int labelBreak;        /* Jump here to break out of UPDATE loop */ | 
| +  int labelContinue;     /* Jump here to continue next step of UPDATE loop */ | 
|  | 
| #ifndef SQLITE_OMIT_TRIGGER | 
| int isView;            /* True when updating a view (INSTEAD OF trigger) */ | 
| @@ -120,14 +128,18 @@ void sqlite3Update( | 
| int tmask;             /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ | 
| #endif | 
| int newmask;           /* Mask of NEW.* columns accessed by BEFORE triggers */ | 
| +  int iEph = 0;          /* Ephemeral table holding all primary key values */ | 
| +  int nKey = 0;          /* Number of elements in regKey for WITHOUT ROWID */ | 
| +  int aiCurOnePass[2];   /* The write cursors opened by WHERE_ONEPASS */ | 
|  | 
| /* Register Allocations */ | 
| int regRowCount = 0;   /* A count of rows changed */ | 
| int regOldRowid;       /* The old rowid */ | 
| int regNewRowid;       /* The new rowid */ | 
| -  int regNew; | 
| -  int regOld = 0; | 
| +  int regNew;            /* Content of the NEW.* table in triggers */ | 
| +  int regOld = 0;        /* Content of OLD.* table in triggers */ | 
| int regRowSet = 0;     /* Rowset of rows to be updated */ | 
| +  int regKey = 0;        /* composite PRIMARY KEY value */ | 
|  | 
| memset(&sContext, 0, sizeof(sContext)); | 
| db = pParse->db; | 
| @@ -165,20 +177,34 @@ void sqlite3Update( | 
| if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ | 
| goto update_cleanup; | 
| } | 
| -  aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); | 
| -  if( aXRef==0 ) goto update_cleanup; | 
| -  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; | 
|  | 
| /* Allocate a cursors for the main database table and for all indices. | 
| ** The index cursors might not be used, but if they are used they | 
| ** need to occur right after the database cursor.  So go ahead and | 
| ** allocate enough space, just in case. | 
| */ | 
| -  pTabList->a[0].iCursor = iCur = pParse->nTab++; | 
| -  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | 
| +  pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++; | 
| +  iIdxCur = iDataCur+1; | 
| +  pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); | 
| +  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ | 
| +    if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ | 
| +      iDataCur = pParse->nTab; | 
| +      pTabList->a[0].iCursor = iDataCur; | 
| +    } | 
| pParse->nTab++; | 
| } | 
|  | 
| +  /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. | 
| +  ** Initialize aXRef[] and aToOpen[] to their default values. | 
| +  */ | 
| +  aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); | 
| +  if( aXRef==0 ) goto update_cleanup; | 
| +  aRegIdx = aXRef+pTab->nCol; | 
| +  aToOpen = (u8*)(aRegIdx+nIdx); | 
| +  memset(aToOpen, 1, nIdx+1); | 
| +  aToOpen[nIdx+1] = 0; | 
| +  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; | 
| + | 
| /* Initialize the name-context */ | 
| memset(&sNC, 0, sizeof(sNC)); | 
| sNC.pParse = pParse; | 
| @@ -190,7 +216,7 @@ void sqlite3Update( | 
| ** column to be updated, make sure we have authorization to change | 
| ** that column. | 
| */ | 
| -  chngRowid = 0; | 
| +  chngRowid = chngPk = 0; | 
| for(i=0; i<pChanges->nExpr; i++){ | 
| if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ | 
| goto update_cleanup; | 
| @@ -200,13 +226,16 @@ void sqlite3Update( | 
| if( j==pTab->iPKey ){ | 
| chngRowid = 1; | 
| pRowidExpr = pChanges->a[i].pExpr; | 
| +        }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ | 
| +          chngPk = 1; | 
| } | 
| aXRef[j] = i; | 
| break; | 
| } | 
| } | 
| if( j>=pTab->nCol ){ | 
| -      if( sqlite3IsRowid(pChanges->a[i].zName) ){ | 
| +      if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){ | 
| +        j = -1; | 
| chngRowid = 1; | 
| pRowidExpr = pChanges->a[i].pExpr; | 
| }else{ | 
| @@ -219,7 +248,8 @@ void sqlite3Update( | 
| { | 
| int rc; | 
| rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, | 
| -                           pTab->aCol[j].zName, db->aDb[iDb].zName); | 
| +                            j<0 ? "ROWID" : pTab->aCol[j].zName, | 
| +                            db->aDb[iDb].zName); | 
| if( rc==SQLITE_DENY ){ | 
| goto update_cleanup; | 
| }else if( rc==SQLITE_IGNORE ){ | 
| @@ -228,32 +258,36 @@ void sqlite3Update( | 
| } | 
| #endif | 
| } | 
| +  assert( (chngRowid & chngPk)==0 ); | 
| +  assert( chngRowid==0 || chngRowid==1 ); | 
| +  assert( chngPk==0 || chngPk==1 ); | 
| +  chngKey = chngRowid + chngPk; | 
|  | 
| -  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngRowid); | 
| +  /* The SET expressions are not actually used inside the WHERE loop. | 
| +  ** So reset the colUsed mask | 
| +  */ | 
| +  pTabList->a[0].colUsed = 0; | 
|  | 
| -  /* Allocate memory for the array aRegIdx[].  There is one entry in the | 
| -  ** array for each index associated with table being updated.  Fill in | 
| -  ** the value with a register number for indices that are to be used | 
| -  ** and with zero for unused indices. | 
| +  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); | 
| + | 
| +  /* There is one entry in the aRegIdx[] array for each index on the table | 
| +  ** being updated.  Fill in aRegIdx[] with a register number that will hold | 
| +  ** the key for accessing each index. | 
| */ | 
| -  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} | 
| -  if( nIdx>0 ){ | 
| -    aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx ); | 
| -    if( aRegIdx==0 ) goto update_cleanup; | 
| -  } | 
| for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ | 
| int reg; | 
| -    if( chngRowid ){ | 
| +    if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ | 
| reg = ++pParse->nMem; | 
| }else{ | 
| reg = 0; | 
| -      for(i=0; i<pIdx->nColumn; i++){ | 
| +      for(i=0; i<pIdx->nKeyCol; i++){ | 
| if( aXRef[pIdx->aiColumn[i]]>=0 ){ | 
| reg = ++pParse->nMem; | 
| break; | 
| } | 
| } | 
| } | 
| +    if( reg==0 ) aToOpen[j+1] = 0; | 
| aRegIdx[j] = reg; | 
| } | 
|  | 
| @@ -267,7 +301,7 @@ void sqlite3Update( | 
| /* Virtual tables must be handled separately */ | 
| if( IsVirtual(pTab) ){ | 
| updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, | 
| -                       pWhere); | 
| +                       pWhere, onError); | 
| pWhere = 0; | 
| pTabList = 0; | 
| goto update_cleanup; | 
| @@ -275,12 +309,13 @@ void sqlite3Update( | 
| #endif | 
|  | 
| /* Allocate required registers. */ | 
| +  regRowSet = ++pParse->nMem; | 
| regOldRowid = regNewRowid = ++pParse->nMem; | 
| -  if( pTrigger || hasFK ){ | 
| +  if( chngPk || pTrigger || hasFK ){ | 
| regOld = pParse->nMem + 1; | 
| pParse->nMem += pTab->nCol; | 
| } | 
| -  if( chngRowid || pTrigger || hasFK ){ | 
| +  if( chngKey || pTrigger || hasFK ){ | 
| regNewRowid = ++pParse->nMem; | 
| } | 
| regNew = pParse->nMem + 1; | 
| @@ -292,11 +327,11 @@ void sqlite3Update( | 
| } | 
|  | 
| /* If we are trying to update a view, realize that view into | 
| -  ** a ephemeral table. | 
| +  ** an ephemeral table. | 
| */ | 
| #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) | 
| if( isView ){ | 
| -    sqlite3MaterializeView(pParse, pTab, pWhere, iCur); | 
| +    sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur); | 
| } | 
| #endif | 
|  | 
| @@ -309,23 +344,58 @@ void sqlite3Update( | 
|  | 
| /* Begin the database scan | 
| */ | 
| -  sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); | 
| -  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED); | 
| -  if( pWInfo==0 ) goto update_cleanup; | 
| -  okOnePass = pWInfo->okOnePass; | 
| - | 
| -  /* Remember the rowid of every item to be updated. | 
| -  */ | 
| -  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid); | 
| -  if( !okOnePass ){ | 
| -    regRowSet = ++pParse->nMem; | 
| -    sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); | 
| +  if( HasRowid(pTab) ){ | 
| +    sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); | 
| +    pWInfo = sqlite3WhereBegin( | 
| +        pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur | 
| +    ); | 
| +    if( pWInfo==0 ) goto update_cleanup; | 
| +    okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); | 
| + | 
| +    /* Remember the rowid of every item to be updated. | 
| +    */ | 
| +    sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); | 
| +    if( !okOnePass ){ | 
| +      sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); | 
| +    } | 
| + | 
| +    /* End the database scan loop. | 
| +    */ | 
| +    sqlite3WhereEnd(pWInfo); | 
| +  }else{ | 
| +    int iPk;         /* First of nPk memory cells holding PRIMARY KEY value */ | 
| +    i16 nPk;         /* Number of components of the PRIMARY KEY */ | 
| +    int addrOpen;    /* Address of the OpenEphemeral instruction */ | 
| + | 
| +    assert( pPk!=0 ); | 
| +    nPk = pPk->nKeyCol; | 
| +    iPk = pParse->nMem+1; | 
| +    pParse->nMem += nPk; | 
| +    regKey = ++pParse->nMem; | 
| +    iEph = pParse->nTab++; | 
| +    sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); | 
| +    addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); | 
| +    sqlite3VdbeSetP4KeyInfo(pParse, pPk); | 
| +    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, | 
| +                               WHERE_ONEPASS_DESIRED, iIdxCur); | 
| +    if( pWInfo==0 ) goto update_cleanup; | 
| +    okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); | 
| +    for(i=0; i<nPk; i++){ | 
| +      sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], | 
| +                                      iPk+i); | 
| +    } | 
| +    if( okOnePass ){ | 
| +      sqlite3VdbeChangeToNoop(v, addrOpen); | 
| +      nKey = nPk; | 
| +      regKey = iPk; | 
| +    }else{ | 
| +      sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, | 
| +                        sqlite3IndexAffinityStr(v, pPk), nPk); | 
| +      sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); | 
| +    } | 
| +    sqlite3WhereEnd(pWInfo); | 
| } | 
|  | 
| -  /* End the database scan loop. | 
| -  */ | 
| -  sqlite3WhereEnd(pWInfo); | 
| - | 
| /* Initialize the count of updated rows | 
| */ | 
| if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ | 
| @@ -333,6 +403,7 @@ void sqlite3Update( | 
| sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); | 
| } | 
|  | 
| +  labelBreak = sqlite3VdbeMakeLabel(v); | 
| if( !isView ){ | 
| /* | 
| ** Open every index that needs updating.  Note that if any | 
| @@ -340,73 +411,84 @@ void sqlite3Update( | 
| ** action, then we need to open all indices because we might need | 
| ** to be deleting some records. | 
| */ | 
| -    if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); | 
| if( onError==OE_Replace ){ | 
| -      openAll = 1; | 
| +      memset(aToOpen, 1, nIdx+1); | 
| }else{ | 
| -      openAll = 0; | 
| for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | 
| if( pIdx->onError==OE_Replace ){ | 
| -          openAll = 1; | 
| +          memset(aToOpen, 1, nIdx+1); | 
| break; | 
| } | 
| } | 
| } | 
| -    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ | 
| -      if( openAll || aRegIdx[i]>0 ){ | 
| -        KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); | 
| -        sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb, | 
| -                       (char*)pKey, P4_KEYINFO_HANDOFF); | 
| -        assert( pParse->nTab>iCur+i+1 ); | 
| -      } | 
| +    if( okOnePass ){ | 
| +      if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; | 
| +      if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; | 
| } | 
| +    sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen, | 
| +                               0, 0); | 
| } | 
|  | 
| /* Top of the update loop */ | 
| if( okOnePass ){ | 
| -    int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid); | 
| -    addr = sqlite3VdbeAddOp0(v, OP_Goto); | 
| -    sqlite3VdbeJumpHere(v, a1); | 
| +    if( aToOpen[iDataCur-iBaseCur] && !isView ){ | 
| +      assert( pPk ); | 
| +      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); | 
| +      VdbeCoverageNeverTaken(v); | 
| +    } | 
| +    labelContinue = labelBreak; | 
| +    sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); | 
| +    VdbeCoverageIf(v, pPk==0); | 
| +    VdbeCoverageIf(v, pPk!=0); | 
| +  }else if( pPk ){ | 
| +    labelContinue = sqlite3VdbeMakeLabel(v); | 
| +    sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); | 
| +    addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); | 
| +    sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); | 
| +    VdbeCoverage(v); | 
| }else{ | 
| -    addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid); | 
| +    labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, | 
| +                             regOldRowid); | 
| +    VdbeCoverage(v); | 
| +    sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); | 
| +    VdbeCoverage(v); | 
| } | 
|  | 
| -  /* Make cursor iCur point to the record that is being updated. If | 
| -  ** this record does not exist for some reason (deleted by a trigger, | 
| -  ** for example, then jump to the next iteration of the RowSet loop.  */ | 
| -  sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); | 
| - | 
| /* If the record number will change, set register regNewRowid to | 
| ** contain the new value. If the record number is not being modified, | 
| ** then regNewRowid is the same register as regOldRowid, which is | 
| ** already populated.  */ | 
| -  assert( chngRowid || pTrigger || hasFK || regOldRowid==regNewRowid ); | 
| +  assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); | 
| if( chngRowid ){ | 
| sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); | 
| -    sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); | 
| +    sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); | 
| } | 
|  | 
| -  /* If there are triggers on this table, populate an array of registers | 
| -  ** with the required old.* column data.  */ | 
| -  if( hasFK || pTrigger ){ | 
| +  /* Compute the old pre-UPDATE content of the row being changed, if that | 
| +  ** information is needed */ | 
| +  if( chngPk || hasFK || pTrigger ){ | 
| u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); | 
| oldmask |= sqlite3TriggerColmask(pParse, | 
| pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError | 
| ); | 
| for(i=0; i<pTab->nCol; i++){ | 
| -      if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){ | 
| -        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i); | 
| +      if( oldmask==0xffffffff | 
| +       || (i<32 && (oldmask & MASKBIT32(i))!=0) | 
| +       || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 | 
| +      ){ | 
| +        testcase(  oldmask!=0xffffffff && i==31 ); | 
| +        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i); | 
| }else{ | 
| sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i); | 
| } | 
| } | 
| -    if( chngRowid==0 ){ | 
| +    if( chngRowid==0 && pPk==0 ){ | 
| sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); | 
| } | 
| } | 
|  | 
| /* Populate the array of registers beginning at regNew with the new | 
| -  ** row data. This array is used to check constaints, create the new | 
| +  ** row data. This array is used to check constants, create the new | 
| ** table and index records, and as the values for any new.* references | 
| ** made by triggers. | 
| ** | 
| @@ -421,6 +503,7 @@ void sqlite3Update( | 
| newmask = sqlite3TriggerColmask( | 
| pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError | 
| ); | 
| +  /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/ | 
| for(i=0; i<pTab->nCol; i++){ | 
| if( i==pTab->iPKey ){ | 
| sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); | 
| @@ -428,7 +511,7 @@ void sqlite3Update( | 
| j = aXRef[i]; | 
| if( j>=0 ){ | 
| sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); | 
| -      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){ | 
| +      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ | 
| /* This branch loads the value of a column that will not be changed | 
| ** into a register. This is done if there are no BEFORE triggers, or | 
| ** if there are one or more BEFORE triggers that use this value via | 
| @@ -436,8 +519,9 @@ void sqlite3Update( | 
| */ | 
| testcase( i==31 ); | 
| testcase( i==32 ); | 
| -        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); | 
| -        sqlite3ColumnDefault(v, pTab, i, regNew+i); | 
| +        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); | 
| +      }else{ | 
| +        sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); | 
| } | 
| } | 
| } | 
| @@ -446,18 +530,23 @@ void sqlite3Update( | 
| ** verified. One could argue that this is wrong. | 
| */ | 
| if( tmask&TRIGGER_BEFORE ){ | 
| -    sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); | 
| -    sqlite3TableAffinityStr(v, pTab); | 
| +    sqlite3TableAffinity(v, pTab, regNew); | 
| sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, | 
| -        TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); | 
| +        TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); | 
|  | 
| /* The row-trigger may have deleted the row being updated. In this | 
| ** case, jump to the next row. No updates or AFTER triggers are | 
| -    ** required. This behaviour - what happens when the row being updated | 
| +    ** required. This behavior - what happens when the row being updated | 
| ** is deleted or renamed by a BEFORE trigger - is left undefined in the | 
| ** documentation. | 
| */ | 
| -    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); | 
| +    if( pPk ){ | 
| +      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); | 
| +      VdbeCoverage(v); | 
| +    }else{ | 
| +      sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); | 
| +      VdbeCoverage(v); | 
| +    } | 
|  | 
| /* If it did not delete it, the row-trigger may still have modified | 
| ** some of the columns of the row being updated. Load the values for | 
| @@ -466,46 +555,57 @@ void sqlite3Update( | 
| */ | 
| for(i=0; i<pTab->nCol; i++){ | 
| if( aXRef[i]<0 && i!=pTab->iPKey ){ | 
| -        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); | 
| -        sqlite3ColumnDefault(v, pTab, i, regNew+i); | 
| +        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); | 
| } | 
| } | 
| } | 
|  | 
| if( !isView ){ | 
| -    int j1;                       /* Address of jump instruction */ | 
| +    int j1 = 0;           /* Address of jump instruction */ | 
| +    int bReplace = 0;     /* True if REPLACE conflict resolution might happen */ | 
|  | 
| /* Do constraint checks. */ | 
| -    sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, | 
| -        aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0); | 
| +    assert( regOldRowid>0 ); | 
| +    sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, | 
| +        regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace); | 
|  | 
| /* Do FK constraint checks. */ | 
| if( hasFK ){ | 
| -      sqlite3FkCheck(pParse, pTab, regOldRowid, 0); | 
| +      sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); | 
| } | 
|  | 
| /* Delete the index entries associated with the current record.  */ | 
| -    j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); | 
| -    sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); | 
| +    if( bReplace || chngKey ){ | 
| +      if( pPk ){ | 
| +        j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); | 
| +      }else{ | 
| +        j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); | 
| +      } | 
| +      VdbeCoverageNeverTaken(v); | 
| +    } | 
| +    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); | 
|  | 
| /* If changing the record number, delete the old record.  */ | 
| -    if( hasFK || chngRowid ){ | 
| -      sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0); | 
| +    if( hasFK || chngKey || pPk!=0 ){ | 
| +      sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); | 
| +    } | 
| +    if( bReplace || chngKey ){ | 
| +      sqlite3VdbeJumpHere(v, j1); | 
| } | 
| -    sqlite3VdbeJumpHere(v, j1); | 
|  | 
| if( hasFK ){ | 
| -      sqlite3FkCheck(pParse, pTab, 0, regNewRowid); | 
| +      sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); | 
| } | 
|  | 
| /* Insert the new index entries and the new record. */ | 
| -    sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0); | 
| +    sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, | 
| +                             regNewRowid, aRegIdx, 1, 0, 0); | 
|  | 
| /* 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 updated. */ | 
| if( hasFK ){ | 
| -      sqlite3FkActions(pParse, pTab, pChanges, regOldRowid); | 
| +      sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); | 
| } | 
| } | 
|  | 
| @@ -516,21 +616,29 @@ void sqlite3Update( | 
| } | 
|  | 
| sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, | 
| -      TRIGGER_AFTER, pTab, regOldRowid, onError, addr); | 
| +      TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); | 
|  | 
| /* Repeat the above with the next record to be updated, until | 
| ** all record selected by the WHERE clause have been updated. | 
| */ | 
| -  sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); | 
| -  sqlite3VdbeJumpHere(v, addr); | 
| +  if( okOnePass ){ | 
| +    /* Nothing to do at end-of-loop for a single-pass */ | 
| +  }else if( pPk ){ | 
| +    sqlite3VdbeResolveLabel(v, labelContinue); | 
| +    sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); | 
| +  }else{ | 
| +    sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue); | 
| +  } | 
| +  sqlite3VdbeResolveLabel(v, labelBreak); | 
|  | 
| /* Close all tables */ | 
| for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ | 
| -    if( openAll || aRegIdx[i]>0 ){ | 
| -      sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0); | 
| +    assert( aRegIdx ); | 
| +    if( aToOpen[i+1] ){ | 
| +      sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0); | 
| } | 
| } | 
| -  sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); | 
| +  if( iDataCur<iIdxCur ) sqlite3VdbeAddOp2(v, OP_Close, iDataCur, 0); | 
|  | 
| /* Update the sqlite_sequence table by storing the content of the | 
| ** maximum rowid counter values recorded while inserting into | 
| @@ -553,15 +661,14 @@ void sqlite3Update( | 
|  | 
| update_cleanup: | 
| sqlite3AuthContextPop(&sContext); | 
| -  sqlite3DbFree(db, aRegIdx); | 
| -  sqlite3DbFree(db, aXRef); | 
| +  sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */ | 
| sqlite3SrcListDelete(db, pTabList); | 
| sqlite3ExprListDelete(db, pChanges); | 
| 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 | 
| +** they 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 | 
| @@ -574,7 +681,7 @@ update_cleanup: | 
| /* | 
| ** Generate code for an UPDATE of a virtual table. | 
| ** | 
| -** The strategy is that we create an ephemerial table that contains | 
| +** The strategy is that we create an ephemeral table that contains | 
| ** for each row to be changed: | 
| ** | 
| **   (A)  The original rowid of that row. | 
| @@ -582,7 +689,7 @@ update_cleanup: | 
| **   (C)  The content of every column in the row. | 
| ** | 
| ** Then we loop over this ephemeral table and for each row in | 
| -** the ephermeral table call VUpdate. | 
| +** the ephemeral table call VUpdate. | 
| ** | 
| ** When finished, drop the ephemeral table. | 
| ** | 
| @@ -597,7 +704,8 @@ static void updateVirtualTable( | 
| ExprList *pChanges,  /* The columns to change in the UPDATE statement */ | 
| Expr *pRowid,        /* Expression used to recompute the rowid */ | 
| int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */ | 
| -  Expr *pWhere         /* WHERE clause of the UPDATE statement */ | 
| +  Expr *pWhere,        /* WHERE clause of the UPDATE statement */ | 
| +  int onError          /* ON CONFLICT strategy */ | 
| ){ | 
| Vdbe *v = pParse->pVdbe;  /* Virtual machine under construction */ | 
| ExprList *pEList = 0;     /* The result set of the SELECT statement */ | 
| @@ -646,7 +754,7 @@ static void updateVirtualTable( | 
| /* Generate code to scan the ephemeral table and call VUpdate. */ | 
| iReg = ++pParse->nMem; | 
| pParse->nMem += pTab->nCol+1; | 
| -  addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); | 
| +  addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); | 
| sqlite3VdbeAddOp3(v, OP_Column,  ephemTab, 0, iReg); | 
| sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); | 
| for(i=0; i<pTab->nCol; i++){ | 
| @@ -654,8 +762,9 @@ static void updateVirtualTable( | 
| } | 
| sqlite3VtabMakeWritable(pParse, pTab); | 
| sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); | 
| +  sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); | 
| sqlite3MayAbort(pParse); | 
| -  sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); | 
| +  sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); | 
| sqlite3VdbeJumpHere(v, addr); | 
| sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); | 
|  | 
|  |