📄 vdbe.c
字号:
** 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]; } Release(pOut); if( v1==2 ){ pOut->flags = MEM_Null; }else{ pOut->u.i = v1; pOut->flags = 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 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: { 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 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; assert( p1<p->nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &p->aMem[pOp->p3]; sqlite3VdbeMemSetNull(pDest); /* 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>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->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 = sqlite3DbMallocRaw(db, 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 ); */ szHdrSz = GetVarint((u8*)zData, offset); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete ** record header if the record header does not fit on a single page ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to ** acquire the complete header text. */ if( !zRec && avail<offset ){ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } zEndHdr = (u8 *)&zData[offset]; zIdx = (u8 *)&zData[szHdrSz]; /* Scan the header and use it to fill in the aType[] and aOffset[] ** arrays. aType[i] will contain the type integer for the i-th ** column and aOffset[i] will contain the offset from the beginning ** of the record to the start of the data for the i-th column */ for(i=0; i<nField; i++){ if( zIdx<zEndHdr ){ aOffset[i] = offset; zIdx += GetVarint(zIdx, aType[i]); offset += sqlite3VdbeSerialTypeLen(aType[i]); }else{ /* If i is less that nField, then there are less fields in this ** record than SetNumColumns indicated there are columns in the ** table. Set the offset for any extra columns not present in ** the record to 0. This tells code below to store a NULL ** instead of deserializing a value from the record. */ aOffset[i] = 0; } } Release(&sMem); sMem.flags = MEM_Null; /* If we have read more header data than was contained in the header, ** or if the end of the last field appears to be past the end of the ** record, then we must be dealing with a corrupt database. */ if( zIdx>zEndHdr || offset>payloadSize ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; } } /* Get the column information. If aOffset[p2] is non-zero, then ** deserialize the value from the record. If aOffset[p2] is zero, ** then there are not enough fields in the record to satisfy the ** request. In this case, set the value NULL or to P4 if P4 is ** a pointer to a Mem object. */ if( aOffset[p2] ){ assert( rc==SQLITE_OK ); if( zRec ){ zData = &zRec[aOffset[p2]]; }else{ len = sqlite3VdbeSerialTypeLen(aType[p2]); rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest); pDest->enc = encoding; }else{ if( pOp->p4type==P4_MEM ){ sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); }else{ assert( pDest->flags==MEM_Null ); } } /* If we dynamically allocated space to hold the data (in the ** sqlite3VdbeMemFromBtree() call above) then transfer control of that ** dynamically allocated space over to the pDest structure. ** This prevents a memory copy. */ if( (sMem.flags & MEM_Dyn)!=0 ){ assert( pDest->flags & MEM_Ephem ); assert( pDest->flags & (MEM_Str|MEM_Blob) ); assert( pDest->z==sMem.z ); assert( sMem.flags & MEM_Term ); pDest->flags &= ~MEM_Ephem; pDest->flags |= MEM_Dyn|MEM_Term; } /* pDest->z might be pointing to sMem.zShort[]. Fix that so that we ** can abandon sMem */ rc = sqlite3VdbeMemMakeWriteable(pDest);op_column_out: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break;}/* Opcode: MakeRecord P1 P2 P3 P4 ***** Convert P2 registers beginning with P1 into a single entry** suitable for use as a data record in a database table or as a key** in an index. The details of the format are irrelavant as long as** the OP_Column opcode can decode the record later and as long as the** sqlite3VdbeRecordCompare function will correctly compare two encoded** records. Refer to source code comments for the details of the record** format.**** P4 may be a string that is P1 characters long. The nth character of the** string indicates the column affinity that should be used for the nth** field of the index key.**** The mapping from character to affinity is given by the SQLITE_AFF_** macros defined in sqliteInt.h.**** If P4 is NULL then all index fields have the affinity NONE.*/case OP_MakeRecord:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -