📄 vdbe.c
字号:
** functions.**** The interface used by the implementation of the aforementioned functions** to retrieve the collation sequence set by this opcode is not available** publicly, only to user functions defined in func.c.*/case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); break;}/* Opcode: Function P1 P2 P3 P4 P5**** Invoke a user function (P4 is a pointer to a Function structure that** defines the function) with P5 arguments taken from register P2 and** successors. The result of the function is stored in register P3.** Register P3 must not be one of the function inputs.**** P1 is a 32-bit bitmask indicating whether or not each argument to the ** function was determined to be constant at compile time. If the first** argument was constant then bit 0 of P1 is set. This is used to determine** whether meta data associated with a user function argument using the** sqlite3_set_auxdata() API may be safely retained until the next** invocation of this opcode.**** See also: AggStep and AggFinal*/case OP_Function: { int i; Mem *pArg; sqlite3_context ctx; sqlite3_value **apVal; int n = pOp->p5; apVal = p->apArg; assert( apVal || n==0 ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) ); assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); pArg = &p->aMem[pOp->p2]; for(i=0; i<n; i++, pArg++){ apVal[i] = pArg; storeTypeInfo(pArg, encoding); REGISTER_TRACE(pOp->p2, pArg); } assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC ); if( pOp->p4type==P4_FUNCDEF ){ ctx.pFunc = pOp->p4.pFunc; ctx.pVdbeFunc = 0; }else{ ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; ctx.pFunc = ctx.pVdbeFunc->pFunc; } assert( pOp->p3>0 && pOp->p3<=p->nMem ); pOut = &p->aMem[pOp->p3]; ctx.s.flags = MEM_Null; ctx.s.db = db; ctx.s.xDel = 0; ctx.s.zMalloc = 0; /* The output cell may already have a buffer allocated. Move ** the pointer to ctx.s so in case the user-function can use ** the already allocated buffer instead of allocating a new one. */ sqlite3VdbeMemMove(&ctx.s, pOut); MemSetTypeFlag(&ctx.s, MEM_Null); ctx.isError = 0; if( ctx.pFunc->needCollSeq ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); ctx.pColl = pOp[-1].p4.pColl; } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, apVal); if( sqlite3SafetyOn(db) ){ sqlite3VdbeMemRelease(&ctx.s); goto abort_due_to_misuse; } if( db->mallocFailed ){ /* Even though a malloc() has failed, the implementation of the ** user function may have called an sqlite3_result_XXX() function ** to return a value. The following call releases any resources ** associated with such a value. ** ** Note: Maybe MemRelease() should be called if sqlite3SafetyOn() ** fails also (the if(...) statement above). But if people are ** misusing sqlite, they have bigger problems than a leaked value. */ sqlite3VdbeMemRelease(&ctx.s); goto no_mem; } /* If any auxiliary data functions have been called by this user function, ** 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, db, "%s", sqlite3_value_text(&ctx.s)); rc = ctx.isError; } /* Copy the result of the function into register P3 */ sqlite3VdbeChangeEncoding(&ctx.s, encoding); 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; } pOut->u.i = a; MemSetTypeFlag(pOut, MEM_Int); break;}/* Opcode: AddImm P1 P2 * * *** ** Add the constant P2 to 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++; } pIn1->u.i = v; MemSetTypeFlag(pIn1, 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{ MemSetTypeFlag(pIn1, 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 || db->mallocFailed ); 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 || db->mallocFailed ); } MemSetTypeFlag(pIn1, MEM_Blob); 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.**** 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; flags = pIn1->flags|pIn3->flags; if( flags&MEM_Null ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -