📄 vdbe.c
字号:
/*** 2001 September 15**** 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.***************************************************************************** The code in this file implements execution method of the ** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")** handles housekeeping details such as creating and deleting** VDBE instances. This file is solely interested in executing** the VDBE program.**** In the external interface, an "sqlite3_stmt*" is an opaque pointer** to a VDBE.**** The SQL parser generates a program which is then executed by** the VDBE to do the work of the SQL statement. VDBE programs are ** similar in form to assembly language. The program consists of** a linear sequence of operations. Each operation has an opcode ** and 3 operands. Operands P1 and P2 are integers. Operand P3 ** is a null-terminated string. The P2 operand must be non-negative.** Opcodes will typically ignore one or more operands. Many opcodes** ignore all three operands.**** Computation results are stored on a stack. Each entry on the** stack is either an integer, a null-terminated string, a floating point** number, or the SQL "NULL" value. An inplicit conversion from one** type to the other occurs as necessary.** ** Most of the code in this file is taken up by the sqlite3VdbeExec()** function which does the work of interpreting a VDBE program.** But other routines are also provided to help in building up** a program instruction by instruction.**** Various scripts scan this source file in order to generate HTML** documentation, headers files, or other derived files. The formatting** of the code in this file is, therefore, important. See other comments** in this file for details. If in doubt, do not deviate from existing** commenting and indentation practices when changing or adding code.**** $Id: vdbe.c,v 1.636 2007/07/01 21:18:40 drh Exp $*/#include "sqliteInt.h"#include "os.h"#include <ctype.h>#include <math.h>#include "vdbeInt.h"/*** The following global variable is incremented every time a cursor** moves, either by the OP_MoveXX, OP_Next, or OP_Prev opcodes. The test** procedures use this information to make sure that indices are** working correctly. This variable has no function other than to** help verify the correct operation of the library.*/#ifdef SQLITE_TESTint sqlite3_search_count = 0;#endif/*** When this global variable is positive, it gets decremented once before** each instruction in the VDBE. When reaches zero, the u1.isInterrupted** field of the sqlite3 structure is set in order to simulate and interrupt.**** This facility is used for testing purposes only. It does not function** in an ordinary build.*/#ifdef SQLITE_TESTint sqlite3_interrupt_count = 0;#endif/*** The next global variable is incremented each type the OP_Sort opcode** is executed. The test procedures use this information to make sure that** sorting is occurring or not occuring at appropriate times. This variable** has no function other than to help verify the correct operation of the** library.*/#ifdef SQLITE_TESTint sqlite3_sort_count = 0;#endif/*** The next global variable records the size of the largest MEM_Blob** or MEM_Str that has appeared on the VDBE stack. The test procedures** use this information to make sure that the zero-blob functionality** is working correctly. This variable has no function other than to** help verify the correct operation of the library.*/#ifdef SQLITE_TESTint sqlite3_max_blobsize = 0;#endif/*** Release the memory associated with the given stack level. This** leaves the Mem.flags field in an inconsistent state.*/#define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); }/*** Convert the given stack entity into a string if it isn't one** already. Return non-zero if a malloc() fails.*/#define Stringify(P, enc) \ if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ { goto no_mem; }/*** Convert the given stack entity into a string that has been obtained** from sqliteMalloc(). This is different from Stringify() above in that** Stringify() will use the NBFS bytes of static string space if the string** will fit but this routine always mallocs for space.** Return non-zero if we run out of memory.*/#define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P)/*** The header of a record consists of a sequence variable-length integers.** These integers are almost always small and are encoded as a single byte.** The following macro takes advantage this fact to provide a fast decode** of the integers in a record header. It is faster for the common case** where the integer is a single byte. It is a little slower when the** integer is two or more bytes. But overall it is faster.**** The following expressions are equivalent:**** x = sqlite3GetVarint32( A, &B );**** x = GetVarint( A, B );***/#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))/*** An ephemeral string value (signified by the MEM_Ephem flag) contains** a pointer to a dynamically allocated string where some other entity** is responsible for deallocating that string. Because the stack entry** does not control the string, it might be deleted without the stack** entry knowing it.**** This routine converts an ephemeral string into a dynamically allocated** string that the stack entry itself controls. In other words, it** converts an MEM_Ephem string into an MEM_Dyn string.*/#define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}/*** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)** P if required.*/#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)/*** Argument pMem points at a memory cell that will be passed to a** user-defined function or returned to the user as the result of a query.** The second argument, 'db_enc' is the text encoding used by the vdbe for** stack variables. This routine sets the pMem->enc and pMem->type** variables used by the sqlite3_value_*() routines.*/#define storeTypeInfo(A,B) _storeTypeInfo(A)static void _storeTypeInfo(Mem *pMem){ int flags = pMem->flags; if( flags & MEM_Null ){ pMem->type = SQLITE_NULL; } else if( flags & MEM_Int ){ pMem->type = SQLITE_INTEGER; } else if( flags & MEM_Real ){ pMem->type = SQLITE_FLOAT; } else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; }}/*** Pop the stack N times.*/static void popStack(Mem **ppTos, int N){ Mem *pTos = *ppTos; while( N>0 ){ N--; Release(pTos); pTos--; } *ppTos = pTos;}/*** Allocate cursor number iCur. Return a pointer to it. Return NULL** if we run out of memory.*/static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){ Cursor *pCx; assert( iCur<p->nCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); } p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) ); if( pCx ){ pCx->iDb = iDb; } return pCx;}/*** Try to convert a value into a numeric representation if we can** do so without loss of information. In other words, if the string** looks like a number, convert it into a number. If it does not** look like a number, leave it alone.*/static void applyNumericAffinity(Mem *pRec){ if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ int realnum; sqlite3VdbeMemNulTerminate(pRec); if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){ i64 value; sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); if( !realnum && sqlite3Atoi64(pRec->z, &value) ){ sqlite3VdbeMemRelease(pRec); pRec->u.i = value; pRec->flags = MEM_Int; }else{ sqlite3VdbeMemRealify(pRec); } } }}/*** Processing is determine by the affinity parameter:**** SQLITE_AFF_INTEGER:** SQLITE_AFF_REAL:** SQLITE_AFF_NUMERIC:** Try to convert pRec to an integer representation or a ** floating-point representation if an integer representation** is not possible. Note that the integer representation is** always preferred, even if the affinity is REAL, because** an integer representation is more space efficient on disk.**** SQLITE_AFF_TEXT:** Convert pRec to a text representation.**** SQLITE_AFF_NONE:** No-op. pRec is unchanged.*/static void applyAffinity(Mem *pRec, char affinity, u8 enc){ if( affinity==SQLITE_AFF_TEXT ){ /* Only attempt the conversion to TEXT if there is an integer or real ** representation (blob and NULL do not get converted) but no string ** representation. */ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ sqlite3VdbeMemStringify(pRec, enc); } pRec->flags &= ~(MEM_Real|MEM_Int); }else if( affinity!=SQLITE_AFF_NONE ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); applyNumericAffinity(pRec); if( pRec->flags & MEM_Real ){ sqlite3VdbeIntegerAffinity(pRec); } }}/*** Try to convert the type of a function argument or a result column** into a numeric representation. Use either INTEGER or REAL whichever** is appropriate. But only do the conversion if it is possible without** loss of information and return the revised type of the argument.**** This is an EXPERIMENTAL api and is subject to change or removal.*/int sqlite3_value_numeric_type(sqlite3_value *pVal){ Mem *pMem = (Mem*)pVal; applyNumericAffinity(pMem); storeTypeInfo(pMem, 0); return pMem->type;}/*** Exported version of applyAffinity(). This one works on sqlite3_value*, ** not the internal Mem* type.*/void sqlite3ValueApplyAffinity(sqlite3_value *pVal, u8 affinity, u8 enc){ applyAffinity((Mem *)pVal, affinity, enc);}#ifdef SQLITE_DEBUG/*** Write a nice string representation of the contents of cell pMem** into buffer zBuf, length nBuf.*/void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ char *zCsr = zBuf; int f = pMem->flags; static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; if( f&MEM_Blob ){ int i; char c; if( f & MEM_Dyn ){ c = 'z'; assert( (f & (MEM_Static|MEM_Ephem))==0 ); }else if( f & MEM_Static ){ c = 't'; assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); }else if( f & MEM_Ephem ){ c = 'e'; assert( (f & (MEM_Static|MEM_Dyn))==0 ); }else{ c = 's'; } sqlite3_snprintf(100, zCsr, "%c", c); zCsr += strlen(zCsr); sqlite3_snprintf(100, zCsr, "%d[", pMem->n); zCsr += strlen(zCsr); for(i=0; i<16 && i<pMem->n; i++){ sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); zCsr += strlen(zCsr); } for(i=0; i<16 && i<pMem->n; i++){ char z = pMem->z[i]; if( z<32 || z>126 ) *zCsr++ = '.'; else *zCsr++ = z; } sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]); zCsr += strlen(zCsr); if( f & MEM_Zero ){ sqlite3_snprintf(100, zCsr,"+%lldz",pMem->u.i); zCsr += strlen(zCsr); } *zCsr = '\0'; }else if( f & MEM_Str ){ int j, k; zBuf[0] = ' '; if( f & MEM_Dyn ){ zBuf[1] = 'z'; assert( (f & (MEM_Static|MEM_Ephem))==0 ); }else if( f & MEM_Static ){ zBuf[1] = 't'; assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); }else if( f & MEM_Ephem ){ zBuf[1] = 'e'; assert( (f & (MEM_Static|MEM_Dyn))==0 ); }else{ zBuf[1] = 's'; } k = 2; sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); k += strlen(&zBuf[k]); zBuf[k++] = '['; for(j=0; j<15 && j<pMem->n; j++){ u8 c = pMem->z[j]; if( c>=0x20 && c<0x7f ){ zBuf[k++] = c; }else{ zBuf[k++] = '.'; } } zBuf[k++] = ']'; sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]); k += strlen(&zBuf[k]); zBuf[k++] = 0; }}#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -