Add assert() statements on the nExtraDelete variable in vdbe.c to try to verify
that the FORDELETE and IDXDELETE flags are being generated correctly. Those flags are not currently generated correctly, and so the assert()s trip on this check-in. FossilOrigin-Name: dde1db0dd2e2cf04706117629756c352b178ebb8
This commit is contained in:
+7
-4
@@ -479,13 +479,12 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
if( !isView ){
|
||||
int iAddrOnce = 0;
|
||||
u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE);
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
testcase( IsVirtual(pTab) );
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur,
|
||||
aToOpen, &iDataCur, &iIdxCur);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
|
||||
iTabCur, aToOpen, &iDataCur, &iIdxCur);
|
||||
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
||||
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
||||
if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
|
||||
@@ -724,9 +723,13 @@ void sqlite3GenerateRowDelete(
|
||||
if( count ){
|
||||
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
|
||||
}
|
||||
if( eMode!=ONEPASS_OFF ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_IDXDELETE);
|
||||
p5 = OPFLAG_IDXDELETE;
|
||||
}
|
||||
if( iIdxNoSeek>=0 ){
|
||||
sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
|
||||
if( eMode!=ONEPASS_OFF ) p5 = OPFLAG_IDXDELETE;
|
||||
p5 = 0;
|
||||
}
|
||||
if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;
|
||||
sqlite3VdbeChangeP5(v, p5);
|
||||
|
||||
+6
-5
@@ -1647,7 +1647,7 @@ int sqlite3OpenTableAndIndices(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Table *pTab, /* Table to be opened */
|
||||
int op, /* OP_OpenRead or OP_OpenWrite */
|
||||
u8 p5, /* P5 value for OP_Open* instructions */
|
||||
u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */
|
||||
int iBase, /* Use this for the table cursor, if there is one */
|
||||
u8 *aToOpen, /* If not NULL: boolean for each table and index */
|
||||
int *piDataCur, /* Write the database source cursor number here */
|
||||
@@ -1682,15 +1682,16 @@ int sqlite3OpenTableAndIndices(
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||
int iIdxCur = iBase++;
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
|
||||
*piDataCur = iIdxCur;
|
||||
}
|
||||
if( aToOpen==0 || aToOpen[i+1] ){
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
sqlite3VdbeChangeP5(v, p5);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
}
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
if( piDataCur ) *piDataCur = iIdxCur;
|
||||
}else{
|
||||
sqlite3VdbeChangeP5(v, p5);
|
||||
}
|
||||
}
|
||||
if( iBase>pParse->nTab ) pParse->nTab = iBase;
|
||||
return i;
|
||||
|
||||
+32
-2
@@ -551,6 +551,9 @@ int sqlite3VdbeExec(
|
||||
Op *pOp = aOp; /* Current operation */
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
Op *pOrigOp; /* Value of pOp at the top of the loop */
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
int nExtraDelete = 0; /* Verifies FORDELETE and IDXDELETE flags */
|
||||
#endif
|
||||
int rc = SQLITE_OK; /* Value to return */
|
||||
sqlite3 *db = p->db; /* The database */
|
||||
@@ -3392,6 +3395,9 @@ case OP_OpenWrite:
|
||||
pCur->nullRow = 1;
|
||||
pCur->isOrdered = 1;
|
||||
pCur->pgnoRoot = p2;
|
||||
#ifdef SQLITE_DEBUG
|
||||
pCur->wrFlag = wrFlag;
|
||||
#endif
|
||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor);
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
/* Set the VdbeCursor.isTable variable. Previous versions of
|
||||
@@ -4390,10 +4396,24 @@ case OP_Delete: {
|
||||
assert( pC->movetoTarget==iKey );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Only flags that can be set are SAVEPOISTION and IDXDELETE */
|
||||
assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 );
|
||||
assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION );
|
||||
assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE );
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pC->isEphemeral==0
|
||||
&& (pOp->p5 & OPFLAG_IDXDELETE)==0
|
||||
&& (pC->wrFlag & OPFLAG_FORDELETE)==0
|
||||
){
|
||||
nExtraDelete++;
|
||||
}
|
||||
if( pOp->p2 & OPFLAG_NCHANGE ){
|
||||
nExtraDelete--;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
|
||||
@@ -4939,7 +4959,16 @@ case OP_IdxDelete: {
|
||||
r.default_rc = 0;
|
||||
r.aMem = &aMem[pOp->p2];
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) );
|
||||
if( pC->isEphemeral==0
|
||||
&& (pOp->p5 & OPFLAG_IDXDELETE)==0
|
||||
&& (pC->wrFlag & OPFLAG_FORDELETE)==0
|
||||
){
|
||||
nExtraDelete++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
|
||||
if( rc==SQLITE_OK && res==0 ){
|
||||
@@ -6762,6 +6791,7 @@ vdbe_return:
|
||||
testcase( nVmStep>0 );
|
||||
p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
|
||||
sqlite3VdbeLeave(p);
|
||||
assert( nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 );
|
||||
return rc;
|
||||
|
||||
/* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
|
||||
|
||||
@@ -82,6 +82,7 @@ struct VdbeCursor {
|
||||
u8 isTable; /* True for rowid tables. False for indexes */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 seekOp; /* Most recent seek operation on this cursor */
|
||||
u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
|
||||
#endif
|
||||
Bool isEphemeral:1; /* True for an ephemeral table */
|
||||
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
|
||||
|
||||
Reference in New Issue
Block a user