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
This commit is contained in:
parent
ee0ec8e1db
commit
313619f572
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sissues\swith\squering\sfrom\san\sauxiliary\sindex\sthat\smust\srefer\sback\sto\sthe\nPRIMARY\sKEY\sindex\sof\sa\sWITHOUT\sROWID\stable.
|
||||
D 2013-10-31T17:38:01.124
|
||||
C Fix\sthe\sSynopsis\son\sOP_Concat.\s\sAdded\stest_addop_breakpoint()\sduring\nSQLITE_DEBUG.\s\sEnhanced\ssqlite3VdbeChangeToNoop()\sto\somit\sthe\sinstruction\nif\sit\sis\sthe\smost\srecent\sadded.\s\sContinue\sto\sfix\sproblems\swith\sUPDATE\nand\sWITHOUT\sROWID.
|
||||
D 2013-10-31T20:34:06.322
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -173,8 +173,8 @@ F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c 0e10849258efbdab48b8679de19edd661859dc7d
|
||||
F src/expr.c 179b164b6ecee9cb2d33104d61cb7a8e1c0bf7a2
|
||||
F src/delete.c df1775ee33f40bc8feb37b2bfb59d792ff496359
|
||||
F src/expr.c ecc2b98eb75fe5533cfdfcca6b04cfe5f0c6001f
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
|
||||
F src/func.c 2c47b65e6e00e3e9374942f28254faf8adafe398
|
||||
@ -275,15 +275,15 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
|
||||
F src/trigger.c 53d6b5d50b3b23d4fcd0a36504feb5cff9aed716
|
||||
F src/update.c 3cabfcbd3e40e9c025fe772cf172ce24b6d53c45
|
||||
F src/update.c 5afafb5300b3ec2daf5d4876a13aa4e2e0e549df
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c ba7829e8a483a34e16ac7b13d4633c490d512459
|
||||
F src/vdbe.c 613af4c9ac24b1bf70fe35484502e74183492802
|
||||
F src/vdbe.h c18a2dd91c838601b867a214e43c5f66d5d001ba
|
||||
F src/vdbeInt.h 42dcff74dbeb2b071e569b53f885fc9c2e4b4cb0
|
||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||
F src/vdbeaux.c 717c8c2eb30641a75790311669ee0dfe5504ec56
|
||||
F src/vdbeaux.c cf6d0bc68fd1783747909cd14387bc06ac10a4e2
|
||||
F src/vdbeblob.c ef973d8d9f8170015343dd8824f795da675caa87
|
||||
F src/vdbemem.c 6087553f2c61c06c8e1ab3959a60e174d6240c98
|
||||
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
|
||||
@ -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 ad90e762e51384ac7c311f08a641419f03f6d3f0
|
||||
R ef34eedb5148ee0261de70fa65806b54
|
||||
P cff1f55c52ff57557d9b728a5cd830a367091794
|
||||
R e79e8c20b6bbceeb122a0ba8aa95ec94
|
||||
U drh
|
||||
Z da87d4852016fc159afe99674b5fb9ae
|
||||
Z 622837c1d15f3d4a0d2025f8d559acca
|
||||
|
@ -1 +1 @@
|
||||
cff1f55c52ff57557d9b728a5cd830a367091794
|
||||
9b6d9e106aaa3c2efb33d234d26cf08cd3c967b9
|
@ -407,7 +407,7 @@ void sqlite3DeleteFrom(
|
||||
|
||||
/* 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 @@ delete_from_cleanup:
|
||||
** 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 @@ void sqlite3GenerateRowIndexDelete(
|
||||
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 @@ void sqlite3GenerateRowIndexDelete(
|
||||
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
||||
}
|
||||
VdbeModuleComment((v, "END: GenRowIdxDel()"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2214,9 +2214,9 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
|
||||
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);
|
||||
|
45
src/update.c
45
src/update.c
@ -101,7 +101,6 @@ void sqlite3Update(
|
||||
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 @@ void sqlite3Update(
|
||||
** 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 @@ void sqlite3Update(
|
||||
** 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 @@ void sqlite3Update(
|
||||
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 @@ void sqlite3Update(
|
||||
*/
|
||||
#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 @@ void sqlite3Update(
|
||||
|
||||
/* 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 @@ void sqlite3Update(
|
||||
** 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 @@ void sqlite3Update(
|
||||
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 @@ void sqlite3Update(
|
||||
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 @@ void sqlite3Update(
|
||||
** 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 @@ void sqlite3Update(
|
||||
*/
|
||||
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 @@ void sqlite3Update(
|
||||
*/
|
||||
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 @@ void sqlite3Update(
|
||||
|
||||
/* 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);
|
||||
|
@ -1203,7 +1203,7 @@ case OP_ResultRow: {
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
@ -107,6 +107,17 @@ static int growOpArray(Vdbe *p){
|
||||
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 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
#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 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
memset(pOp, 0, sizeof(pOp[0]));
|
||||
pOp->opcode = OP_Noop;
|
||||
if( addr==p->nOp-1 ) p->nOp--;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user