📄 vdbe.c
字号:
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&&R>0)registerTrace(p->trace,R,M)#else# define REGISTER_TRACE(R,M)#endif#ifdef VDBE_PROFILE/*** The following routine only works on pentium-class processors.** It uses the RDTSC opcode to read the cycle count value out of the** processor and returns that value. This can be used for high-res** profiling.*/__inline__ unsigned long long int hwtime(void){ unsigned long long int x; __asm__("rdtsc\n\t" "mov %%edx, %%ecx\n\t" :"=A" (x)); return x;}#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;/*** 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;#ifdef VDBE_PROFILE unsigned long long 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 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 if( p->pc==0 && ((p->db->flags & SQLITE_VdbeListing)!=0 || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS)) ){ int i; printf("VDBE Program Listing:\n"); sqlite3VdbePrintSql(p); for(i=0; i<p->nOp; i++){ sqlite3VdbePrintOp(stdout, i, &p->aOp[i]); } } if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS) ){ p->trace = stdout; }#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 = hwtime();#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 && sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS) ){ sqlite3VdbePrintSql(p); }#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]; sqlite3VdbeMemRelease(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 * P2 * * ***** Push the current address plus 1 onto the return address stack** and then jump to address P2.**** The return address stack is of limited depth. If too many** OP_Gosub operations occur without intervening OP_Returns, then** the return address stack will fill up and processing will abort** with a fatal error.*/case OP_Gosub: { /* jump */ assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) ); p->returnStack[p->returnDepth++] = pc+1; pc = pOp->p2 - 1; break;}/* Opcode: Return * * * * ***** Jump immediately to the next instruction after the last unreturned** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then** processing aborts with a fatal error.*/case OP_Return: { assert( p->returnDepth>0 ); p->returnDepth--; pc = p->returnStack[p->returnDepth] - 1; 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, pOp->p4.z, (char*)0); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); if( rc==SQLITE_BUSY ){ p->rc = rc = SQLITE_BUSY; }else{ rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return;}/* Opcode: Integer P1 P2 * * ***** The 32-bit integer value P1 is written into register P2.*/case OP_Integer: { /* out2-prerelease */ pOut->flags = MEM_Int; pOut->u.i = pOp->p1; break;}/* Opcode: Int64 * P2 * P4 ***** P4 is a pointer to a 64-bit integer value.** Write that value into register P2.*/case OP_Int64: { /* out2-prerelease */ assert( pOp->p4.pI64!=0 ); pOut->flags = MEM_Int; pOut->u.i = *pOp->p4.pI64; break;}/* Opcode: Real * P2 * P4 ***** P4 is a pointer to a 64-bit floating point value.** Write that value into register P2.*/case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ pOut->flags = MEM_Real; pOut->r = *pOp->p4.pReal; break;}/* Opcode: String8 * P2 * P4 ***** P4 points to a nul terminated UTF-8 string. This opcode is transformed ** into an OP_String before it is executed for the first time.*/case OP_String8: { /* same as TK_STRING, out2-prerelease */ assert( pOp->p4.z!=0 ); pOp->opcode = OP_String; pOp->p1 = strlen(pOp->p4.z);#ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -