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

📄 vdbeaux.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** 2003 September 6**** The author disclaims copyright to this source code.  In place of** a legal notice, here is a blessing:****    May you do good and not evil.**    May you find forgiveness for yourself and forgive others.**    May you share freely, never taking more than you give.***************************************************************************** This file contains code used for creating, destroying, and populating** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior** to version 2.8.7, all this code was combined into the vdbe.c source file.** But that file was getting too big so this subroutines were split out.*/#include "sqliteInt.h"#include "os.h"#include <ctype.h>#include "vdbeInt.h"/*** When debugging the code generator in a symbolic debugger, one can** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed** as they are added to the instruction stream.*/#ifdef SQLITE_DEBUGint sqlite3_vdbe_addop_trace = 0;#endif/*** Create a new virtual database engine.*/Vdbe *sqlite3VdbeCreate(sqlite3 *db){  Vdbe *p;  p = sqliteMalloc( sizeof(Vdbe) );  if( p==0 ) return 0;  p->db = db;  if( db->pVdbe ){    db->pVdbe->pPrev = p;  }  p->pNext = db->pVdbe;  p->pPrev = 0;  db->pVdbe = p;  p->magic = VDBE_MAGIC_INIT;  return p;}/*** Remember the SQL string for a prepared statement.*/void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n){  if( p==0 ) return;  assert( p->zSql==0 );  p->zSql = sqlite3StrNDup(z, n);}/*** Return the SQL associated with a prepared statement*/const char *sqlite3VdbeGetSql(Vdbe *p){  return p->zSql;}/*** Swap all content between two VDBE structures.*/void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){  Vdbe tmp, *pTmp;  char *zTmp;  int nTmp;  tmp = *pA;  *pA = *pB;  *pB = tmp;  pTmp = pA->pNext;  pA->pNext = pB->pNext;  pB->pNext = pTmp;  pTmp = pA->pPrev;  pA->pPrev = pB->pPrev;  pB->pPrev = pTmp;  zTmp = pA->zSql;  pA->zSql = pB->zSql;  pB->zSql = zTmp;  nTmp = pA->nSql;  pA->nSql = pB->nSql;  pB->nSql = nTmp;}#ifdef SQLITE_DEBUG/*** Turn tracing on or off*/void sqlite3VdbeTrace(Vdbe *p, FILE *trace){  p->trace = trace;}#endif/*** Resize the Vdbe.aOp array so that it contains at least N** elements. If the Vdbe is in VDBE_MAGIC_RUN state, then** the Vdbe.aOp array will be sized to contain exactly N** elements. Vdbe.nOpAlloc is set to reflect the new size of** the array.**** If an out-of-memory error occurs while resizing the array,** Vdbe.aOp and Vdbe.nOpAlloc remain unchanged (this is so that** any opcodes already allocated can be correctly deallocated** along with the rest of the Vdbe).*/static void resizeOpArray(Vdbe *p, int N){  int runMode = p->magic==VDBE_MAGIC_RUN;  if( runMode || p->nOpAlloc<N ){    VdbeOp *pNew;    int nNew = N + 100*(!runMode);    int oldSize = p->nOpAlloc;    pNew = sqliteRealloc(p->aOp, nNew*sizeof(Op));    if( pNew ){      p->nOpAlloc = nNew;      p->aOp = pNew;      if( nNew>oldSize ){        memset(&p->aOp[oldSize], 0, (nNew-oldSize)*sizeof(Op));      }    }  }}/*** Add a new instruction to the list of instructions current in the** VDBE.  Return the address of the new instruction.**** Parameters:****    p               Pointer to the VDBE****    op              The opcode for this instruction****    p1, p2          First two of the three possible operands.**** Use the sqlite3VdbeResolveLabel() function to fix an address and** the sqlite3VdbeChangeP3() function to change the value of the P3** operand.*/int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){  int i;  VdbeOp *pOp;  i = p->nOp;  assert( p->magic==VDBE_MAGIC_INIT );  if( p->nOpAlloc<=i ){    resizeOpArray(p, i+1);    if( sqlite3MallocFailed() ){      return 0;    }  }  p->nOp++;  pOp = &p->aOp[i];  pOp->opcode = op;  pOp->p1 = p1;  pOp->p2 = p2;  pOp->p3 = 0;  pOp->p3type = P3_NOTUSED;  p->expired = 0;#ifdef SQLITE_DEBUG  if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);#endif  return i;}/*** Add an opcode that includes the p3 value.*/int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3,int p3type){  int addr = sqlite3VdbeAddOp(p, op, p1, p2);  sqlite3VdbeChangeP3(p, addr, zP3, p3type);  return addr;}/*** Create a new symbolic label for an instruction that has yet to be** coded.  The symbolic label is really just a negative number.  The** label can be used as the P2 value of an operation.  Later, when** the label is resolved to a specific address, the VDBE will scan** through its operation list and change all values of P2 which match** the label into the resolved address.**** The VDBE knows that a P2 value is a label because labels are** always negative and P2 values are suppose to be non-negative.** Hence, a negative P2 value is a label that has yet to be resolved.**** Zero is returned if a malloc() fails.*/int sqlite3VdbeMakeLabel(Vdbe *p){  int i;  i = p->nLabel++;  assert( p->magic==VDBE_MAGIC_INIT );  if( i>=p->nLabelAlloc ){    p->nLabelAlloc = p->nLabelAlloc*2 + 10;    p->aLabel = sqliteReallocOrFree(p->aLabel,                                    p->nLabelAlloc*sizeof(p->aLabel[0]));  }  if( p->aLabel ){    p->aLabel[i] = -1;  }  return -1-i;}/*** Resolve label "x" to be the address of the next instruction to** be inserted.  The parameter "x" must have been obtained from** a prior call to sqlite3VdbeMakeLabel().*/void sqlite3VdbeResolveLabel(Vdbe *p, int x){  int j = -1-x;  assert( p->magic==VDBE_MAGIC_INIT );  assert( j>=0 && j<p->nLabel );  if( p->aLabel ){    p->aLabel[j] = p->nOp;  }}/*** Return non-zero if opcode 'op' is guarenteed not to push more values** onto the VDBE stack than it pops off.*/static int opcodeNoPush(u8 op){  /* The 10 NOPUSH_MASK_n constants are defined in the automatically  ** generated header file opcodes.h. Each is a 16-bit bitmask, one  ** bit corresponding to each opcode implemented by the virtual  ** machine in vdbe.c. The bit is true if the word "no-push" appears  ** in a comment on the same line as the "case OP_XXX:" in   ** sqlite3VdbeExec() in vdbe.c.  **  ** If the bit is true, then the corresponding opcode is guarenteed not  ** to grow the stack when it is executed. Otherwise, it may grow the  ** stack by at most one entry.  **  ** NOPUSH_MASK_0 corresponds to opcodes 0 to 15. NOPUSH_MASK_1 contains  ** one bit for opcodes 16 to 31, and so on.  **  ** 16-bit bitmasks (rather than 32-bit) are specified in opcodes.h   ** because the file is generated by an awk program. Awk manipulates  ** all numbers as floating-point and we don't want to risk a rounding  ** error if someone builds with an awk that uses (for example) 32-bit   ** IEEE floats.  */   static const u32 masks[5] = {    NOPUSH_MASK_0 + (((unsigned)NOPUSH_MASK_1)<<16),    NOPUSH_MASK_2 + (((unsigned)NOPUSH_MASK_3)<<16),    NOPUSH_MASK_4 + (((unsigned)NOPUSH_MASK_5)<<16),    NOPUSH_MASK_6 + (((unsigned)NOPUSH_MASK_7)<<16),    NOPUSH_MASK_8 + (((unsigned)NOPUSH_MASK_9)<<16)  };  assert( op<32*5 );  return (masks[op>>5] & (1<<(op&0x1F)));}#ifndef NDEBUGint sqlite3VdbeOpcodeNoPush(u8 op){  return opcodeNoPush(op);}#endif/*** Loop through the program looking for P2 values that are negative.** Each such value is a label.  Resolve the label by setting the P2** value to its correct non-zero value.**** This routine is called once after all opcodes have been inserted.**** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument ** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by ** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.**** The integer *pMaxStack is set to the maximum number of vdbe stack** entries that static analysis reveals this program might need.**** This routine also does the following optimization:  It scans for** Halt instructions where P1==SQLITE_CONSTRAINT or P2==OE_Abort or for** IdxInsert instructions where P2!=0.  If no such instruction is** found, then every Statement instruction is changed to a Noop.  In** this way, we avoid creating the statement journal file unnecessarily.*/static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){  int i;  int nMaxArgs = 0;  int nMaxStack = p->nOp;  Op *pOp;  int *aLabel = p->aLabel;  int doesStatementRollback = 0;  int hasStatementBegin = 0;  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){    u8 opcode = pOp->opcode;    if( opcode==OP_Function || opcode==OP_AggStep #ifndef SQLITE_OMIT_VIRTUALTABLE        || opcode==OP_VUpdate#endif    ){      if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;    }    if( opcode==OP_Halt ){      if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){        doesStatementRollback = 1;      }    }else if( opcode==OP_Statement ){      hasStatementBegin = 1;#ifndef SQLITE_OMIT_VIRTUALTABLE    }else if( opcode==OP_VUpdate || opcode==OP_VRename ){      doesStatementRollback = 1;    }else if( opcode==OP_VFilter ){      int n;      assert( p->nOp - i >= 3 );      assert( pOp[-2].opcode==OP_Integer );      n = pOp[-2].p1;      if( n>nMaxArgs ) nMaxArgs = n;#endif    }    if( opcodeNoPush(opcode) ){      nMaxStack--;    }    if( pOp->p2>=0 ) continue;    assert( -1-pOp->p2<p->nLabel );    pOp->p2 = aLabel[-1-pOp->p2];  }  sqliteFree(p->aLabel);  p->aLabel = 0;  *pMaxFuncArgs = nMaxArgs;  *pMaxStack = nMaxStack;  /* If we never rollback a statement transaction, then statement  ** transactions are not needed.  So change every OP_Statement  ** opcode into an OP_Noop.  This avoid a call to sqlite3OsOpenExclusive()  ** which can be expensive on some platforms.  */  if( hasStatementBegin && !doesStatementRollback ){    for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){      if( pOp->opcode==OP_Statement ){        pOp->opcode = OP_Noop;      }    }  }}/*** Return the address of the next instruction to be inserted.*/int sqlite3VdbeCurrentAddr(Vdbe *p){  assert( p->magic==VDBE_MAGIC_INIT );  return p->nOp;}/*** Add a whole list of operations to the operation stack.  Return the** address of the first operation added.*/int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){  int addr;  assert( p->magic==VDBE_MAGIC_INIT );  resizeOpArray(p, p->nOp + nOp);  if( sqlite3MallocFailed() ){    return 0;  }  addr = p->nOp;  if( nOp>0 ){    int i;    VdbeOpList const *pIn = aOp;    for(i=0; i<nOp; i++, pIn++){      int p2 = pIn->p2;      VdbeOp *pOut = &p->aOp[i+addr];      pOut->opcode = pIn->opcode;      pOut->p1 = pIn->p1;      pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;      pOut->p3 = pIn->p3;      pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;#ifdef SQLITE_DEBUG      if( sqlite3_vdbe_addop_trace ){        sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);      }#endif    }    p->nOp += nOp;  }  return addr;}/*** Change the value of the P1 operand for a specific instruction.** This routine is useful when a large program is loaded from a** static array using sqlite3VdbeAddOpList but we want to make a** few minor changes to the program.*/void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){  assert( p==0 || p->magic==VDBE_MAGIC_INIT );  if( p && addr>=0 && p->nOp>addr && p->aOp ){    p->aOp[addr].p1 = val;  }}/*** Change the value of the P2 operand for a specific instruction.** This routine is useful for setting a jump destination.*/void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){  assert( val>=0 );  assert( p==0 || p->magic==VDBE_MAGIC_INIT );  if( p && addr>=0 && p->nOp>addr && p->aOp ){    p->aOp[addr].p2 = val;  }}/*** Change the P2 operand of instruction addr so that it points to** the address of the next instruction to be coded.*/void sqlite3VdbeJumpHere(Vdbe *p, int addr){  sqlite3VdbeChangeP2(p, addr, p->nOp);}/*** If the input FuncDef structure is ephemeral, then free it.  If** the FuncDef is not ephermal, then do nothing.*/static void freeEphemeralFunction(FuncDef *pDef){  if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){    sqliteFree(pDef);  }}/*** Delete a P3 value if necessary.*/static void freeP3(int p3type, void *p3){  if( p3 ){

⌨️ 快捷键说明

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