diff options
author | drh <drh@noemail.net> | 2013-10-31 20:34:06 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-10-31 20:34:06 +0000 |
commit | 313619f5725632e4ea69b5f5d2b4ba9a50a31c3a (patch) | |
tree | 6c1679eac506105f99099c3057fbf1c1449ee7da /src | |
parent | ee0ec8e1db6049e6c38c94fa08201ca73ef3f60a (diff) | |
download | sqlite-313619f5725632e4ea69b5f5d2b4ba9a50a31c3a.tar.gz sqlite-313619f5725632e4ea69b5f5d2b4ba9a50a31c3a.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/delete.c | 8 | ||||
-rw-r--r-- | src/expr.c | 4 | ||||
-rw-r--r-- | src/update.c | 45 | ||||
-rw-r--r-- | src/vdbe.c | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 13 |
5 files changed, 47 insertions, 25 deletions
diff --git a/src/delete.c b/src/delete.c index 4d27f98f9..55688409b 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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()")); } /* diff --git a/src/expr.c b/src/expr.c index 24d866f19..4a321dbc4 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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); diff --git a/src/update.c b/src/update.c index 5c92f6fd6..c06fcd2a0 100644 --- a/src/update.c +++ b/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); diff --git a/src/vdbe.c b/src/vdbe.c index 2f648a76a..b72ef40ca 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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. diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e2ef4eee1..8a1eea1b8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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--; } } |