📄 vdbe.c
字号:
** immediately call the destructor for any non-static values. */ if( ctx.pVdbeFunc ){ sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1); pOp->p4.pVdbeFunc = ctx.pVdbeFunc; pOp->p4type = P4_VDBEFUNC; } /* If the function returned an error, throw an exception */ if( ctx.isError ){ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0); rc = ctx.isError; } /* Copy the result of the function into register P3 */ sqlite3VdbeChangeEncoding(&ctx.s, encoding); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pOut = &p->aMem[pOp->p3]; sqlite3VdbeMemMove(pOut, &ctx.s); if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); break;}/* Opcode: BitAnd P1 P2 P3 * ***** Take the bit-wise AND of the values in register P1 and P2 and** store the result in register P3.** If either input is NULL, the result is NULL.*//* Opcode: BitOr P1 P2 P3 * ***** Take the bit-wise OR of the values in register P1 and P2 and** store the result in register P3.** If either input is NULL, the result is NULL.*//* Opcode: ShiftLeft P1 P2 P3 * ***** Shift the integer value in register P2 to the left by the** number of bits specified by the integer in regiser P1.** Store the result in register P3.** If either input is NULL, the result is NULL.*//* Opcode: ShiftRight P1 P2 P3 * ***** Shift the integer value in register P2 to the right by the** number of bits specified by the integer in register P1.** Store the result in register P3.** If either input is NULL, the result is NULL.*/case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ i64 a, b; if( (pIn1->flags | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); break; } a = sqlite3VdbeIntValue(pIn2); b = sqlite3VdbeIntValue(pIn1); switch( pOp->opcode ){ case OP_BitAnd: a &= b; break; case OP_BitOr: a |= b; break; case OP_ShiftLeft: a <<= b; break; default: assert( pOp->opcode==OP_ShiftRight ); a >>= b; break; } Release(pOut); pOut->u.i = a; pOut->flags = MEM_Int; break;}/* Opcode: AddImm P1 P2 * * *** ** Add the constant P2 the value in register P1.** The result is always an integer.**** To force any register to be an integer, just add 0.*/case OP_AddImm: { /* in1 */ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i += pOp->p2; break;}/* Opcode: ForceInt P1 P2 P3 * ***** Convert value in register P1 into an integer. If the value ** in P1 is not numeric (meaning that is is a NULL or a string that** does not look like an integer or floating point number) then** jump to P2. If the value in P1 is numeric then** convert it into the least integer that is greater than or equal to its** current value if P3==0, or to the least integer that is strictly** greater than its current value if P3==1.*/case OP_ForceInt: { /* jump, in1 */ i64 v; applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); if( (pIn1->flags & (MEM_Int|MEM_Real))==0 ){ pc = pOp->p2 - 1; break; } if( pIn1->flags & MEM_Int ){ v = pIn1->u.i + (pOp->p3!=0); }else{ assert( pIn1->flags & MEM_Real ); v = (sqlite3_int64)pIn1->r; if( pIn1->r>(double)v ) v++; if( pOp->p3 && pIn1->r==(double)v ) v++; } Release(pIn1); pIn1->u.i = v; pIn1->flags = MEM_Int; break;}/* Opcode: MustBeInt P1 P2 * * *** ** Force the value in register P1 to be an integer. If the value** in P1 is not an integer and cannot be converted into an integer** without data loss, then jump immediately to P2, or if P2==0** raise an SQLITE_MISMATCH exception.*/case OP_MustBeInt: { /* jump, in1 */ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); if( (pIn1->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ pc = pOp->p2 - 1; } }else{ Release(pIn1); pIn1->flags = MEM_Int; } break;}/* Opcode: RealAffinity P1 * * * ***** If register P1 holds 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: { /* in1 */ if( pIn1->flags & MEM_Int ){ sqlite3VdbeMemRealify(pIn1); } break;}#ifndef SQLITE_OMIT_CAST/* Opcode: ToText P1 * * * ***** Force the value in register P1 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, in1 */ if( pIn1->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); rc = ExpandBlob(pIn1); assert( pIn1->flags & MEM_Str ); pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); UPDATE_MAX_BLOBSIZE(pIn1); break;}/* Opcode: ToBlob P1 * * * ***** Force the value in register P1 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, in1 */ if( pIn1->flags & MEM_Null ) break; if( (pIn1->flags & MEM_Blob)==0 ){ applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); assert( pIn1->flags & MEM_Str ); pIn1->flags |= MEM_Blob; } pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str); UPDATE_MAX_BLOBSIZE(pIn1); break;}/* Opcode: ToNumeric P1 * * * ***** Force the value in register P1 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, in1 */ if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){ sqlite3VdbeMemNumerify(pIn1); } break;}#endif /* SQLITE_OMIT_CAST *//* Opcode: ToInt P1 * * * ***** Force the value in register P1 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, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ sqlite3VdbeMemIntegerify(pIn1); } break;}#ifndef SQLITE_OMIT_CAST/* Opcode: ToReal P1 * * * ***** Force the value in register P1 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.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, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ sqlite3VdbeMemRealify(pIn1); } break;}#endif /* SQLITE_OMIT_CAST *//* Opcode: Lt P1 P2 P3 P4 P5**** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then** jump to address P2. **** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL ** bit is clear then fall thru if either operand is NULL.**** If the SQLITE_NULLEQUAL bit of P5 is set then treat NULL operands** as being equal to one another. Normally NULLs are not equal to ** anything including other NULLs.**** The SQLITE_AFF_MASK portion of P5 must be an affinity character -** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made ** to coerce both inputs according to this affinity before the** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric** affinity is used. Note that the affinity conversions are stored** back into the input registers P1 and P3. So this opcode can cause** persistent changes to registers P1 and P3.**** Once any conversions have taken place, and neither value is NULL, ** the values are compared. If both values are blobs then memcmp() is** used to determine the results of the comparison. If both values** are text, then the appropriate collating function specified in** P4 is used to do the comparison. If P4 is not specified then** memcmp() is used to compare text string. If both values are** numeric, then a numeric comparison is used. If the two values** are of different types, then numbers are considered less than** strings and strings are considered less than blobs.**** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead,** store a boolean result (either 0, or 1, or NULL) in register P2.*//* Opcode: Ne P1 P2 P3 P4 P5**** This works just like the Lt opcode except that the jump is taken if** the operands in registers P1 and P3 are not equal. See the Lt opcode for** additional information.*//* Opcode: Eq P1 P2 P3 P4 P5**** This works just like the Lt opcode except that the jump is taken if** the operands in registers P1 and P3 are equal.** See the Lt opcode for additional information.*//* Opcode: Le P1 P2 P3 P4 P5**** This works just like the Lt opcode except that the jump is taken if** the content of register P3 is less than or equal to the content of** register P1. See the Lt opcode for additional information.*//* Opcode: Gt P1 P2 P3 P4 P5**** This works just like the Lt opcode except that the jump is taken if** the content of register P3 is greater than the content of** register P1. See the Lt opcode for additional information.*//* Opcode: Ge P1 P2 P3 P4 P5**** This works just like the Lt opcode except that the jump is taken if** the content of register P3 is greater than or equal to the content of** register P1. See the Lt opcode for additional information.*/case OP_Eq: /* same as TK_EQ, jump, in1, in3 */case OP_Ne: /* same as TK_NE, jump, in1, in3 */case OP_Lt: /* same as TK_LT, jump, in1, in3 */case OP_Le: /* same as TK_LE, jump, in1, in3 */case OP_Gt: /* same as TK_GT, jump, in1, in3 */case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ int flags; int res; char affinity; Mem x1, x3; flags = pIn1->flags|pIn3->flags; if( flags&MEM_Null ){ if( (pOp->p5 & SQLITE_NULLEQUAL)!=0 ){ /* ** When SQLITE_NULLEQUAL set and 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 SQLITE_NULLEQUAL ** set, NULL==NULL is true whereas it would normally NULL. ** Similarly, NULL!=123 is true. */ x1.flags = MEM_Int; x1.u.i = (pIn1->flags & MEM_Null)==0; pIn1 = &x1; x3.flags = MEM_Int; x3.u.i = (pIn3->flags & MEM_Null)==0; pIn3 = &x3; }else{ /* If the SQLITE_NULLEQUAL bit is clear and either operand is NULL then ** the result is always NULL. The jump is taken if the ** SQLITE_JUMPIFNULL bit is set. */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &p->aMem[pOp->p2]; Release(pOut); pOut->flags = MEM_Null; REGISTER_TRACE(pOp->p2, pOut); }else if( pOp->p5 & SQLITE_JUMPIFNULL ){ pc = pOp->p2-1; } break; } } affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity ){ applyAffinity(pIn1, affinity, encoding); applyAffinity(pIn3, affinity, encoding); } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); ExpandBlob(pIn1); ExpandBlob(pIn3); res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); 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; } if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &p->aMem[pOp->p2]; Release(pOut); pOut->flags = MEM_Int; pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); }else if( res ){ pc = pOp->p2-1; } break;}/* Opcode: And P1 P2 P3 * ***** Take the logical AND of the values in registers P1 and P2 and** write the result into register P3.**** If either P1 or P2 is 0 (false) then the result is 0 even if** the other input is NULL. A NULL and true or two NULLs give** a NULL output.*//* Opcode: Or P1 P2 P3 * ***** Take the logical OR of the values in register P1 and P2 and** store the answer in register P3.**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -