📄 vdbe.c
字号:
}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 ); ExpandBlob(pNos); ExpandBlob(pTos); 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 ){ if( res ){ pc = pOp->p2-1; } }else{ pTos++; pTos->flags = MEM_Int; pTos->u.i = res; } break;}/* Opcode: And * * ***** Pop two values off the stack. Take the logical AND of the** two values and push the resulting boolean value back onto the** stack. *//* Opcode: Or * * ***** Pop two values off the stack. Take the logical OR of the** two values and push the resulting boolean value back onto the** stack. */case OP_And: /* same as TK_AND, no-push */case OP_Or: { /* same as TK_OR, no-push */ Mem *pNos = &pTos[-1]; int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ assert( pNos>=p->aStack ); if( pTos->flags & MEM_Null ){ v1 = 2; }else{ sqlite3VdbeMemIntegerify(pTos); v1 = pTos->u.i==0; } if( pNos->flags & MEM_Null ){ v2 = 2; }else{ sqlite3VdbeMemIntegerify(pNos); v2 = pNos->u.i==0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = or_logic[v1*3+v2]; } popStack(&pTos, 2); pTos++; if( v1==2 ){ pTos->flags = MEM_Null; }else{ pTos->u.i = v1==0; pTos->flags = MEM_Int; } break;}/* Opcode: Negative * * ***** Treat the top of the stack as a numeric quantity. Replace it** with its additive inverse. If the top of the stack is NULL** its value is unchanged.*//* Opcode: AbsValue * * ***** Treat the top of the stack as a numeric quantity. Replace it** with its absolute value. If the top of the stack is NULL** its value is unchanged.*/case OP_Negative: /* same as TK_UMINUS, no-push */case OP_AbsValue: { assert( pTos>=p->aStack ); if( (pTos->flags & (MEM_Real|MEM_Int|MEM_Null))==0 ){ sqlite3VdbeMemNumerify(pTos); } if( pTos->flags & MEM_Real ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; }else if( pTos->flags & MEM_Int ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->u.i<0 ){ pTos->u.i = -pTos->u.i; } pTos->flags = MEM_Int; } break;}/* Opcode: Not * * ***** Interpret the top of the stack as a boolean value. Replace it** with its complement. If the top of the stack is NULL its value** is unchanged.*/case OP_Not: { /* same as TK_NOT, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); pTos->u.i = !pTos->u.i; pTos->flags = MEM_Int; break;}/* Opcode: BitNot * * ***** Interpret the top of the stack as an value. Replace it** with its ones-complement. If the top of the stack is NULL its** value is unchanged.*/case OP_BitNot: { /* same as TK_BITNOT, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); pTos->u.i = ~pTos->u.i; pTos->flags = MEM_Int; break;}/* Opcode: Noop * * ***** Do nothing. This instruction is often useful as a jump** destination.*//*** The magic Explain opcode are only inserted when explain==2 (which** is to say when the EXPLAIN QUERY PLAN syntax is used.)** This opcode records information from the optimizer. It is the** the same as a no-op. This opcodesnever appears in a real VM program.*/case OP_Explain:case OP_Noop: { /* no-push */ break;}/* Opcode: If P1 P2 ***** Pop a single boolean from the stack. If the boolean popped is** true, then jump to p2. Otherwise continue to the next instruction.** An integer is false if zero and true otherwise. A string is** false if it has zero length and true otherwise.**** If the value popped of the stack is NULL, then take the jump if P1** is true and fall through if P1 is false.*//* Opcode: IfNot P1 P2 ***** Pop a single boolean from the stack. If the boolean popped is** false, then jump to p2. Otherwise continue to the next instruction.** An integer is false if zero and true otherwise. A string is** false if it has zero length and true otherwise.**** If the value popped of the stack is NULL, then take the jump if P1** is true and fall through if P1 is false.*/case OP_If: /* no-push */case OP_IfNot: { /* no-push */ int c; assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ){ c = pOp->p1; }else{#ifdef SQLITE_OMIT_FLOATING_POINT c = sqlite3VdbeIntValue(pTos);#else c = sqlite3VdbeRealValue(pTos)!=0.0;#endif if( pOp->opcode==OP_IfNot ) c = !c; } Release(pTos); pTos--; if( c ) pc = pOp->p2-1; break;}/* Opcode: IsNull P1 P2 ***** Check the top of the stack and jump to P2 if the top of the stack** is NULL. If P1 is positive, then pop P1 elements from the stack** regardless of whether or not the jump is taken. If P1 is negative,** pop -P1 elements from the stack only if the jump is taken and leave** the stack unchanged if the jump is not taken.*/case OP_IsNull: { /* same as TK_ISNULL, no-push */ if( pTos->flags & MEM_Null ){ pc = pOp->p2-1; if( pOp->p1<0 ){ popStack(&pTos, -pOp->p1); } } if( pOp->p1>0 ){ popStack(&pTos, pOp->p1); } break;}/* Opcode: NotNull P1 P2 ***** Jump to P2 if the top abs(P1) values on the stack are all not NULL. ** Regardless of whether or not the jump is taken, pop the stack** P1 times if P1 is greater than zero. But if P1 is negative,** leave the stack unchanged.*/case OP_NotNull: { /* same as TK_NOTNULL, no-push */ int i, cnt; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; assert( &pTos[1-cnt] >= p->aStack ); for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){} if( i>=cnt ) pc = pOp->p2-1; if( pOp->p1>0 ) popStack(&pTos, cnt); break;}/* Opcode: SetNumColumns P1 P2 ***** Before the OP_Column opcode can be executed on a cursor, this** opcode must be called to set the number of fields in the table.**** This opcode sets the number of columns for cursor P1 to P2.**** If OP_KeyAsData is to be applied to cursor P1, it must be executed** before this op-code.*/case OP_SetNumColumns: { /* no-push */ Cursor *pC; assert( (pOp->p1)<p->nCursor ); assert( p->apCsr[pOp->p1]!=0 ); pC = p->apCsr[pOp->p1]; pC->nField = pOp->p2; break;}/* Opcode: Column P1 P2 P3**** 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.) Push onto the stack the value** of the P2-th column contained in the data. If there are less that (P2+1) ** values in the record, push a NULL onto the stack.**** 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 push a NULL. Or** if P3 is of type P3_MEM, then push the P3 value. The P3 value will** be default value for a column that has been added using the ALTER TABLE** ADD COLUMN command. If P3 is an ordinary string, just push a NULL.** When P3 is a string it is really just a comment describing the value** to be pushed, not a default value.*/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 sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1<p->nCursor ); pTos++; pTos->flags = 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. For ** records on the stack, the next entry down on the stack is an integer ** which is the number of records. */ pC = p->apCsr[p1];#ifndef SQLITE_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 );#endif assert( pC!=0 ); 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 if( 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; }else{ zRec = 0; payloadSize = 0; pCrsr = 0; nField = 0; } /* If payloadSize is 0, then just push a NULL onto the stack. */ if( payloadSize==0 ){ assert( pTos->flags==MEM_Null ); break; } if( payloadSize>SQLITE_MAX_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. */ if( pC && pC->cacheStatus==p->cacheCtr ){ aType = pC->aType; 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 */ aType = pC->aType; if( aType==0 ){ pC->aType = aType = sqliteMallocRaw( 2*nField*sizeof(aType) ); } if( aType==0 ){ goto no_mem; } 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 externally. ** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */ szHd
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -