Fix the Synopsis on OP_Concat.  Added test_addop_breakpoint() during
SQLITE_DEBUG.  Enhanced sqlite3VdbeChangeToNoop() to omit the instruction
if it is the most recent added.  Continue to fix problems with UPDATE
and WITHOUT ROWID.

FossilOrigin-Name: 9b6d9e106aaa3c2efb33d234d26cf08cd3c967b9
diff --git a/src/delete.c b/src/delete.c
index 4d27f98..5568840 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -407,7 +407,7 @@
 
     /* Delete the row */
     sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
-                             iPk, nPk, 1, OE_Default);
+                             iPk, 0, 1, OE_Default);
 
     /* End of the delete loop */
     sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1);
@@ -537,7 +537,9 @@
 **       cursor number iIdxCur+i for the i-th index.
 **
 **   3.  The primary key for the row to be deleted must be stored in a
-**       sequence of nPk memory cells starting at iPk. 
+**       sequence of nPk memory cells starting at iPk.  If nPk==0 that means
+**       that a search record formed from OP_MakeRecord is contained in the
+**       single memory location iPk.
 */
 void sqlite3GenerateRowDelete(
   Parse *pParse,     /* Parsing context */
@@ -669,6 +671,7 @@
   Index *pPk;        /* PRIMARY KEY index, or NULL for rowid tables */
 
   v = pParse->pVdbe;
+  VdbeModuleComment((v, "BEGIN: GenRowIdxDel(%d,%d)", iDataCur, iIdxCur));
   pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
   for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
     assert( iIdxCur+i!=iDataCur || pPk==pIdx );
@@ -679,6 +682,7 @@
                       pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
     sqlite3VdbeResolveLabel(v, iPartIdxLabel);
   }
+  VdbeModuleComment((v, "END: GenRowIdxDel()"));
 }
 
 /*
diff --git a/src/expr.c b/src/expr.c
index 24d866f..4a321db 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -2214,9 +2214,9 @@
 void sqlite3ExprCodeGetColumnOfTable(
   Vdbe *v,        /* The VDBE under construction */
   Table *pTab,    /* The table containing the value */
-  int iTabCur,    /* The cursor for this table */
+  int iTabCur,    /* The table cursor.  Or the PK cursor for WITHOUT ROWID */
   int iCol,       /* Index of the column to extract */
-  int regOut      /* Extract the valud into this register */
+  int regOut      /* Extract the value into this register */
 ){
   if( iCol<0 || iCol==pTab->iPKey ){
     sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
diff --git a/src/update.c b/src/update.c
index 5c92f6f..c06fcd2 100644
--- a/src/update.c
+++ b/src/update.c
@@ -101,7 +101,6 @@
   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 iTabCur;           /* VDBE Cursor number of pTab */
   int iDataCur;          /* Cursor for the canonical data btree */
   int iIdxCur;           /* Cursor for the first index */
   sqlite3 *db;           /* The database structure */
@@ -182,11 +181,14 @@
   ** need to occur right after the database cursor.  So go ahead and
   ** allocate enough space, just in case.
   */
-  pTabList->a[0].iCursor = iTabCur = iDataCur = pParse->nTab++;
-  iIdxCur = iTabCur+1;
+  pTabList->a[0].iCursor = iDataCur = pParse->nTab++;
+  iIdxCur = iDataCur+1;
   pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
   for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
-    if( pIdx->autoIndex==2 && pPk!=0 ) iDataCur = pParse->nTab;
+    if( pIdx->autoIndex==2 && pPk!=0 ){
+      iDataCur = pParse->nTab;
+      pTabList->a[0].iCursor = iDataCur;
+    }
     pParse->nTab++;
   }
 
@@ -199,9 +201,11 @@
   ** of the UPDATE statement.  Also find the column index
   ** for each column to be updated in the pChanges array.  For each
   ** column to be updated, make sure we have authorization to change
-  ** that column.
+  ** that column.  Set chngPk if the iDataCur key changes.  Note that
+  ** for WITHOUT ROWID columns, the iDataCur key contains all columns of
+  ** the table and so it will always change.
   */
-  chngPk = 0;
+  chngPk = (pPk!=0);
   for(i=0; i<pChanges->nExpr; i++){
     if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
       goto update_cleanup;
@@ -211,8 +215,6 @@
         if( j==pTab->iPKey ){
           chngPk = 1;
           pRowidExpr = pChanges->a[i].pExpr;
-        }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
-          chngPk = 1;
         }
         aXRef[j] = i;
         break;
@@ -311,7 +313,7 @@
   */
 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur);
+    sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur);
   }
 #endif
 
@@ -334,7 +336,7 @@
   
     /* Remember the rowid of every item to be updated.
     */
-    sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOldRowid);
+    sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
     if( !okOnePass ){
       sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
     }
@@ -383,7 +385,7 @@
     ** to be deleting some records.
     */
     if( !okOnePass && HasRowid(pTab) ){
-      sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenWrite); 
+      sqlite3OpenTable(pParse, iDataCur, iDb, pTab, OP_OpenWrite); 
     }
     if( onError==OE_Replace ){
       openAll = 1;
@@ -403,6 +405,7 @@
         sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdxCur+i, pIdx->tnum, iDb,
                        (char*)pKey, P4_KEYINFO_HANDOFF);
         assert( pParse->nTab>iIdxCur+i );
+        VdbeComment((v, "%s", pIdx->zName));
       }
     }
   }
@@ -413,7 +416,7 @@
   if( pPk ){
     sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak);
     addr = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
-    sqlite3VdbeAddOp3(v, OP_NotFound, iEph, labelContinue, regKey);
+    sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
   }else if( okOnePass ){
     int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
     addr = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelBreak);
@@ -429,7 +432,7 @@
   ** then regNewRowid is the same register as regOldRowid, which is
   ** already populated.  */
   assert( chngPk || pTrigger || hasFK || regOldRowid==regNewRowid );
-  if( chngPk ){
+  if( chngPk && pPk==0 ){
     sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
     sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
   }
@@ -485,8 +488,7 @@
         */
         testcase( i==31 );
         testcase( i==32 );
-        sqlite3VdbeAddOp3(v, OP_Column, iDataCur, i, regNew+i);
-        sqlite3ColumnDefault(v, pTab, i, regNew+i);
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
       }
     }
   }
@@ -515,8 +517,7 @@
     */
     for(i=0; i<pTab->nCol; i++){
       if( aXRef[i]<0 && i!=pTab->iPKey ){
-        sqlite3VdbeAddOp3(v, OP_Column, iDataCur, i, regNew+i);
-        sqlite3ColumnDefault(v, pTab, i, regNew+i);
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
       }
     }
   }
@@ -535,17 +536,21 @@
 
     /* Delete the index entries associated with the current record.  */
     if( pPk ){
-      j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regOldRowid, 1);
+      j1 = sqlite3VdbeAddOp3(v, OP_NotFound, iDataCur, 0, regOldRowid);
     }else{
       j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
-      sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
     }
+    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
   
     /* If changing the record number, delete the old record.  */
     if( hasFK || chngPk ){
       sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
     }
-    sqlite3VdbeJumpHere(v, j1);
+    if( sqlite3VdbeCurrentAddr(v)==j1+1 ){
+      sqlite3VdbeChangeToNoop(v, j1);
+    }else{
+      sqlite3VdbeJumpHere(v, j1);
+    }
 
     if( hasFK ){
       sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngPk);
diff --git a/src/vdbe.c b/src/vdbe.c
index 2f648a7..b72ef40 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -1203,7 +1203,7 @@
 }
 
 /* Opcode: Concat P1 P2 P3 * *
-** Synopsis: r[P3]=r[P2]+r[P3]
+** Synopsis: r[P3]=r[P2]+r[P1]
 **
 ** Add the text in register P1 onto the end of the text in
 ** register P2 and store the result in register P3.
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index e2ef4ee..8a1eea1 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -107,6 +107,17 @@
   return (pNew ? SQLITE_OK : SQLITE_NOMEM);
 }
 
+#ifdef SQLITE_DEBUG
+/* This routine is just a convenient place to set a breakpoint that will
+** fire after each opcode is inserted and displayed using
+** "PRAGMA vdbe_addoptrace=on".
+*/
+static void test_addop_breakpoint(void){
+  static int n = 0;
+  n++;
+}
+#endif
+
 /*
 ** Add a new instruction to the list of instructions current in the
 ** VDBE.  Return the address of the new instruction.
@@ -150,6 +161,7 @@
 #ifdef SQLITE_DEBUG
   if( p->db->flags & SQLITE_VdbeAddopTrace ){
     sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+    test_addop_breakpoint();
   }
 #endif
 #ifdef VDBE_PROFILE
@@ -695,6 +707,7 @@
     freeP4(db, pOp->p4type, pOp->p4.p);
     memset(pOp, 0, sizeof(pOp[0]));
     pOp->opcode = OP_Noop;
+    if( addr==p->nOp-1 ) p->nOp--;
   }
 }