?? vdbe.c
字號:
** invoke the callback function using the newly formed array as the** 3rd parameter.*/case OP_Callback: { int i; char **azArgv = p->zArgv; Mem *pCol; pCol = &pTos[1-pOp->p1]; assert( pCol>=p->aStack ); for(i=0; i<pOp->p1; i++, pCol++){ if( pCol->flags & MEM_Null ){ azArgv[i] = 0; }else{ Stringify(pCol); azArgv[i] = pCol->z; } } azArgv[i] = 0; p->nCallback++; p->azResColumn = azArgv; assert( p->nResColumn==pOp->p1 ); p->popStack = pOp->p1; p->pc = pc + 1; p->pTos = pTos; return SQLITE_ROW;}/* Opcode: Concat P1 P2 P3**** Look at the first P1 elements of the stack. Append them all ** together with the lowest element first. Use P3 as a separator. ** Put the result on the top of the stack. The original P1 elements** are popped from the stack if P2==0 and retained if P2==1. If** any element of the stack is NULL, then the result is NULL.**** If P3 is NULL, then use no separator. When P1==1, this routine** makes a copy of the top stack element into memory obtained** from sqliteMalloc().*/case OP_Concat: { char *zNew; int nByte; int nField; int i, j; char *zSep; int nSep; Mem *pTerm; nField = pOp->p1; zSep = pOp->p3; if( zSep==0 ) zSep = ""; nSep = strlen(zSep); assert( &pTos[1-nField] >= p->aStack ); nByte = 1 - nSep; pTerm = &pTos[1-nField]; for(i=0; i<nField; i++, pTerm++){ if( pTerm->flags & MEM_Null ){ nByte = -1; break; }else{ Stringify(pTerm); nByte += pTerm->n - 1 + nSep; } } if( nByte<0 ){ if( pOp->p2==0 ){ popStack(&pTos, nField); } pTos++; pTos->flags = MEM_Null; break; } zNew = sqliteMallocRaw( nByte ); if( zNew==0 ) goto no_mem; j = 0; pTerm = &pTos[1-nField]; for(i=j=0; i<nField; i++, pTerm++){ assert( pTerm->flags & MEM_Str ); memcpy(&zNew[j], pTerm->z, pTerm->n-1); j += pTerm->n-1; if( nSep>0 && i<nField-1 ){ memcpy(&zNew[j], zSep, nSep); j += nSep; } } zNew[j] = 0; if( pOp->p2==0 ){ popStack(&pTos, nField); } pTos++; pTos->n = nByte; pTos->flags = MEM_Str|MEM_Dyn; pTos->z = zNew; break;}/* Opcode: Add * * ***** Pop the top two elements from the stack, add them together,** and push the result back onto the stack. If either element** is a string then it is converted to a double using the atof()** function before the addition.** If either operand is NULL, the result is NULL.*//* Opcode: Multiply * * ***** Pop the top two elements from the stack, multiply them together,** and push the result back onto the stack. If either element** is a string then it is converted to a double using the atof()** function before the multiplication.** If either operand is NULL, the result is NULL.*//* Opcode: Subtract * * ***** Pop the top two elements from the stack, subtract the** first (what was on top of the stack) from the second (the** next on stack)** and push the result back onto the stack. If either element** is a string then it is converted to a double using the atof()** function before the subtraction.** If either operand is NULL, the result is NULL.*//* Opcode: Divide * * ***** Pop the top two elements from the stack, divide the** first (what was on top of the stack) from the second (the** next on stack)** and push the result back onto the stack. If either element** is a string then it is converted to a double using the atof()** function before the division. Division by zero returns NULL.** If either operand is NULL, the result is NULL.*//* Opcode: Remainder * * ***** Pop the top two elements from the stack, divide the** first (what was on top of the stack) from the second (the** next on stack)** and push the remainder after division onto the stack. If either element** is a string then it is converted to a double using the atof()** function before the division. Division by zero returns NULL.** If either operand is NULL, the result is NULL.*/case OP_Add:case OP_Subtract:case OP_Multiply:case OP_Divide:case OP_Remainder: { Mem *pNos = &pTos[-1]; assert( pNos>=p->aStack ); if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){ Release(pTos); pTos--; Release(pTos); pTos->flags = MEM_Null; }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){ int a, b; a = pTos->i; b = pNos->i; switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; case OP_Multiply: b *= a; break; case OP_Divide: { if( a==0 ) goto divide_by_zero; b /= a; break; } default: { if( a==0 ) goto divide_by_zero; b %= a; break; } } Release(pTos); pTos--; Release(pTos); pTos->i = b; pTos->flags = MEM_Int; }else{ double a, b; Realify(pTos); Realify(pNos); a = pTos->r; b = pNos->r; switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; case OP_Multiply: b *= a; break; case OP_Divide: { if( a==0.0 ) goto divide_by_zero; b /= a; break; } default: { int ia = (int)a; int ib = (int)b; if( ia==0.0 ) goto divide_by_zero; b = ib % ia; break; } } Release(pTos); pTos--; Release(pTos); pTos->r = b; pTos->flags = MEM_Real; } break;divide_by_zero: Release(pTos); pTos--; Release(pTos); pTos->flags = MEM_Null; break;}/* Opcode: Function P1 * P3**** Invoke a user function (P3 is a pointer to a Function structure that** defines the function) with P1 string arguments taken from the stack.** Pop all arguments from the stack and push back the result.**** See also: AggFunc*/case OP_Function: { int n, i; Mem *pArg; char **azArgv; sqlite_func ctx; n = pOp->p1; pArg = &pTos[1-n]; azArgv = p->zArgv; for(i=0; i<n; i++, pArg++){ if( pArg->flags & MEM_Null ){ azArgv[i] = 0; }else{ Stringify(pArg); azArgv[i] = pArg->z; } } ctx.pFunc = (FuncDef*)pOp->p3; ctx.s.flags = MEM_Null; ctx.s.z = 0; ctx.isError = 0; ctx.isStep = 0; if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, (const char**)azArgv); if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; popStack(&pTos, n); pTos++; *pTos = ctx.s; if( pTos->flags & MEM_Short ){ pTos->z = pTos->zShort; } if( ctx.isError ){ sqliteSetString(&p->zErrMsg, (pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0); rc = SQLITE_ERROR; } 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 top element shifted** left by N bits where N is the second 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 top element shifted** right by N bits where N is the second element on the stack.** If either operand is NULL, the result is NULL.*/case OP_BitAnd:case OP_BitOr:case OP_ShiftLeft:case OP_ShiftRight: { Mem *pNos = &pTos[-1]; int a, b; assert( pNos>=p->aStack ); if( (pTos->flags | pNos->flags) & MEM_Null ){ popStack(&pTos, 2); pTos++; pTos->flags = MEM_Null; break; } Integerify(pTos); Integerify(pNos); a = pTos->i; b = pNos->i; 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; } assert( (pTos->flags & MEM_Dyn)==0 ); assert( (pNos->flags & MEM_Dyn)==0 ); 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: { assert( pTos>=p->aStack ); Integerify(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: { int v; assert( pTos>=p->aStack ); if( (pTos->flags & (MEM_Int|MEM_Real))==0 && ((pTos->flags & MEM_Str)==0 || sqliteIsNumber(pTos->z)==0) ){ Release(pTos); pTos--; pc = pOp->p2 - 1; break; } 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 ); if( pTos->flags & MEM_Int ){ /* Do nothing */ }else if( pTos->flags & MEM_Real ){ int i = (int)pTos->r; double r = (double)i; if( r!=pTos->r ){ goto mismatch; } pTos->i = i; }else if( pTos->flags & MEM_Str ){ int v; if( !toInt(pTos->z, &v) ){ double r; if( !sqliteIsNumber(pTos->z) ){ goto mismatch; } Realify(pTos); v = (int)pTos->r; r = (double)v; if( r!=pTos->r ){ goto mismatch; } } pTos->i = v; }else{ goto mismatch; } Release(pTos); pTos->flags = MEM_Int; break;mismatch: if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ if( pOp->p1 ) popStack(&pTos, 1); pc = pOp->p2 - 1; } break;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -