📄 vdbe.c
字号:
*/
if( ctx.pVdbeFunc ){
sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1);
pOp->p3 = (char *)ctx.pVdbeFunc;
pOp->p3type = P3_VDBEFUNC;
}
/* If the function returned an error, throw an exception */
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0);
rc = SQLITE_ERROR;
}
/* Copy the result of the function to the top of the stack */
sqlite3VdbeChangeEncoding(&ctx.s, encoding);
pTos++;
pTos->flags = 0;
sqlite3VdbeMemMove(pTos, &ctx.s);
break;
}
/* Opcode: BitAnd * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the bit-wise AND of the
** two elements.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: BitOr * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the bit-wise OR of the
** two elements.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: ShiftLeft * * *
**
** 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 ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -