⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdbe.c

📁 一个小型嵌入式数据库SQLite的源码,C语言
💻 C
📖 第 1 页 / 共 5 页
字号:
  popStack(&pTos, 2);  pTos++;  if( v1==2 ){    pTos->flags = MEM_Null;  }else{    pTos->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 ){    neg_abs_real_case:    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->i<0 ){      pTos->i = -pTos->i;    }    pTos->flags = MEM_Int;  }else if( pTos->flags & MEM_Null ){    /* Do nothing */  }else{    sqlite3VdbeMemNumerify(pTos);    goto neg_abs_real_case;  }  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->i = !pTos->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->i = ~pTos->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 ***** If any of the top abs(P1) values on the stack are NULL, then jump** to P2.  Pop the stack P1 times if P1>0.   If P1<0 leave the stack** unchanged.*/case OP_IsNull: {            /* same as TK_ISNULL, no-push */  int i, cnt;  Mem *pTerm;  cnt = pOp->p1;  if( cnt<0 ) cnt = -cnt;  pTerm = &pTos[1-cnt];  assert( pTerm>=p->aStack );  for(i=0; i<cnt; i++, pTerm++){    if( pTerm->flags & MEM_Null ){      pc = pOp->p2-1;      break;    }  }  if( pOp->p1>0 ) popStack(&pTos, cnt);  break;}/* Opcode: NotNull P1 P2 ***** Jump to P2 if the top P1 values on the stack are all not NULL.  Pop the** stack if P1 times if P1 is greater than zero.  If P1 is less than** zero then 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];  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;  }  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;      }    }    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 push a NULL onto the        ** stack 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 P3 if P3 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], pTos);    pTos->enc = encoding;  }else{    if( pOp->p3type==P3_MEM ){      sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);    }else{      pTos->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 ov

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -