static Op *opIterNext(VdbeOpIter *p){ Vdbe *v = p->v; Op *pRet = 0; Op *aOp; int nOp; if( p->iSub<=p->nSub ){ if( p->iSub==0 ){ aOp = v->aOp; nOp = v->nOp; }else{ aOp = p->apSub[p->iSub-1]->aOp; nOp = p->apSub[p->iSub-1]->nOp; } assert( p->iAddr<nOp ); pRet = &aOp[p->iAddr]; p->iAddr++; if( p->iAddr==nOp ){ p->iSub++; p->iAddr = 0; } if( pRet->p4type==P4_SUBPROGRAM ){ int nByte = (p->nSub+1)*sizeof(SubProgram*); int j; for(j=0; j<p->nSub; j++){ if( p->apSub[j]==pRet->p4.pProgram ) break; } if( j==p->nSub ){ p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte); if( !p->apSub ){ pRet = 0; }else{ p->apSub[p->nSub++] = pRet->p4.pProgram; } } } } return pRet; }
/* ** Check if the program stored in the VM associated with pParse may ** throw an ABORT exception (causing the statement, but not entire transaction ** to be rolled back). This condition is true if the main program or any ** sub-programs contains any of the following: ** ** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. ** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort. ** * OP_Destroy ** * OP_VUpdate ** * OP_VRename ** * OP_FkCounter with P2==0 (immediate foreign key constraint) ** ** Then check that the value of Parse.mayAbort is true if an ** ABORT may be thrown, or false otherwise. Return true if it does ** match, or false otherwise. This function is intended to be used as ** part of an assert statement in the compiler. Similar to: ** ** Debug.Assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); */ static int sqlite3VdbeAssertMayAbort( Vdbe v, int mayAbort ) { int hasAbort = 0; Op pOp; VdbeOpIter sIter; sIter = new VdbeOpIter();// memset( &sIter, 0, sizeof( sIter ) ); sIter.v = v; while ( ( pOp = opIterNext( sIter ) ) != null ) { int opcode = pOp.opcode; if ( opcode == OP_Destroy || opcode == OP_VUpdate || opcode == OP_VRename #if !SQLITE_OMIT_FOREIGN_KEY || ( opcode == OP_FkCounter && pOp.p1 == 0 && pOp.p2 == 1 ) #endif || ( ( opcode == OP_Halt || opcode == OP_HaltIfNull ) && ( pOp.p1 == SQLITE_CONSTRAINT && pOp.p2 == OE_Abort ) ) ) { hasAbort = 1; break; } } sIter.apSub = null;// sqlite3DbFree( v.db, sIter.apSub ); /* Return true if hasAbort==mayAbort. Or if a malloc failure occured. ** If malloc failed, then the while() loop above may not have iterated ** through all opcodes and hasAbort may be set incorrectly. Return ** true for this case to prevent the Debug.Assert() in the callers frame ** from failing. */ return ( hasAbort == mayAbort ) ? 1 : 0;//v.db.mallocFailed !=0|| hasAbort==mayAbort ); }
public bool AssertMayAbort(bool mayAbort) { VdbeOpIter sIter; sIter = new VdbeOpIter(); sIter.V = this; bool hasAbort = false; VdbeOp op; while ((op = OpIterNext(sIter)) != null) { OP opcode = (OP)op.Opcode; if (opcode == OP.Destroy || opcode == OP.VUpdate || opcode == OP.VRename #if !OMIT_FOREIGN_KEY || (opcode == OP.FkCounter && op.P1 == 0 && op.P2 == 1) #endif || ((opcode == OP.Halt || opcode == OP.HaltIfNull) && (op.P1 == (int)RC.CONSTRAINT && op.P2 == (int)OE.Abort))) { hasAbort = true; break; } } C._tagfree(Ctx, ref sIter.Subs.data); // Return true if hasAbort==mayAbort. Or if a malloc failure occurred. If malloc failed, then the while() loop above may not have iterated // through all opcodes and hasAbort may be set incorrectly. Return true for this case to prevent the assert() in the callers frame from failing. return (hasAbort == mayAbort) ? 1 : 0;//v.db.mallocFailed !=0|| hasAbort==mayAbort ); return (Ctx.MallocFailed || hasAbort == mayAbort); }
static Op opIterNext( VdbeOpIter p ) { Vdbe v = p.v; Op pRet = null; Op[] aOp; int nOp; if ( p.iSub <= p.nSub ) { if ( p.iSub == 0 ) { aOp = v.aOp; nOp = v.nOp; } else { aOp = p.apSub[p.iSub - 1].aOp; nOp = p.apSub[p.iSub - 1].nOp; } Debug.Assert( p.iAddr < nOp ); pRet = aOp[p.iAddr]; p.iAddr++; if ( p.iAddr == nOp ) { p.iSub++; p.iAddr = 0; } if ( pRet.p4type == P4_SUBPROGRAM ) { //int nByte = p.nSub + 1 ) * sizeof( SubProgram* ); int j; for ( j = 0; j < p.nSub; j++ ) { if ( p.apSub[j] == pRet.p4.pProgram ) break; } if ( j == p.nSub ) { Array.Resize( ref p.apSub, p.nSub + 1 );/// sqlite3DbReallocOrFree( v.db, p.apSub, nByte ); //if( null==p.apSub ){ // pRet = null; //}else{ p.apSub[p.nSub++] = pRet.p4.pProgram; //} } } } return pRet; }
static VdbeOp OpIterNext(VdbeOpIter p) { VdbeOp r = null; if (p.SubId <= p.Subs.length) { Vdbe v = p.V; array_t<VdbeOp> ops = (p.SubId == 0 ? v.Ops : p.Subs[p.SubId - 1].Ops); Debug.Assert(p.Addr < ops.length); r = ops[p.Addr]; p.Addr++; if (p.Addr == ops.length) { p.SubId++; p.Addr = 0; } if (r.P4Type == Vdbe.P4T.SUBPROGRAM) { int bytes = p.Subs.length + 1; int j; for (j = 0; j < p.Subs.length; j++) if (p.Subs[j] == r.P4.Program) break; if (j == p.Subs.length) { C._tagrealloc_or_free2(v.Ctx, ref p.Subs.data, bytes); p.Subs[p.Subs.length++] = r.P4.Program; } } } return r; }