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

📄 vdbe.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** 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.469 2005/06/12 21:35:53 drh Exp $*/#include "sqliteInt.h"#include "os.h"#include <ctype.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.*/int sqlite3_search_count = 0;/*** When this global variable is positive, it gets decremented once before** each instruction in the VDBE.  When reaches zero, the SQLITE_Interrupt** of the db.flags field is set in order to simulate and interrupt.**** This facility is used for testing purposes only.  It does not function** in an ordinary build.*/int sqlite3_interrupt_count = 0;/*** 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.*/int sqlite3_sort_count = 0;/*** 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)/*** 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;}/*** Convert the given stack entity into a integer if it isn't one** already.**** Any prior string or real representation is invalidated.  ** NULLs are converted into 0.*/#define Integerify(P) sqlite3VdbeMemIntegerify(P)/*** Convert P so that it has type MEM_Real.**** Any prior string or integer representation is invalidated.** NULLs are converted into 0.0.*/#define Realify(P) sqlite3VdbeMemRealify(P)/*** 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;  }}/*** Insert a new aggregate element and make it the element that** has focus.**** Return 0 on success and 1 if memory is exhausted.*/static int AggInsert(Agg *p, char *zKey, int nKey){  AggElem *pElem;  int i;  int rc;  pElem = sqliteMalloc( sizeof(AggElem) + nKey +                        (p->nMem-1)*sizeof(pElem->aMem[0]) );  if( pElem==0 ) return SQLITE_NOMEM;  pElem->zKey = (char*)&pElem->aMem[p->nMem];  memcpy(pElem->zKey, zKey, nKey);  pElem->nKey = nKey;  if( p->pCsr ){    rc = sqlite3BtreeInsert(p->pCsr, zKey, nKey, &pElem, sizeof(AggElem*));    if( rc!=SQLITE_OK ){      sqliteFree(pElem);      return rc;    }  }  for(i=0; i<p->nMem; i++){    pElem->aMem[i].flags = MEM_Null;  }  p->pCurrent = pElem;  return 0;}/*** Pop the stack N times.*/static void popStack(Mem **ppTos, int N){  Mem *pTos = *ppTos;  while( N>0 ){    N--;    Release(pTos);    pTos--;  }  *ppTos = pTos;}/*** The parameters are pointers to the head of two sorted lists** of Sorter structures.  Merge these two lists together and return** a single sorted list.  This routine forms the core of the merge-sort** algorithm.**** In the case of a tie, left sorts in front of right.*/static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){  Sorter sHead;  Sorter *pTail;  pTail = &sHead;  pTail->pNext = 0;  while( pLeft && pRight ){    int c = sqlite3VdbeRecordCompare(pKeyInfo, pLeft->nKey, pLeft->zKey,                                     pRight->nKey, pRight->zKey);    if( c<=0 ){      pTail->pNext = pLeft;      pLeft = pLeft->pNext;    }else{      pTail->pNext = pRight;      pRight = pRight->pNext;    }    pTail = pTail->pNext;  }  if( pLeft ){    pTail->pNext = pLeft;  }else if( pRight ){    pTail->pNext = pRight;  }  return sHead.pNext;}/*** Allocate cursor number iCur.  Return a pointer to it.  Return NULL** if we run out of memory.*/static Cursor *allocateCursor(Vdbe *p, int iCur){  Cursor *pCx;  assert( iCur<p->nCursor );  if( p->apCsr[iCur] ){    sqlite3VdbeFreeCursor(p->apCsr[iCur]);  }  p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );  return pCx;}/*** Apply any conversion required by the supplied column affinity to** memory cell pRec. affinity may be one of:**** SQLITE_AFF_NUMERIC** SQLITE_AFF_TEXT** SQLITE_AFF_NONE** SQLITE_AFF_INTEGER***/static void applyAffinity(Mem *pRec, char affinity, u8 enc){  if( affinity==SQLITE_AFF_NONE ){    /* do nothing */  }else 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( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){      /* pRec does not have a valid integer or real representation.       ** Attempt a conversion if pRec has a string representation and      ** it looks like a number.      */      int realnum;      sqlite3VdbeMemNulTerminate(pRec);      if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum, enc) ){        if( realnum ){          Realify(pRec);        }else{          Integerify(pRec);        }      }    }    if( affinity==SQLITE_AFF_INTEGER ){      /* For INTEGER affinity, try to convert a real value to an int */      if( (pRec->flags&MEM_Real) && !(pRec->flags&MEM_Int) ){        pRec->i = pRec->r;        if( ((double)pRec->i)==pRec->r ){          pRec->flags |= MEM_Int;        }      }    }  }}/*** 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, int nBuf){  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';    }    zCsr += sprintf(zCsr, "%c", c);    zCsr += sprintf(zCsr, "%d[", pMem->n);    for(i=0; i<16 && i<pMem->n; i++){      zCsr += sprintf(zCsr, "%02X ", ((int)pMem->z[i] & 0xFF));    }    for(i=0; i<16 && i<pMem->n; i++){      char z = pMem->z[i];      if( z<32 || z>126 ) *zCsr++ = '.';      else *zCsr++ = z;    }    zCsr += sprintf(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;    k += sprintf(&zBuf[k], "%d", pMem->n);    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++] = ']';    k += sprintf(&zBuf[k], encnames[pMem->enc]);    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->flags & SQLITE_Interrupt ) 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.**

⌨️ 快捷键说明

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