diff options
Diffstat (limited to 'src/vdbe.c')
-rw-r--r-- | src/vdbe.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/src/vdbe.c b/src/vdbe.c index e7fa05037..64ae54e3d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -764,7 +764,8 @@ case OP_Goto: { /* jump */ ** Write the current address onto register P1 ** and then jump to address P2. */ -case OP_Gosub: { /* jump, in1 */ +case OP_Gosub: { /* jump */ + assert( pOp->p1>0 && pOp->p1<=p->nMem ); pIn1 = &aMem[pOp->p1]; assert( (pIn1->flags & MEM_Dyn)==0 ); memAboutToChange(p, pIn1); @@ -961,12 +962,25 @@ case OP_String: { /* out2-prerelease */ break; } -/* Opcode: Null * P2 * * * +/* Opcode: Null * P2 P3 * * ** -** Write a NULL into register P2. +** Write a NULL into registers P2. If P3 greater than P2, then also write +** NULL into register P3 and ever register in between P2 and P3. If P3 +** is less than P2 (typically P3 is zero) then only register P2 is +** set to NULL */ case OP_Null: { /* out2-prerelease */ + int cnt; + cnt = pOp->p3-pOp->p2; + assert( pOp->p3<=p->nMem ); pOut->flags = MEM_Null; + while( cnt>0 ){ + pOut++; + memAboutToChange(p, pOut); + MemReleaseExt(pOut); + pOut->flags = MEM_Null; + cnt--; + } break; } @@ -2023,27 +2037,33 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ /* Opcode: Once P1 P2 * * * ** -** Jump to P2 if the value in register P1 is a not null or zero. If -** the value is NULL or zero, fall through and change the P1 register -** to an integer 1. +** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, +** set the flag and fall through to the next instruction. ** -** When P1 is not used otherwise in a program, this opcode falls through -** once and jumps on all subsequent invocations. It is the equivalent -** of "OP_If P1 P2", followed by "OP_Integer 1 P1". +** See also: JumpOnce */ +case OP_Once: { /* jump */ + assert( pOp->p1<p->nOnceFlag ); + if( p->aOnceFlag[pOp->p1] ){ + pc = pOp->p2-1; + }else{ + p->aOnceFlag[pOp->p1] = 1; + } + break; +} + /* Opcode: If P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value -** in P1 is NULL then take the jump if P3 is true. +** in P1 is NULL then take the jump if P3 is non-zero. */ /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value -** is considered true if it has a numeric value of zero. If the value -** in P1 is NULL then take the jump if P3 is true. +** is considered false if it has a numeric value of zero. If the value +** in P1 is NULL then take the jump if P3 is zero. */ -case OP_Once: /* jump, in1 */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ int c; @@ -2060,12 +2080,6 @@ case OP_IfNot: { /* jump, in1 */ } if( c ){ pc = pOp->p2-1; - }else if( pOp->opcode==OP_Once ){ - assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 ); - memAboutToChange(p, pIn1); - pIn1->flags = MEM_Int; - pIn1->u.i = 1; - REGISTER_TRACE(pOp->p1, pIn1); } break; } @@ -5071,7 +5085,6 @@ case OP_Program: { /* jump */ pProgram = pOp->p4.pProgram; pRt = &aMem[pOp->p3]; - assert( memIsValid(pRt) ); assert( pProgram->nOp>0 ); /* If the p5 flag is clear, then recursive invocation of triggers is @@ -5110,7 +5123,8 @@ case OP_Program: { /* jump */ nMem = pProgram->nMem + pProgram->nCsr; nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) - + pProgram->nCsr * sizeof(VdbeCursor *); + + pProgram->nCsr * sizeof(VdbeCursor *) + + pProgram->nOnce * sizeof(u8); pFrame = sqlite3DbMallocZero(db, nByte); if( !pFrame ){ goto no_mem; @@ -5130,10 +5144,12 @@ case OP_Program: { /* jump */ pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; + pFrame->aOnceFlag = p->aOnceFlag; + pFrame->nOnceFlag = p->nOnceFlag; pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ - pMem->flags = MEM_Null; + pMem->flags = MEM_Invalid; pMem->db = db; } }else{ @@ -5155,7 +5171,11 @@ case OP_Program: { /* jump */ p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; + p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; + p->nOnceFlag = pProgram->nOnce; + p->nOp = pProgram->nOp; pc = -1; + memset(p->aOnceFlag, 0, p->nOnceFlag); break; } |