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

📄 vdbeaux.c

📁 最新的sqlite3.6.2源代码
💻 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.**** $Id: vdbeaux.c,v 1.409 2008/08/20 22:06:48 drh Exp $*/#include "sqliteInt.h"#include <ctype.h>#include "vdbeInt.h"/*** When debugging the code generator in a symbolic debugger, one can** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed** as they are added to the instruction stream.*/#ifdef SQLITE_DEBUGint sqlite3VdbeAddopTrace = 0;#endif/*** Create a new virtual database engine.*/Vdbe *sqlite3VdbeCreate(sqlite3 *db){  Vdbe *p;  p = sqlite3DbMallocZero(db, 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 = sqlite3DbStrNDup(p->db, z, n);}/*** Return the SQL associated with a prepared statement*/const char *sqlite3_sql(sqlite3_stmt *pStmt){  return ((Vdbe *)pStmt)->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 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){  VdbeOp *pNew;  pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op));  if( pNew ){    p->nOpAlloc = N;    p->aOp = pNew;  }}/*** 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, p3      Operands**** Use the sqlite3VdbeResolveLabel() function to fix an address and** the sqlite3VdbeChangeP4() function to change the value of the P4** operand.*/int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){  int i;  VdbeOp *pOp;  i = p->nOp;  assert( p->magic==VDBE_MAGIC_INIT );  if( p->nOpAlloc<=i ){    resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op));    if( p->db->mallocFailed ){      return 0;    }  }  p->nOp++;  pOp = &p->aOp[i];  pOp->opcode = op;  pOp->p5 = 0;  pOp->p1 = p1;  pOp->p2 = p2;  pOp->p3 = p3;  pOp->p4.p = 0;  pOp->p4type = P4_NOTUSED;  p->expired = 0;#ifdef SQLITE_DEBUG  pOp->zComment = 0;  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);#endif#ifdef VDBE_PROFILE  pOp->cycles = 0;  pOp->cnt = 0;#endif  return i;}int sqlite3VdbeAddOp0(Vdbe *p, int op){  return sqlite3VdbeAddOp3(p, op, 0, 0, 0);}int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){  return sqlite3VdbeAddOp3(p, op, p1, 0, 0);}int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){  return sqlite3VdbeAddOp3(p, op, p1, p2, 0);}/*** Add an opcode that includes the p4 value as a pointer.*/int sqlite3VdbeAddOp4(  Vdbe *p,            /* Add the opcode to this VM */  int op,             /* The new opcode */  int p1,             /* The P1 operand */  int p2,             /* The P2 operand */  int p3,             /* The P3 operand */  const char *zP4,    /* The P4 operand */  int p4type          /* P4 operand type */){  int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);  sqlite3VdbeChangeP4(p, addr, zP4, p4type);  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 = sqlite3DbReallocOrFree(p->db, 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;  }}/*** Loop through the program looking for P2 values that are negative** on jump instructions.  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.**** This routine also does the following optimization:  It scans for** instructions that might cause a statement rollback.  Such instructions** are:****   *  OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.**   *  OP_Destroy**   *  OP_VUpdate**   *  OP_VRename**** 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 i;  int nMaxArgs = 0;  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 ){      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;#ifndef SQLITE_OMIT_VIRTUALTABLE    }else if( opcode==OP_VUpdate ){      if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;#endif    }    if( opcode==OP_Halt ){      if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){        doesStatementRollback = 1;      }    }else if( opcode==OP_Statement ){      hasStatementBegin = 1;    }else if( opcode==OP_Destroy ){      doesStatementRollback = 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[-1].opcode==OP_Integer );      n = pOp[-1].p1;      if( n>nMaxArgs ) nMaxArgs = n;#endif    }    if( sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_JUMP) && pOp->p2<0 ){      assert( -1-pOp->p2<p->nLabel );      pOp->p2 = aLabel[-1-pOp->p2];    }  }  sqlite3DbFree(p->db, p->aLabel);  p->aLabel = 0;  *pMaxFuncArgs = nMaxArgs;  /* 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 );  if( p->nOp + nOp > p->nOpAlloc ){    resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op));    assert( p->nOp+nOp<=p->nOpAlloc || p->db->mallocFailed );  }  if( p->db->mallocFailed ){    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;      if( p2<0 && sqlite3VdbeOpcodeHasProperty(pOut->opcode, OPFLG_JUMP) ){        pOut->p2 = addr + ADDR(p2);      }else{        pOut->p2 = p2;      }      pOut->p3 = pIn->p3;      pOut->p4type = P4_NOTUSED;      pOut->p4.p = 0;      pOut->p5 = 0;#ifdef SQLITE_DEBUG      pOut->zComment = 0;      if( sqlite3VdbeAddopTrace ){        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( p==0 || p->magic==VDBE_MAGIC_INIT );  if( p && addr>=0 && p->nOp>addr && p->aOp ){    p->aOp[addr].p2 = val;  }}/*** Change the value of the P3 operand for a specific instruction.*/void sqlite3VdbeChangeP3(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].p3 = val;  }}/*** Change the value of the P5 operand for the most recently** added operation.*/void sqlite3VdbeChangeP5(Vdbe *p, u8 val){  assert( p==0 || p->magic==VDBE_MAGIC_INIT );  if( p && p->aOp ){    assert( p->nOp>0 );    p->aOp[p->nOp-1].p5 = 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(sqlite3 *db, FuncDef *pDef){  if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){    sqlite3DbFree(db, pDef);  }}/*** Delete a P4 value if necessary.*/static void freeP4(sqlite3 *db, int p4type, void *p4){  if( p4 ){    switch( p4type ){

⌨️ 快捷键说明

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