📄 vdbe.c
字号:
if( pTos->flags & MEM_Int ){ v = pTos->i + (pOp->p1!=0); }else{ Realify(pTos); v = (int)pTos->r; if( pTos->r>(double)v ) v++; if( pOp->p1 && pTos->r==(double)v ) v++; } Release(pTos); pTos->i = v; pTos->flags = MEM_Int; break;}/* Opcode: MustBeInt P1 P2 *** ** Force the top of the stack to be an integer. If the top of the** stack is not an integer and cannot be converted into an integer** with out data loss, then jump immediately to P2, or if P2==0** raise an SQLITE_MISMATCH exception.**** If the top of the stack is not an integer and P2 is not zero and** P1 is 1, then the stack is popped. In all other cases, the depth** of the stack is unchanged.*/case OP_MustBeInt: { assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); if( (pTos->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ if( pOp->p1 ) popStack(&pTos, 1); pc = pOp->p2 - 1; } }else{ Release(pTos); pTos->flags = MEM_Int; } break;}/* Opcode: Eq P1 P2 P3**** Pop the top two elements from the stack. If they are equal, then** jump to instruction P2. Otherwise, continue to the next instruction.**** The least significant byte of P1 may be either 0x00 or 0x01. If either** operand is NULL (and thus if the result is unknown) then take the jump** only if the least significant byte of P1 is 0x01.**** The second least significant byte of P1 must be an affinity character -** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values** according to the affinity before the comparison is made. If the byte is** 0x00, then numeric affinity is used.**** Once any conversions have taken place, and neither value is NULL, ** the values are compared. If both values are blobs, or both are text,** then memcmp() is used to determine the results of the comparison. If** both values are numeric, then a numeric comparison is used. If the** two values are of different types, then they are inequal.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.**** If P3 is not NULL it is a pointer to a collating sequence (a CollSeq** structure) that defines how to compare text.*//* Opcode: Ne P1 P2 P3**** This works just like the Eq opcode except that the jump is taken if** the operands from the stack are not equal. See the Eq opcode for** additional information.*//* Opcode: Lt P1 P2 P3**** This works just like the Eq opcode except that the jump is taken if** the 2nd element down on the stack is less than the top of the stack.** See the Eq opcode for additional information.*//* Opcode: Le P1 P2 P3**** This works just like the Eq opcode except that the jump is taken if** the 2nd element down on the stack is less than or equal to the** top of the stack. See the Eq opcode for additional information.*//* Opcode: Gt P1 P2 P3**** This works just like the Eq opcode except that the jump is taken if** the 2nd element down on the stack is greater than the top of the stack.** See the Eq opcode for additional information.*//* Opcode: Ge P1 P2 P3**** This works just like the Eq opcode except that the jump is taken if** the 2nd element down on the stack is greater than or equal to the** top of the stack. See the Eq opcode for additional information.*/case OP_Eq: /* same as TK_EQ */case OP_Ne: /* same as TK_NE */case OP_Lt: /* same as TK_LT */case OP_Le: /* same as TK_LE */case OP_Gt: /* same as TK_GT */case OP_Ge: { /* same as TK_GE */ Mem *pNos; int flags; int res; char affinity; pNos = &pTos[-1]; flags = pTos->flags|pNos->flags; /* If either value is a NULL P2 is not zero, take the jump if the least ** significant byte of P1 is true. If P2 is zero, then push a NULL onto ** the stack. */ if( flags&MEM_Null ){ popStack(&pTos, 2); if( pOp->p2 ){ if( (pOp->p1&0xFF) ) pc = pOp->p2-1; }else{ pTos++; pTos->flags = MEM_Null; } break; } affinity = (pOp->p1>>8)&0xFF; if( affinity ){ applyAffinity(pNos, affinity, db->enc); applyAffinity(pTos, affinity, db->enc); } assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; case OP_Ne: res = res!=0; break; case OP_Lt: res = res<0; break; case OP_Le: res = res<=0; break; case OP_Gt: res = res>0; break; default: res = res>=0; break; } popStack(&pTos, 2); if( pOp->p2 ){ if( res ){ pc = pOp->p2-1; } }else{ pTos++; pTos->flags = MEM_Int; pTos->i = res; } break;}/* Opcode: And * * ***** Pop two values off the stack. Take the logical AND of the** two values and push the resulting boolean value back onto the** stack. *//* Opcode: Or * * ***** Pop two values off the stack. Take the logical OR of the** two values and push the resulting boolean value back onto the** stack. */case OP_And: /* same as TK_AND */case OP_Or: { /* same as TK_OR */ Mem *pNos = &pTos[-1]; int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ assert( pNos>=p->aStack ); if( pTos->flags & MEM_Null ){ v1 = 2; }else{ Integerify(pTos); v1 = pTos->i==0; } if( pNos->flags & MEM_Null ){ v2 = 2; }else{ Integerify(pNos); v2 = pNos->i==0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = or_logic[v1*3+v2]; } popStack(&pTos, 2); pTos++; if( v1==2 ){ pTos->flags = MEM_Null; }else{ pTos->i = v1==0; pTos->flags = MEM_Int; } break;}/* Opcode: Negative * * ***** Treat the top of the stack as a numeric quantity. Replace it** with its additive inverse. If the top of the stack is NULL** its value is unchanged.*//* Opcode: AbsValue * * ***** Treat the top of the stack as a numeric quantity. Replace it** with its absolute value. If the top of the stack is NULL** its value is unchanged.*/case OP_Negative: /* same as TK_UMINUS */case OP_AbsValue: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Real ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; }else if( pTos->flags & MEM_Int ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->i<0 ){ pTos->i = -pTos->i; } pTos->flags = MEM_Int; }else if( pTos->flags & MEM_Null ){ /* Do nothing */ }else{ Realify(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; } break;}/* Opcode: Not * * ***** Interpret the top of the stack as a boolean value. Replace it** with its complement. If the top of the stack is NULL its value** is unchanged.*/case OP_Not: { /* same as TK_NOT */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); pTos->i = !pTos->i; pTos->flags = MEM_Int; break;}/* Opcode: BitNot * * ***** Interpret the top of the stack as an value. Replace it** with its ones-complement. If the top of the stack is NULL its** value is unchanged.*/case OP_BitNot: { /* same as TK_BITNOT */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); pTos->i = ~pTos->i; pTos->flags = MEM_Int; break;}/* Opcode: Noop * * ***** Do nothing. This instruction is often useful as a jump** destination.*/case OP_Noop: { break;}/* Opcode: If P1 P2 ***** Pop a single boolean from the stack. If the boolean popped is** true, then jump to p2. Otherwise continue to the next instruction.** An integer is false if zero and true otherwise. A string is** false if it has zero length and true otherwise.**** If the value popped of the stack is NULL, then take the jump if P1** is true and fall through if P1 is false.*//* Opcode: IfNot P1 P2 ***** Pop a single boolean from the stack. If the boolean popped is** false, then jump to p2. Otherwise continue to the next instruction.** An integer is false if zero and true otherwise. A string is** false if it has zero length and true otherwise.**** If the value popped of the stack is NULL, then take the jump if P1** is true and fall through if P1 is false.*/case OP_If:case OP_IfNot: { int c; assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ){ c = pOp->p1; }else{ c = sqlite3VdbeIntValue(pTos); if( pOp->opcode==OP_IfNot ) c = !c; } Release(pTos); pTos--; if( c ) pc = pOp->p2-1; break;}/* Opcode: IsNull P1 P2 ***** If any of the top abs(P1) values on the stack are NULL, then jump** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack** unchanged.*/case OP_IsNull: { /* same as TK_ISNULL */ int i, cnt; Mem *pTerm; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; pTerm = &pTos[1-cnt]; assert( pTerm>=p->aStack ); for(i=0; i<cnt; i++, pTerm++){ if( pTerm->flags & MEM_Null ){ pc = pOp->p2-1; break; } } if( pOp->p1>0 ) popStack(&pTos, cnt); break;}/* Opcode: NotNull P1 P2 ***** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the** stack if P1 times if P1 is greater than zero. If P1 is less than** zero then leave the stack unchanged.*/case OP_NotNull: { /* same as TK_NOTNULL */ int i, cnt; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; assert( &pTos[1-cnt] >= p->aStack ); for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){} if( i>=cnt ) pc = pOp->p2-1; if( pOp->p1>0 ) popStack(&pTos, cnt); break;}/* Opcode: SetNumColumns P1 P2 ***** Before the OP_Column opcode can be executed on a cursor, this** opcode must be called to set the number of fields in the table.**** This opcode sets the number of columns for cursor P1 to P2.**** If OP_KeyAsData is to be applied to cursor P1, it must be executed** before this op-code.*/case OP_SetNumColumns: { Cursor *pC; assert( (pOp->p1)<p->nCursor ); assert( p->apCsr[pOp->p1]!=0 ); pC = p->apCsr[pOp->p1]; pC->nField = pOp->p2; if( (!pC->keyAsData && pC->zeroData) || (pC->keyAsData && pC->intKey) ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } break;}/* Opcode: Column P1 P2 ***** Interpret the data that cursor P1 points to as a structure built using** the MakeRecord instruction. (See the MakeRecord opcode for additional** information about the format of the data.) Push onto the stack the value** of the P2-th column contained in the data. If there are less that (P2+1) ** values in the record, push a NULL onto the stack.**** If the KeyAsData opcode has previously executed on this cursor, then the** field might be extracted from the key rather than the data.**** If P1 is negative, then the record is stored on the stack rather than in** a table. For P1==-1, the top of the stack is used. For P1==-2, the** next on the stack is used. And so forth. The value pushed is always** just a pointer into the record which is stored further down on the** stack. The column value is not copied. The number of columns in the** record is stored on the stack just above the record itself.*/case OP_Column: { u32 payloadSize; /* Number of bytes in the record */ int p1 = pOp->p1; /* P1 value of the opcode */ int p2 = pOp->p2; /* column number to retrieve */ Cursor *pC = 0; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ u32 nField; /* number of fields in the record */ u32 szHdr; /* Number of bytes in the record header */ int len; /* The length of the serialized data for the column */ int offset = 0; /* Offset into the data */ int idx; /* Index into the header */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1<p->nCursor ); pTos++; pTos->flags = MEM_Null; /* This block sets the variable payloadSize to be the total number of ** bytes in the record. ** ** zRec is set to be the complete text of the record if it is available.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -