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

📄 vdbe.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      }else{        zBuf[k++] = '.';      }    }    zBuf[k++] = ']';    sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);    k += strlen(&zBuf[k]);    zBuf[k++] = 0;  }}#endif#ifdef SQLITE_DEBUG/*** Print the value of a register for tracing purposes:*/static void memTracePrint(FILE *out, Mem *p){  if( p->flags & MEM_Null ){    fprintf(out, " NULL");  }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){    fprintf(out, " si:%lld", p->u.i);  }else if( p->flags & MEM_Int ){    fprintf(out, " i:%lld", p->u.i);  }else if( p->flags & MEM_Real ){    fprintf(out, " r:%g", p->r);  }else{    char zBuf[200];    sqlite3VdbeMemPrettyPrint(p, zBuf);    fprintf(out, " ");    fprintf(out, "%s", zBuf);  }}static void registerTrace(FILE *out, int iReg, Mem *p){  fprintf(out, "REG[%d] = ", iReg);  memTracePrint(out, p);  fprintf(out, "\n");}#endif#ifdef SQLITE_DEBUG#  define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M)#else#  define REGISTER_TRACE(R,M)#endif#ifdef VDBE_PROFILE/* ** hwtime.h contains inline assembler code for implementing ** high-performance timing routines.*/#include "hwtime.h"#endif/*** The CHECK_FOR_INTERRUPT macro defined here looks to see if the** sqlite3_interrupt() routine has been called.  If it has been, then** processing of the VDBE program is interrupted.**** This macro added to every instruction that does a jump in order to** implement a loop.  This test used to be on every single instruction,** but that meant we more testing that we needed.  By only testing the** flag on jump instructions, we get a (small) speed improvement.*/#define CHECK_FOR_INTERRUPT \   if( db->u1.isInterrupted ) goto abort_due_to_interrupt;#ifdef SQLITE_DEBUGstatic int fileExists(sqlite3 *db, const char *zFile){  int res = 0;  int rc = SQLITE_OK;#ifdef SQLITE_TEST  /* If we are currently testing IO errors, then do not call OsAccess() to  ** test for the presence of zFile. This is because any IO error that  ** occurs here will not be reported, causing the test to fail.  */  extern int sqlite3_io_error_pending;  if( sqlite3_io_error_pending<=0 )#endif    rc = sqlite3OsAccess(db->pVfs, zFile, SQLITE_ACCESS_EXISTS, &res);  return (res && rc==SQLITE_OK);}#endif/*** Execute as much of a VDBE program as we can then return.**** sqlite3VdbeMakeReady() must be called before this routine in order to** close the program with a final OP_Halt and to set up the callbacks** and the error message pointer.**** Whenever a row or result data is available, this routine will either** invoke the result callback (if there is one) or return with** SQLITE_ROW.**** If an attempt is made to open a locked database, then this routine** will either invoke the busy callback (if there is one) or it will** return SQLITE_BUSY.**** If an error occurs, an error message is written to memory obtained** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.** The error code is stored in p->rc and this routine returns SQLITE_ERROR.**** If the callback ever returns non-zero, then the program exits** immediately.  There will be no error message but the p->rc field is** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.**** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this** routine to return SQLITE_ERROR.**** Other fatal errors return SQLITE_ERROR.**** After this routine has finished, sqlite3VdbeFinalize() should be** used to clean up the mess that was left behind.*/int sqlite3VdbeExec(  Vdbe *p                    /* The VDBE */){  int pc;                    /* The program counter */  Op *pOp;                   /* Current operation */  int rc = SQLITE_OK;        /* Value to return */  sqlite3 *db = p->db;       /* The database */  u8 encoding = ENC(db);     /* The database encoding */  Mem *pIn1, *pIn2, *pIn3;   /* Input operands */  Mem *pOut;                 /* Output operand */  u8 opProperty;  int iCompare = 0;          /* Result of last OP_Compare operation */  int *aPermute = 0;         /* Permuation of columns for OP_Compare */#ifdef VDBE_PROFILE  u64 start;                 /* CPU clock count at start of opcode */  int origPc;                /* Program counter at start of opcode */#endif#ifndef SQLITE_OMIT_PROGRESS_CALLBACK  int nProgressOps = 0;      /* Opcodes executed since progress callback. */#endif  UnpackedRecord aTempRec[16]; /* Space to hold a transient UnpackedRecord */  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */  assert( db->magic==SQLITE_MAGIC_BUSY );  sqlite3BtreeMutexArrayEnter(&p->aMutex);  if( p->rc==SQLITE_NOMEM ){    /* This happens if a malloc() inside a call to sqlite3_column_text() or    ** sqlite3_column_text16() failed.  */    goto no_mem;  }  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );  p->rc = SQLITE_OK;  assert( p->explain==0 );  p->pResultSet = 0;  db->busyHandler.nBusy = 0;  CHECK_FOR_INTERRUPT;  sqlite3VdbeIOTraceSql(p);#ifdef SQLITE_DEBUG  sqlite3BeginBenignMalloc();  if( p->pc==0    && ((p->db->flags & SQLITE_VdbeListing) || fileExists(db, "vdbe_explain"))  ){    int i;    printf("VDBE Program Listing:\n");    sqlite3VdbePrintSql(p);    for(i=0; i<p->nOp; i++){      sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);    }  }  if( fileExists(db, "vdbe_trace") ){    p->trace = stdout;  }  sqlite3EndBenignMalloc();#endif  for(pc=p->pc; rc==SQLITE_OK; pc++){    assert( pc>=0 && pc<p->nOp );    if( db->mallocFailed ) goto no_mem;#ifdef VDBE_PROFILE    origPc = pc;    start = sqlite3Hwtime();#endif    pOp = &p->aOp[pc];    /* Only allow tracing if SQLITE_DEBUG is defined.    */#ifdef SQLITE_DEBUG    if( p->trace ){      if( pc==0 ){        printf("VDBE Execution Trace:\n");        sqlite3VdbePrintSql(p);      }      sqlite3VdbePrintOp(p->trace, pc, pOp);    }    if( p->trace==0 && pc==0 ){      sqlite3BeginBenignMalloc();      if( fileExists(db, "vdbe_sqltrace") ){        sqlite3VdbePrintSql(p);      }      sqlite3EndBenignMalloc();    }#endif          /* Check to see if we need to simulate an interrupt.  This only happens    ** if we have a special test build.    */#ifdef SQLITE_TEST    if( sqlite3_interrupt_count>0 ){      sqlite3_interrupt_count--;      if( sqlite3_interrupt_count==0 ){        sqlite3_interrupt(db);      }    }#endif#ifndef SQLITE_OMIT_PROGRESS_CALLBACK    /* Call the progress callback if it is configured and the required number    ** of VDBE ops have been executed (either since this invocation of    ** sqlite3VdbeExec() or since last time the progress callback was called).    ** If the progress callback returns non-zero, exit the virtual machine with    ** a return code SQLITE_ABORT.    */    if( db->xProgress ){      if( db->nProgressOps==nProgressOps ){        int prc;        if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;        prc =db->xProgress(db->pProgressArg);        if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;        if( prc!=0 ){          rc = SQLITE_INTERRUPT;          goto vdbe_error_halt;        }        nProgressOps = 0;      }      nProgressOps++;    }#endif    /* Do common setup processing for any opcode that is marked    ** with the "out2-prerelease" tag.  Such opcodes have a single    ** output which is specified by the P2 parameter.  The P2 register    ** is initialized to a NULL.    */    opProperty = opcodeProperty[pOp->opcode];    if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){      assert( pOp->p2>0 );      assert( pOp->p2<=p->nMem );      pOut = &p->aMem[pOp->p2];      sqlite3VdbeMemReleaseExternal(pOut);      pOut->flags = MEM_Null;    }else     /* Do common setup for opcodes marked with one of the following    ** combinations of properties.    **    **           in1    **           in1 in2    **           in1 in2 out3    **           in1 in3    **    ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate    ** registers for inputs.  Variable pOut points to the output register.    */    if( (opProperty & OPFLG_IN1)!=0 ){      assert( pOp->p1>0 );      assert( pOp->p1<=p->nMem );      pIn1 = &p->aMem[pOp->p1];      REGISTER_TRACE(pOp->p1, pIn1);      if( (opProperty & OPFLG_IN2)!=0 ){        assert( pOp->p2>0 );        assert( pOp->p2<=p->nMem );        pIn2 = &p->aMem[pOp->p2];        REGISTER_TRACE(pOp->p2, pIn2);        if( (opProperty & OPFLG_OUT3)!=0 ){          assert( pOp->p3>0 );          assert( pOp->p3<=p->nMem );          pOut = &p->aMem[pOp->p3];        }      }else if( (opProperty & OPFLG_IN3)!=0 ){        assert( pOp->p3>0 );        assert( pOp->p3<=p->nMem );        pIn3 = &p->aMem[pOp->p3];        REGISTER_TRACE(pOp->p3, pIn3);      }    }else if( (opProperty & OPFLG_IN2)!=0 ){      assert( pOp->p2>0 );      assert( pOp->p2<=p->nMem );      pIn2 = &p->aMem[pOp->p2];      REGISTER_TRACE(pOp->p2, pIn2);    }else if( (opProperty & OPFLG_IN3)!=0 ){      assert( pOp->p3>0 );      assert( pOp->p3<=p->nMem );      pIn3 = &p->aMem[pOp->p3];      REGISTER_TRACE(pOp->p3, pIn3);    }    switch( pOp->opcode ){/******************************************************************************* What follows is a massive switch statement where each case implements a** separate instruction in the virtual machine.  If we follow the usual** indentation conventions, each case should be indented by 6 spaces.  But** that is a lot of wasted space on the left margin.  So the code within** the switch statement will break with convention and be flush-left. Another** big comment (similar to this one) will mark the point in the code where** we transition back to normal indentation.**** The formatting of each case is important.  The makefile for SQLite** generates two C files "opcodes.h" and "opcodes.c" by scanning this** file looking for lines that begin with "case OP_".  The opcodes.h files** will be filled with #defines that give unique integer values to each** opcode and the opcodes.c file is filled with an array of strings where** each string is the symbolic name for the corresponding opcode.  If the** case statement is followed by a comment of the form "/# same as ... #/"** that comment is used to determine the particular value of the opcode.**** Other keywords in the comment that follows each case are used to** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].** Keywords include: in1, in2, in3, out2_prerelease, out2, out3.  See** the mkopcodeh.awk script for additional information.**** Documentation about VDBE opcodes is generated by scanning this file** for lines of that contain "Opcode:".  That line and all subsequent** comment lines are used in the generation of the opcode.html documentation** file.**** SUMMARY:****     Formatting is important to scripts that scan this file.**     Do not deviate from the formatting style currently in use.*******************************************************************************//* Opcode:  Goto * P2 * * ***** An unconditional jump to address P2.** The next instruction executed will be ** the one at index P2 from the beginning of** the program.*/case OP_Goto: {             /* jump */  CHECK_FOR_INTERRUPT;  pc = pOp->p2 - 1;  break;}/* Opcode:  Gosub P1 P2 * * ***** Write the current address onto register P1** and then jump to address P2.*/case OP_Gosub: {            /* jump */  assert( pOp->p1>0 );  assert( pOp->p1<=p->nMem );  pIn1 = &p->aMem[pOp->p1];  assert( (pIn1->flags & MEM_Dyn)==0 );  pIn1->flags = MEM_Int;  pIn1->u.i = pc;  REGISTER_TRACE(pOp->p1, pIn1);  pc = pOp->p2 - 1;  break;}/* Opcode:  Return P1 * * * ***** Jump to the next instruction after the address in register P1.*/case OP_Return: {           /* in1 */  assert( pIn1->flags & MEM_Int );  pc = pIn1->u.i;  break;}/* Opcode:  Yield P1 * * * ***** Swap the program counter with the value in register P1.*/case OP_Yield: {  int pcDest;  assert( pOp->p1>0 );  assert( pOp->p1<=p->nMem );  pIn1 = &p->aMem[pOp->p1];  assert( (pIn1->flags & MEM_Dyn)==0 );  pIn1->flags = MEM_Int;  pcDest = pIn1->u.i;  pIn1->u.i = pc;  REGISTER_TRACE(pOp->p1, pIn1);  pc = pcDest;  break;}/* Opcode:  Halt P1 P2 * P4 ***** Exit immediately.  All open cursors, Fifos, etc are closed** automatically.**** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),** or sqlite3_finalize().  For a normal halt, this should be SQLITE_OK (0).** For errors, it can be some other value.  If P1!=0 then P2 will determine** whether or not to rollback the current transaction.  Do not rollback** if P2==OE_Fail. Do the rollback if P2==OE_Rollback.  If P2==OE_Abort,** then back out all changes that have occurred during this execution of the** VDBE, but do not rollback the transaction. **** If P4 is not null then it is an error message string.**** There is an implied "Halt 0 0 0" instruction inserted at the very end of** every program.  So a jump past the last instruction of the program** is the same as executing Halt.*/case OP_Halt: {  p->rc = pOp->p1;  p->pc = pc;  p->errorAction = pOp->p2;  if( pOp->p4.z ){    sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);  }  rc = sqlite3VdbeHalt(p);  assert( rc==SQLITE_BUSY || rc==SQLITE_OK );  if( rc==SQLITE_BUSY ){    p->rc = rc = SQLITE_BUSY;

⌨️ 快捷键说明

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