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

📄 vdbe.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
      }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 + -