]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improved comments and variable names in infrastructure routines of UPDATE,
authordrh <drh@noemail.net>
Thu, 31 Oct 2013 15:37:49 +0000 (15:37 +0000)
committerdrh <drh@noemail.net>
Thu, 31 Oct 2013 15:37:49 +0000 (15:37 +0000)
DELETE, and INSERT.

FossilOrigin-Name: ad90e762e51384ac7c311f08a641419f03f6d3f0

manifest
manifest.uuid
src/delete.c
src/insert.c
src/pragma.c
test/without_rowid1.test

index 0c22692110ae414b910ffb428ddddead2c020c80..70184834ba6645b8b09875cb0c2d4c33b3bca56c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Moving\sUPDATE\stowards\sthe\siDataCur/iIdxCur\srepresentation.\s\sStill\snot\sworking\nfor\sWITHOUT\sROWID,\sthough.
-D 2013-10-31T12:13:37.732
+C Improved\scomments\sand\svariable\snames\sin\sinfrastructure\sroutines\sof\sUPDATE,\nDELETE,\sand\sINSERT.
+D 2013-10-31T15:37:49.070
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -173,7 +173,7 @@ F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
 F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
-F src/delete.c d50cc704030139e19f2e9d5ac7a49db04dfe08a9
+F src/delete.c 0e10849258efbdab48b8679de19edd661859dc7d
 F src/expr.c 3180b6332072b263f845592e72e92971af562ab0
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
@@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c e8f0691953194cf1df85b463fed8b75b0dedf7d9
+F src/insert.c 64eb6bf8eda1bbe003cc38394d721b4810f65182
 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
 F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
@@ -212,7 +212,7 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
 F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
-F src/pragma.c 74dec25a3f0d3e5da796345a0ca817cb445e9d2a
+F src/pragma.c ff1a98998d2038bc9c770326986b7c4728de4973
 F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52
 F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
 F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
@@ -1076,7 +1076,7 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
 F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
 F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b
-F test/without_rowid1.test fb3ceaa20bda4e0338f594696a49014c3cbeb30c
+F test/without_rowid1.test e4f023e49a57c90f6d25afd4b3e8b0305ad06e44
 F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
 F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd
 F tool/build-all-msvc.bat 38623a30fd58288fda5cc7f7df2682aaab75c9d5 x
@@ -1128,7 +1128,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 1adfca6019847d37dee4a297669f29d5ca184066
-R 925135441c339dd20ca1becb38d6fbf2
+P deacbd21b50cc8c63a1572d14a4bbc7af4052d37
+R 868cea4e5c536af4b28fd795ccabbf1e
 U drh
-Z 72a84fe0a8232f3d99ba9db66435b958
+Z 77c0455bfaa16e77ab3ac24edbdbd46c
index 00f527cef5f3e6da58066757dc110b606d74b09f..ec60d0ac811eb90398fe4aed56830998a168305a 100644 (file)
@@ -1 +1 @@
-deacbd21b50cc8c63a1572d14a4bbc7af4052d37
\ No newline at end of file
+ad90e762e51384ac7c311f08a641419f03f6d3f0
\ No newline at end of file
index fc0d4813ddb5cc4ba719e0363e52945c8cb29253..4d27f98f94e83cf4223ca6312362b94a1e26d1b9 100644 (file)
@@ -523,24 +523,21 @@ delete_from_cleanup:
 
 /*
 ** This routine generates VDBE code that causes a single row of a
-** single table to be deleted.
+** single table to be deleted.  Both the original table entry and
+** all indices are removed.
 **
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
+** Preconditions:
 **
-**   1.  iDataCur is an open cursor on the btree that is the primary data
-**       repository for the table.  This will be either the table itself,
+**   1.  iDataCur is an open cursor on the btree that is the canonical data
+**       store for the table.  (This will be either the table itself,
 **       in the case of a rowid table, or the PRIMARY KEY index in the case
-**       of a WITHOUT ROWID table.
+**       of a WITHOUT ROWID table.)
 **
 **   2.  Read/write cursors for all indices of pTab must be open as
 **       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. 
-**
-** This routine generates code to remove both the table record and all 
-** index entries that point to that record.
 */
 void sqlite3GenerateRowDelete(
   Parse *pParse,     /* Parsing context */
@@ -560,7 +557,7 @@ void sqlite3GenerateRowDelete(
 
   /* Vdbe is guaranteed to have been allocated by this stage. */
   assert( v );
-  VdbeModuleComment((v, "BEGIN: GenerateRowDelete(%d,%d,%d,%d)",
+  VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
                          iDataCur, iIdxCur, iPk, (int)nPk));
 
   /* Seek cursor iCur to the row to delete. If this row no longer exists 
@@ -636,26 +633,26 @@ void sqlite3GenerateRowDelete(
   ** trigger programs were invoked. Or if a trigger program throws a 
   ** RAISE(IGNORE) exception.  */
   sqlite3VdbeResolveLabel(v, iLabel);
-  VdbeModuleComment((v, "END: GenerateRowDelete()"));
+  VdbeModuleComment((v, "END: GenRowDel()"));
 }
 
 /*
 ** This routine generates VDBE code that causes the deletion of all
-** index entries associated with a single row of a single table.
+** index entries associated with a single row of a single table, pTab
 **
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
+** Preconditions:
 **
-**   1.  A read/write cursor "iDataCur" pointing to canonical storage
-**       tree for the table pTab, which will be either the table itself
+**   1.  A read/write cursor "iDataCur" must be open on the canonical storage
+**       btree for the table pTab.  (This will be either the table itself
 **       for rowid tables or to the primary key index for WITHOUT ROWID
-**       tables.
+**       tables.)
 **
 **   2.  Read/write cursors for all indices of pTab must be open as
-**       cursor number iIdxCur+i for the i-th index.
+**       cursor number iIdxCur+i for the i-th index.  (The pTab->pIndex
+**       index is the 0-th index.)
 **
-**   3.  The "iDataCur" cursor must be pointing to the row that is to be
-**       deleted.
+**   3.  The "iDataCur" cursor must be already be positioned on the row
+**       that is to be deleted.
 */
 void sqlite3GenerateRowIndexDelete(
   Parse *pParse,     /* Parsing and code generating context */
@@ -664,15 +661,17 @@ void sqlite3GenerateRowIndexDelete(
   int iIdxCur,       /* First index cursor */
   int *aRegIdx       /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
 ){
-  int i;
-  Index *pIdx;
-  int r1;
-  int iPartIdxLabel;
-  Vdbe *v = pParse->pVdbe;
-  Index *pPk;
-
+  int i;             /* Index loop counter */
+  int r1;            /* Register holding an index key */
+  int iPartIdxLabel; /* Jump destination for skipping partial index entries */
+  Index *pIdx;       /* Current index */
+  Vdbe *v;           /* The prepared statement under construction */
+  Index *pPk;        /* PRIMARY KEY index, or NULL for rowid tables */
+
+  v = pParse->pVdbe;
   pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
   for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+    assert( iIdxCur+i!=iDataCur || pPk==pIdx );
     if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
     if( pIdx==pPk ) continue;
     r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel);
index d58a9baea9955b759055276101032259de9e398a..199db1e845d2da2d09c0ab6013aa5e39dc92703a 100644 (file)
@@ -1123,36 +1123,47 @@ insert_cleanup:
 #endif
 
 /*
-** Generate code to do constraint checks prior to an INSERT or an UPDATE.
-**
-** The input is a range of consecutive registers as follows:
-**
-**    1.  The rowid of the row after the update, or NULL
-**        for WITHOUT ROWID tables.
-**
-**    2.  The data in the first column of the entry after the update.
-**
-**    i.  Data from middle columns...
-**
-**    N.  The data in the last column of the entry after the update.
-**
-** The regRowid parameter is the index of the register containing (1).
-**
-** If isUpdate is true and pkChng is non-zero, then pkChng contains
-** the address of a range of registers containing the rowid or PRIMARY KEY
-** value before the update takes place. isUpdate is true for UPDATEs and
-** false for INSERTs. If isUpdate is false then a non-zero pkChng 
-** indicates that the rowid was explicitly specified as part of the
-** INSERT statement. If pkChng is false, it means that  the rowid is
-** computed automatically in an insert and is therefore guaranteed to
-** be unique. The pkChng parameter is always false for inserts
-** into a WITHOUT ROWID table.
-**
-** The code generated by this routine should store new index entries into
+** Generate code to do constraint checks prior to an INSERT or an UPDATE
+** on table pTab.
+**
+** The regNewData parameter is the first register in a range that contains
+** the data to be inserted or the data after the update.  There will be
+** pTab->nCol+1 registers in this range.  The first register (the one
+** that regNewData points to) will contain the new rowid, or NULL in the
+** case of a WITHOUT ROWID table.  The second register in the range will
+** contain the content of the first table column.  The third register will
+** contain the content of the second table column.  And so forth.
+**
+** For an UPDATE (isUpdate!=0), if pkChng is non-zero then it contains
+** the address of a range of registers containing the rowid and table
+** data from before the change.  In other words, pkChng is like 
+** regNewData except that it describes the row before the update rather
+** than afterwards.  If pkChng is zero, that means that the rowid does 
+** not change (for a normal rowid table) or the PRIMARY KEY does not
+** change (for a WITHOUT ROWID table) in which case the old data is
+** not needed.
+**
+** For an INSERT (isUpdate==0), pkChng is just a boolean that indicates
+** whether or not the rowid was explicitly specified as part of the
+** INSERT statement.  If pkChng is zero, it means that the either rowid
+** is computed automatically or that the table is a WITHOUT ROWID table
+** and has no rowid.  On an INSERT, pkChng will only be true if the
+** INSERT statement provides an integer value for either the rowid
+** column or its INTEGER PRIMARY KEY alias.
+**
+** The code generated by this routine will store new index entries into
 ** registers identified by aRegIdx[].  No index entry is created for
 ** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
 ** the same as the order of indices on the linked list of indices
-** attached to the table.
+** at pTab->pIndex.
+**
+** The caller must have already opened writeable cursors on the main
+** table and all applicable indices (that is to say, all indices for which
+** aRegIdx[] is not zero).  iDataCur is the cursor for the main table when
+** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
+** index when operating on a WITHOUT ROWID table.  iIdxCur is the cursor
+** for the first index in the pTab->pIndex list.  Cursors for other indices
+** are at iIdxCur+N for the N-th element of the pTab->pIndex list.
 **
 ** This routine also generates code to check constraints.  NOT NULL,
 ** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
@@ -1162,22 +1173,23 @@ insert_cleanup:
 **  Constraint type  Action       What Happens
 **  ---------------  ----------   ----------------------------------------
 **  any              ROLLBACK     The current transaction is rolled back and
-**                                sqlite3_exec() returns immediately with a
+**                                sqlite3_step() returns immediately with a
 **                                return code of SQLITE_CONSTRAINT.
 **
 **  any              ABORT        Back out changes from the current command
 **                                only (do not do a complete rollback) then
-**                                cause sqlite3_exec() to return immediately
+**                                cause sqlite3_step() to return immediately
 **                                with SQLITE_CONSTRAINT.
 **
-**  any              FAIL         Sqlite3_exec() returns immediately with a
+**  any              FAIL         Sqlite3_step() returns immediately with a
 **                                return code of SQLITE_CONSTRAINT.  The
 **                                transaction is not rolled back and any
-**                                prior changes are retained.
+**                                changes to prior rows are retained.
 **
-**  any              IGNORE       The record number and data is popped from
-**                                the stack and there is an immediate jump
-**                                to label ignoreDest.
+**  any              IGNORE       The attempt in insert or update the current
+**                                row is skipped, without throwing an error.
+**                                Processing continues with the next row.
+**                                (There is an immediate jump to ignoreDest.)
 **
 **  NOT NULL         REPLACE      The NULL value is replace by the default
 **                                value for that column.  If the default value
@@ -1192,50 +1204,44 @@ insert_cleanup:
 ** Or if overrideError==OE_Default, then the pParse->onError parameter
 ** is used.  Or if pParse->onError==OE_Default then the onError value
 ** for the constraint is used.
-**
-** The calling routine must open a read/write cursor for pTab with
-** cursor number "baseCur".  All indices of pTab must also have open
-** read/write cursors with cursor number baseCur+i for the i-th cursor.
-** Except, if there is no possibility of a REPLACE action then
-** cursors do not need to be open for indices where aRegIdx[i]==0.
 */
 void sqlite3GenerateConstraintChecks(
-  Parse *pParse,      /* The parser context */
-  Table *pTab,        /* the table into which we are inserting */
-  int iDataCur,       /* Cursor of the canonical data tree */
-  int iIdxCur,        /* First index cursor */
-  int regRowid,       /* First register in a range holding values to insert */
-  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
-  int pkChng,         /* Non-zero if the rowid or PRIMARY KEY changed */
-  int isUpdate,       /* True for UPDATE, False for INSERT */
-  int overrideError,  /* Override onError to this if not OE_Default */
-  int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
-  int *pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
+  Parse *pParse,       /* The parser context */
+  Table *pTab,         /* The table being inserted or updated */
+  int iDataCur,        /* Canonical data cursor (main table or PK index) */
+  int iIdxCur,         /* First index cursor */
+  int regNewData,      /* First register in a range holding values to insert */
+  int *aRegIdx,        /* Register used by each index.  0 for unused indices */
+  int pkChng,          /* Non-zero if the rowid or PRIMARY KEY changed */
+  int isUpdate,        /* True for UPDATE, False for INSERT */
+  int overrideError,   /* Override onError to this if not OE_Default */
+  int ignoreDest,      /* Jump to this label on an OE_Ignore resolution */
+  int *pbMayReplace    /* OUT: Set to true if constraint may cause a replace */
 ){
-  int i;              /* loop counter */
-  Vdbe *v;            /* VDBE under constrution */
-  int nCol;           /* Number of columns */
-  int onError;        /* Conflict resolution strategy */
-  int j1;             /* Addresss of jump instruction */
-  int ix;             /* Index loop counter */
-  int regData;        /* Register containing first data column */
+  int i;               /* loop counter */
+  Vdbe *v;             /* VDBE under constrution */
+  int nCol;            /* Number of columns */
+  int onError;         /* Conflict resolution strategy */
+  int j1;              /* Addresss of jump instruction */
+  int ix;              /* Index loop counter */
   Index *pIdx;         /* Pointer to one of the indices */
   Index *pPk = 0;      /* The PRIMARY KEY index */
   sqlite3 *db;         /* Database connection */
   int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
-  int regOldPk;        /* Previous rowid or PRIMARY KEY value */
+  int regOldData;      /* Previous rowid and table data */
   int nPkField;        /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
 
-  regOldPk = (pkChng && isUpdate) ? pkChng : regRowid;
+  regOldData = (pkChng && isUpdate) ? pkChng : regNewData;
   db = pParse->db;
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
   nCol = pTab->nCol;
-  regData = regRowid + 1;
-
-  /* For WITHOUT ROWID tables, we'll need to know the Index and the cursor
-  ** number for the PRIMARY KEY index */
+  
+  /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
+  ** normal rowid tables.  nPkField is the number of key fields in the 
+  ** pPk index or 1 for a rowid table.  In other words, nPkField is the
+  ** number of fields in the true primary key of the table. */
   if( HasRowid(pTab) ){
     pPk = 0;
     nPkField = 1;
@@ -1246,7 +1252,7 @@ void sqlite3GenerateConstraintChecks(
 
   /* Record that this module has started */
   VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
-                     iDataCur, iIdxCur, regRowid, pkChng, regOldPk));
+                     iDataCur, iIdxCur, regNewData, regOldData, pkChng));
 
   /* Test all NOT NULL constraints.
   */
@@ -1274,20 +1280,20 @@ void sqlite3GenerateConstraintChecks(
       case OE_Fail: {
         char *zMsg;
         sqlite3VdbeAddOp3(v, OP_HaltIfNull,
-                          SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
+                          SQLITE_CONSTRAINT_NOTNULL, onError, regNewData+1+i);
         zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
                               pTab->zName, pTab->aCol[i].zName);
         sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
         break;
       }
       case OE_Ignore: {
-        sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
+        sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
         break;
       }
       default: {
         assert( onError==OE_Replace );
-        j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
-        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);
+        j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
+        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
         sqlite3VdbeJumpHere(v, j1);
         break;
       }
@@ -1299,7 +1305,7 @@ void sqlite3GenerateConstraintChecks(
 #ifndef SQLITE_OMIT_CHECK
   if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
     ExprList *pCheck = pTab->pCheck;
-    pParse->ckBase = regData;
+    pParse->ckBase = regNewData+1;
     onError = overrideError!=OE_Default ? overrideError : OE_Abort;
     for(i=0; i<pCheck->nExpr; i++){
       int allOk = sqlite3VdbeMakeLabel(v);
@@ -1324,7 +1330,8 @@ void sqlite3GenerateConstraintChecks(
 
   /* If there is an INTEGER PRIMARY KEY, make sure the primary key
   ** of the new record does not previously exist.  Except, if this
-  ** is an UPDATE and the primary key is not changing, that is OK.
+  ** is an UPDATE and the primary key is not changing, then obviously
+  ** it is OK for the previous rowid to exist in that case.
   **
   ** This block only runs for tables that have a rowid.
   */
@@ -1339,9 +1346,9 @@ void sqlite3GenerateConstraintChecks(
     }
 
     if( isUpdate ){
-      sqlite3VdbeAddOp3(v, OP_Eq, regRowid, addrRowidOk, pkChng);
+      sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
     }
-    sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regRowid);
+    sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
     switch( onError ){
       default: {
         onError = OE_Abort;
@@ -1384,7 +1391,7 @@ void sqlite3GenerateConstraintChecks(
         if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
           sqlite3MultiWrite(pParse);
           sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
-                                   regRowid, 1, 0, OE_Replace);
+                                   regNewData, 1, 0, OE_Replace);
         }else if( pTab->pIndex ){
           sqlite3MultiWrite(pParse);
           sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
@@ -1406,37 +1413,41 @@ void sqlite3GenerateConstraintChecks(
   ** Compute the revised record entries for indices as we go.
   */
   for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
-    int regIdx;
-    int regR;
-    int iThisCur = iIdxCur+ix;
-    int addrUniqueOk = sqlite3VdbeMakeLabel(v);
+    int regIdx;          /* Range of registers hold conent for pIdx */
+    int regR;            /* Range of registers holding conflicting PK */
+    int iThisCur;        /* Cursor for this UNIQUE index */
+    int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */
 
     if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */
+    iThisCur = iIdxCur+ix;
+    addrUniqueOk = sqlite3VdbeMakeLabel(v);
 
     if( pIdx->pPartIdxWhere ){
       sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
-      pParse->ckBase = regData;
+      pParse->ckBase = regNewData+1;
       sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
                          SQLITE_JUMPIFNULL);
       pParse->ckBase = 0;
     }
 
-    /* Create a key for accessing the index entry */
+    /* Create a record for this index entry as it should appear after
+    ** the insert or update. */
     regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
     for(i=0; i<pIdx->nColumn; i++){
-      i16 iField = pIdx->aiColumn[i];
+      int iField = pIdx->aiColumn[i];
       if( iField<0 || iField==pTab->iPKey ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
+        iField = regNewData;
       }else{
-        sqlite3VdbeAddOp2(v, OP_SCopy, regData+iField, regIdx+i);
+        iField += regNewData + 1;
       }
+      sqlite3VdbeAddOp2(v, OP_SCopy, iField, regIdx+i);
     }
     sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
     sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
     VdbeComment((v, "for %s", pIdx->zName));
     sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
 
-    /* Find out what action to take in case there is an indexing conflict */
+    /* Find out what action to take in case there is a uniqueness conflict */
     onError = pIdx->onError;
     if( onError==OE_None ){ 
       sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
@@ -1458,10 +1469,10 @@ void sqlite3GenerateConstraintChecks(
     sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
                          regIdx, pIdx->nKeyCol);
     if( HasRowid(pTab) ){
+      sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
       /* Conflict only if the rowid of the existing index entry
       ** is different from old-rowid */
-      sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
-      sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldPk);
+      sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
     }else{
       /* Extract the PRIMARY KEY from the end of the index entry and
       ** store it in register regR..regR+nPk-1 */
@@ -1478,10 +1489,10 @@ void sqlite3GenerateConstraintChecks(
         if( isUpdate ){
           int addrPkConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
           for(i=0; i<pPk->nKeyCol-1; i++){
-            sqlite3VdbeAddOp3(v, OP_Ne, regOldPk+pPk->aiColumn[i]+1,
+            sqlite3VdbeAddOp3(v, OP_Ne, regOldData+pPk->aiColumn[i]+1,
                               addrPkConflict, regIdx+i);
           }
-          sqlite3VdbeAddOp3(v, OP_Eq, regOldPk+pPk->aiColumn[i]+1,
+          sqlite3VdbeAddOp3(v, OP_Eq, regOldData+pPk->aiColumn[i]+1,
                             addrUniqueOk, regIdx+i);
         }
       }else{
@@ -1492,10 +1503,10 @@ void sqlite3GenerateConstraintChecks(
         assert( pIdx->nKeyCol + pPk->nKeyCol == pIdx->nColumn );
         for(i=0; i<pPk->nKeyCol-1; i++){
           sqlite3VdbeAddOp3(v, OP_Ne,
-                            regOldPk+pPk->aiColumn[i], addrConflict, regR+i);
+                           regOldData+pPk->aiColumn[i]+1, addrConflict, regR+i);
         }
         sqlite3VdbeAddOp3(v, OP_Eq,
-                          regOldPk+pPk->aiColumn[i], addrUniqueOk, regR+i);
+                          regOldData+pPk->aiColumn[i]+1, addrUniqueOk, regR+i);
       }
     }
     sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
@@ -1560,7 +1571,7 @@ void sqlite3GenerateConstraintChecks(
 /*
 ** This routine generates code to finish the INSERT or UPDATE operation
 ** that was started by a prior call to sqlite3GenerateConstraintChecks.
-** A consecutive range of registers starting at regRowid contains the
+** A consecutive range of registers starting at regNewData contains the
 ** rowid and the content to be inserted.
 **
 ** The arguments to this routine should be the same as the first six
@@ -1571,18 +1582,18 @@ void sqlite3CompleteInsertion(
   Table *pTab,        /* the table into which we are inserting */
   int iDataCur,       /* Cursor of the canonical data source */
   int iIdxCur,        /* First index cursor */
-  int regRowid,       /* Range of content */
+  int regNewData,     /* Range of content */
   int *aRegIdx,       /* Register used by each index.  0 for unused indices */
   int isUpdate,       /* True for UPDATE, False for INSERT */
   int appendBias,     /* True if this is likely to be an append */
   int useSeekResult   /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
 ){
-  int i;
-  Vdbe *v;
-  Index *pIdx;
-  u8 pik_flags;
-  int regData;
-  int regRec;
+  Vdbe *v;            /* Prepared statements under construction */
+  Index *pIdx;        /* An index being inserted or updated */
+  u8 pik_flags;       /* flag values passed to the btree insert */
+  int regData;        /* Content registers (after the rowid) */
+  int regRec;         /* Register holding assemblied record for the table */
+  int i;              /* Loop counter */
 
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
@@ -1598,7 +1609,7 @@ void sqlite3CompleteInsertion(
     }
   }
   if( !HasRowid(pTab) ) return;
-  regData = regRowid + 1;
+  regData = regNewData + 1;
   regRec = sqlite3GetTempReg(pParse);
   sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
   sqlite3TableAffinityStr(v, pTab);
@@ -1615,7 +1626,7 @@ void sqlite3CompleteInsertion(
   if( useSeekResult ){
     pik_flags |= OPFLAG_USESEEKRESULT;
   }
-  sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regRowid);
+  sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
   if( !pParse->nested ){
     sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
   }
index 5516c6dee1f8f9f1d77b73d7c0e09d529aaa3903..16654f06d40f9f519dbedb45c51f613d1fb7202f 100644 (file)
@@ -1917,7 +1917,7 @@ void sqlite3Pragma(
           sqlite3VdbeJumpHere(v, jmp2);
           sqlite3VdbeResolveLabel(v, jmp3);
         }
-        sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop);
+        sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop);
         sqlite3VdbeJumpHere(v, loopTop-1);
 #ifndef SQLITE_OMIT_BTREECOUNT
         sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, 
index 9bb2ecb0cb1453641e3cf80e423756ac7d7a6724..2dc20ca94ac6373e730b1fe86c2b762d812f2f81 100644 (file)
@@ -59,6 +59,6 @@ do_test without_rowid1-1.21 {
 do_execsql_test without_rowid1-1.22 {
   REPLACE INTO t1 VALUES('dynamic','phone','flipper','harvard');
   SELECT *, '|' FROM t1 ORDER BY c, a;
-} {}
+} {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic phone flipper harvard | journal sherman gamma patriot |}
 
 finish_test