From: drh Date: Thu, 31 Oct 2013 15:37:49 +0000 (+0000) Subject: Improved comments and variable names in infrastructure routines of UPDATE, X-Git-Tag: version-3.8.2~137^2~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6934fc7b6ffde4b1e24e277f0ac6fb783790e5db;p=thirdparty%2Fsqlite.git Improved comments and variable names in infrastructure routines of UPDATE, DELETE, and INSERT. FossilOrigin-Name: ad90e762e51384ac7c311f08a641419f03f6d3f0 --- diff --git a/manifest b/manifest index 0c22692110..70184834ba 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 00f527cef5..ec60d0ac81 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -deacbd21b50cc8c63a1572d14a4bbc7af4052d37 \ No newline at end of file +ad90e762e51384ac7c311f08a641419f03f6d3f0 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index fc0d4813dd..4d27f98f94 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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); diff --git a/src/insert.c b/src/insert.c index d58a9baea9..199db1e845 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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; inExpr; 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; inColumn; 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; inKeyCol-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; inKeyCol-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); } diff --git a/src/pragma.c b/src/pragma.c index 5516c6dee1..16654f06d4 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -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, diff --git a/test/without_rowid1.test b/test/without_rowid1.test index 9bb2ecb0cb..2dc20ca94a 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -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