📄 vdbe.c
字号:
**** Pop the top two elements from the stack. Convert both elements** to integers. Push back onto the stack the second element shifted** left by N bits where N is the top element on the stack.** If either operand is NULL, the result is NULL.*//* Opcode: ShiftRight * * ***** Pop the top two elements from the stack. Convert both elements** to integers. Push back onto the stack the second element shifted** right by N bits where N is the top element on the stack.** If either operand is NULL, the result is NULL.*/case OP_BitAnd: /* same as TK_BITAND, no-push */case OP_BitOr: /* same as TK_BITOR, no-push */case OP_ShiftLeft: /* same as TK_LSHIFT, no-push */case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */ Mem *pNos = &pTos[-1]; i64 a, b; assert( pNos>=p->aStack ); if( (pTos->flags | pNos->flags) & MEM_Null ){ popStack(&pTos, 2); pTos++; pTos->flags = MEM_Null; break; } a = sqlite3VdbeIntValue(pNos); b = sqlite3VdbeIntValue(pTos); switch( pOp->opcode ){ case OP_BitAnd: a &= b; break; case OP_BitOr: a |= b; break; case OP_ShiftLeft: a <<= b; break; case OP_ShiftRight: a >>= b; break; default: /* CANT HAPPEN */ break; } Release(pTos); pTos--; Release(pTos); pTos->i = a; pTos->flags = MEM_Int; break;}/* Opcode: AddImm P1 * *** ** Add the value P1 to whatever is on top of the stack. The result** is always an integer.**** To force the top of the stack to be an integer, just add 0.*/case OP_AddImm: { /* no-push */ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); pTos->i += pOp->p1; break;}/* Opcode: ForceInt P1 P2 ***** Convert the top of the stack into an integer. If the current top of** the stack is not numeric (meaning that is is a NULL or a string that** does not look like an integer or floating point number) then pop the** stack and jump to P2. If the top of the stack is numeric then** convert it into the least integer that is greater than or equal to its** current value if P1==0, or to the least integer that is strictly** greater than its current value if P1==1.*/case OP_ForceInt: { /* no-push */ i64 v; assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ Release(pTos); pTos--; pc = pOp->p2 - 1; break; } if( pTos->flags & MEM_Int ){ v = pTos->i + (pOp->p1!=0); }else{ /* FIX ME: should this not be assert( pTos->flags & MEM_Real ) ??? */ sqlite3VdbeMemRealify(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: { /* no-push */ assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); 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: RealAffinity * * ***** If the top of the stack is an integer, convert it to a real value.**** This opcode is used when extracting information from a column that** has REAL affinity. Such column values may still be stored as** integers, for space efficiency, but after extraction we want them** to have only a real value.*/case OP_RealAffinity: { /* no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Int ){ sqlite3VdbeMemRealify(pTos); } break;}#ifndef SQLITE_OMIT_CAST/* Opcode: ToText * * ***** Force the value on the top of the stack to be text.** If the value is numeric, convert it to a string using the** equivalent of printf(). Blob values are unchanged and** are afterwards simply interpreted as text.**** A NULL value is not changed by this routine. It remains NULL.*/case OP_ToText: { /* same as TK_TO_TEXT, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pTos->flags |= (pTos->flags&MEM_Blob)>>3; applyAffinity(pTos, SQLITE_AFF_TEXT, encoding); assert( pTos->flags & MEM_Str ); pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); break;}/* Opcode: ToBlob * * ***** Force the value on the top of the stack to be a BLOB.** If the value is numeric, convert it to a string first.** Strings are simply reinterpreted as blobs with no change** to the underlying data.**** A NULL value is not changed by this routine. It remains NULL.*/case OP_ToBlob: { /* same as TK_TO_BLOB, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; if( (pTos->flags & MEM_Blob)==0 ){ applyAffinity(pTos, SQLITE_AFF_TEXT, encoding); assert( pTos->flags & MEM_Str ); pTos->flags |= MEM_Blob; } pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Str); break;}/* Opcode: ToNumeric * * ***** Force the value on the top of the stack to be numeric (either an** integer or a floating-point number.)** If the value is text or blob, try to convert it to an using the** equivalent of atoi() or atof() and store 0 if no such conversion ** is possible.**** A NULL value is not changed by this routine. It remains NULL.*/case OP_ToNumeric: { /* same as TK_TO_NUMERIC, no-push */ assert( pTos>=p->aStack ); if( (pTos->flags & MEM_Null)==0 ){ sqlite3VdbeMemNumerify(pTos); } break;}#endif /* SQLITE_OMIT_CAST *//* Opcode: ToInt * * ***** Force the value on the top of the stack to be an integer. If** The value is currently a real number, drop its fractional part.** If the value is text or blob, try to convert it to an integer using the** equivalent of atoi() and store 0 if no such conversion is possible.**** A NULL value is not changed by this routine. It remains NULL.*/case OP_ToInt: { /* same as TK_TO_INT, no-push */ assert( pTos>=p->aStack ); if( (pTos->flags & MEM_Null)==0 ){ sqlite3VdbeMemIntegerify(pTos); } break;}#ifndef SQLITE_OMIT_CAST/* Opcode: ToReal * * ***** Force the value on the top of the stack to be a floating point number.** If The value is currently an integer, convert it.** If the value is text or blob, try to convert it to an integer using the** equivalent of atoi() and store 0 if no such conversion is possible.**** A NULL value is not changed by this routine. It remains NULL.*/case OP_ToReal: { /* same as TK_TO_REAL, no-push */ assert( pTos>=p->aStack ); if( (pTos->flags & MEM_Null)==0 ){ sqlite3VdbeMemRealify(pTos); } break;}#endif /* SQLITE_OMIT_CAST *//* 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.**** If the 0x100 bit of P1 is true and either operand is NULL then take the** jump. If the 0x100 bit of P1 is clear then fall thru if either operand** is NULL.**** If the 0x200 bit of P1 is set and either operand is NULL then** both operands are converted to integers prior to comparison.** NULL operands are converted to zero and non-NULL operands are** converted to 1. Thus, for example, with 0x200 set, NULL==NULL is true** whereas it would normally be NULL. Similarly, NULL==123 is false when** 0x200 is set but is NULL when the 0x200 bit of P1 is clear.**** The least significant byte of P1 (mask 0xff) must be an affinity character -** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. 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, no-push */case OP_Ne: /* same as TK_NE, no-push */case OP_Lt: /* same as TK_LT, no-push */case OP_Le: /* same as TK_LE, no-push */case OP_Gt: /* same as TK_GT, no-push */case OP_Ge: { /* same as TK_GE, no-push */ 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 ){ if( (pOp->p1 & 0x200)!=0 ){ /* The 0x200 bit of P1 means, roughly "do not treat NULL as the ** magic SQL value it normally is - treat it as if it were another ** integer". ** ** With 0x200 set, if either operand is NULL then both operands ** are converted to integers prior to being passed down into the ** normal comparison logic below. NULL operands are converted to ** zero and non-NULL operands are converted to 1. Thus, for example, ** with 0x200 set, NULL==NULL is true whereas it would normally ** be NULL. Similarly, NULL!=123 is true. */ sqlite3VdbeMemSetInt64(pTos, (pTos->flags & MEM_Null)==0); sqlite3VdbeMemSetInt64(pNos, (pNos->flags & MEM_Null)==0); }else{ /* If the 0x200 bit of P1 is clear and either operand is NULL then ** the result is always NULL. The jump is taken if the 0x100 bit ** of P1 is set. */ popStack(&pTos, 2); if( pOp->p2 ){ if( pOp->p1 & 0x100 ){ pc = pOp->p2-1; } }else{ pTos++; pTos->flags = MEM_Null; } break; } } affinity = pOp->p1 & 0xFF; if( affinity ){ applyAffinity(pNos, affinity, encoding); applyAffinity(pTos, affinity, encoding); } 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, no-push */case OP_Or: { /* same as TK_OR, no-push */ 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{ sqlite3VdbeMemIntegerify(pTos); v1 = pTos->i==0; } if( pNos->flags & MEM_Null ){ v2 = 2; }else{ sqlite3VdbeMemIntegerify(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]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -