📄 vdbe.c
字号:
/* If 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]; MemSetTypeFlag(pOut, 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]; MemSetTypeFlag(pOut, MEM_Int); pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); }else if( res ){ pc = pOp->p2-1; } break;}/* Opcode: Permutation * * * P4 ***** Set the permuation used by the OP_Compare operator to be the array** of integers in P4.**** The permutation is only valid until the next OP_Permutation, OP_Compare,** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur** immediately prior to the OP_Compare.*/case OP_Permutation: { assert( pOp->p4type==P4_INTARRAY ); assert( pOp->p4.ai ); aPermute = pOp->p4.ai; break;}/* Opcode: Compare P1 P2 P3 P4 ***** Compare to vectors of registers in reg(P1)..reg(P1+P3-1) (all this** one "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of** the comparison for use by the next OP_Jump instruct.**** P4 is a KeyInfo structure that defines collating sequences and sort** orders for the comparison. The permutation applies to registers** only. The KeyInfo elements are used sequentially.**** The comparison is a sort comparison, so NULLs compare equal,** NULLs are less than numbers, numbers are less than strings,** and strings are less than blobs.*/case OP_Compare: { int n = pOp->p3; int i, p1, p2; const KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); p1 = pOp->p1; assert( p1>0 && p1+n-1<p->nMem ); p2 = pOp->p2; assert( p2>0 && p2+n-1<p->nMem ); for(i=0; i<n; i++){ int idx = aPermute ? aPermute[i] : i; CollSeq *pColl; /* Collating sequence to use on this term */ int bRev; /* True for DESCENDING sort order */ REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]); REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]); assert( i<pKeyInfo->nField ); pColl = pKeyInfo->aColl[i]; bRev = pKeyInfo->aSortOrder[i]; iCompare = sqlite3MemCompare(&p->aMem[p1+idx], &p->aMem[p2+idx], pColl); if( iCompare ){ if( bRev ) iCompare = -iCompare; break; } } aPermute = 0; break;}/* Opcode: Jump P1 P2 P3 * ***** Jump to the instruction at address P1, P2, or P3 depending on whether** in the most recent OP_Compare instruction the P1 vector was less than** equal to, or greater than the P2 vector, respectively.*/case OP_Jump: { /* jump */ if( iCompare<0 ){ pc = pOp->p1 - 1; }else if( iCompare==0 ){ pc = pOp->p2 - 1; }else{ pc = pOp->p3 - 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.**** If either P1 or P2 is nonzero (true) then the result is 1 (true)** even if the other input is NULL. A NULL and false or two NULLs** give a NULL output.*/case OP_And: /* same as TK_AND, in1, in2, out3 */case OP_Or: { /* same as TK_OR, in1, in2, out3 */ int v1, v2; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ if( pIn1->flags & MEM_Null ){ v1 = 2; }else{ v1 = sqlite3VdbeIntValue(pIn1)!=0; } if( pIn2->flags & MEM_Null ){ v2 = 2; }else{ v2 = sqlite3VdbeIntValue(pIn2)!=0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; v1 = or_logic[v1*3+v2]; } if( v1==2 ){ MemSetTypeFlag(pOut, MEM_Null); }else{ pOut->u.i = v1; MemSetTypeFlag(pOut, MEM_Int); } break;}/* Opcode: Not P1 * * * ***** Interpret the value in register P1 as a boolean value. Replace it** with its complement. If the value in register P1 is NULL its value** is unchanged.*/case OP_Not: { /* same as TK_NOT, in1 */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i = !pIn1->u.i; assert( pIn1->flags&MEM_Int ); break;}/* Opcode: BitNot P1 * * * ***** Interpret the content of register P1 as an integer. Replace it** with its ones-complement. If the value is originally NULL, leave** it unchanged.*/case OP_BitNot: { /* same as TK_BITNOT, in1 */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i = ~pIn1->u.i; assert( pIn1->flags&MEM_Int ); break;}/* Opcode: If P1 P2 P3 * ***** Jump to P2 if the value in register P1 is true. The value is** is considered true if it is numeric and non-zero. If the value** in P1 is NULL then take the jump if P3 is true.*//* Opcode: IfNot P1 P2 P3 * ***** Jump to P2 if the value in register P1 is False. The value is** is considered true if it has a numeric value of zero. If the value** in P1 is NULL then take the jump if P3 is true.*/case OP_If: /* jump, in1 */case OP_IfNot: { /* jump, in1 */ int c; if( pIn1->flags & MEM_Null ){ c = pOp->p3; }else{#ifdef SQLITE_OMIT_FLOATING_POINT c = sqlite3VdbeIntValue(pIn1);#else c = sqlite3VdbeRealValue(pIn1)!=0.0;#endif if( pOp->opcode==OP_IfNot ) c = !c; } if( c ){ pc = pOp->p2-1; } break;}/* Opcode: IsNull P1 P2 P3 * ***** Jump to P2 if the value in register P1 is NULL. If P3 is greater** than zero, then check all values reg(P1), reg(P1+1), ** reg(P1+2), ..., reg(P1+P3-1).*/case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ int n = pOp->p3; assert( pOp->p3==0 || pOp->p1>0 ); do{ if( (pIn1->flags & MEM_Null)!=0 ){ pc = pOp->p2 - 1; break; } pIn1++; }while( --n > 0 ); break;}/* Opcode: NotNull P1 P2 * * ***** Jump to P2 if the value in register P1 is not NULL. */case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ pc = pOp->p2 - 1; } break;}/* Opcode: SetNumColumns * P2 * * ***** This opcode sets the number of columns for the cursor opened by the** following instruction to P2.**** An OP_SetNumColumns is only useful if it occurs immediately before ** one of the following opcodes:**** OpenRead** OpenWrite** OpenPseudo**** If the OP_Column opcode is to be executed on a cursor, then** this opcode must be present immediately before the opcode that** opens the cursor.*/case OP_SetNumColumns: { break;}/* Opcode: Column P1 P2 P3 P4 ***** Interpret the data that cursor P1 points to as a structure built using** the MakeRecord instruction. (See the MakeRecord opcode for additional** information about the format of the data.) Extract the P2-th column** from this record. If there are less that (P2+1) ** values in the record, extract a NULL.**** The value extracted is stored in register P3.**** If the KeyAsData opcode has previously executed on this cursor, then the** field might be extracted from the key rather than the data.**** If the column contains fewer than P2 fields, then extract a NULL. Or,** if the P4 argument is a P4_MEM use the value of the P4 argument as** the result.*/case OP_Column: { u32 payloadSize; /* Number of bytes in the record */ int p1 = pOp->p1; /* P1 value of the opcode */ int p2 = pOp->p2; /* column number to retrieve */ Cursor *pC = 0; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ u32 nField; /* number of fields in the record */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; sMem.db = 0; sMem.zMalloc = 0; assert( p1<p->nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &p->aMem[pOp->p3]; MemSetTypeFlag(pDest, MEM_Null); /* This block sets the variable payloadSize to be the total number of ** bytes in the record. ** ** zRec is set to be the complete text of the record if it is available. ** The complete record text is always available for pseudo-tables ** If the record is stored in a cursor, the complete record text ** might be available in the pC->aRow cache. Or it might not be. ** If the data is unavailable, zRec is set to NULL. ** ** We also compute the number of columns in the record. For cursors, ** the number of columns is stored in the Cursor.nField element. */ pC = p->apCsr[p1]; assert( pC!=0 );#ifndef SQLITE_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 );#endif if( pC->pCursor!=0 ){ /* The record is stored in a B-Tree */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->cacheStatus==p->cacheCtr ){ payloadSize = pC->payloadSize; zRec = (char*)pC->aRow; }else if( pC->isIndex ){ i64 payloadSize64; sqlite3BtreeKeySize(pCrsr, &payloadSize64); payloadSize = payloadSize64; }else{ sqlite3BtreeDataSize(pCrsr, &payloadSize); } nField = pC->nField; }else{ assert( pC->pseudoTable ); /* The record is the sole entry of a pseudo-table */ payloadSize = pC->nData; zRec = pC->pData; pC->cacheStatus = CACHE_STALE; assert( payloadSize==0 || zRec!=0 ); nField = pC->nField; pCrsr = 0; } /* If payloadSize is 0, then just store a NULL */ if( payloadSize==0 ){ assert( pDest->flags&MEM_Null ); goto op_column_out; } if( payloadSize>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } assert( p2<nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ aType = pC->aType; if( pC->cacheStatus==p->cacheCtr ){ aOffset = pC->aOffset; }else{ u8 *zIdx; /* Index into header */ u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ int szHdrSz; /* Size of the header size field at start of record */ int avail; /* Number of bytes of available data */ assert(aType); pC->aOffset = aOffset = &aType[nField]; pC->payloadSize = payloadSize; pC->cacheStatus = p->cacheCtr; /* Figure out how many bytes are in the header */ if( zRec ){ zData = zRec; }else{ if( pC->isIndex ){ zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail); }else{ zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail); } /* If KeyFetch()/DataFetch() managed to get the entire payload, ** save the payload in the pC->aRow cache. That will save us from ** having to make additional calls to fetch the content portion of ** the record. */ if( avail>=payloadSize ){ zRec = zData; pC->aRow = (u8*)zData; }else{ pC->aRow = 0; } } /* The following assert is true in all cases accept when ** the database file has been corrupted extern
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -