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

📄 vdbeaux.c

📁 嵌入式数据库Sqlite,SQLlite小型数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
  assert( p->nOp>0 );  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0           || sqlite3MallocFailed() );  va_start(ap, zFormat);  sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC);  va_end(ap);}#endif/*** Return the opcode for a given address.*/VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){  assert( p->magic==VDBE_MAGIC_INIT );  assert( addr>=0 && addr<p->nOp );  return &p->aOp[addr];}#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)/*** Compute a string that describes the P3 parameter for an opcode.** Use zTemp for any required temporary buffer space.*/static char *displayP3(Op *pOp, char *zTemp, int nTemp){  char *zP3;  assert( nTemp>=20 );  switch( pOp->p3type ){    case P3_KEYINFO: {      int i, j;      KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;      sprintf(zTemp, "keyinfo(%d", pKeyInfo->nField);      i = strlen(zTemp);      for(j=0; j<pKeyInfo->nField; j++){        CollSeq *pColl = pKeyInfo->aColl[j];        if( pColl ){          int n = strlen(pColl->zName);          if( i+n>nTemp-6 ){            strcpy(&zTemp[i],",...");            break;          }          zTemp[i++] = ',';          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){            zTemp[i++] = '-';          }          strcpy(&zTemp[i], pColl->zName);          i += n;        }else if( i+4<nTemp-6 ){          strcpy(&zTemp[i],",nil");          i += 4;        }      }      zTemp[i++] = ')';      zTemp[i] = 0;      assert( i<nTemp );      zP3 = zTemp;      break;    }    case P3_COLLSEQ: {      CollSeq *pColl = (CollSeq*)pOp->p3;      sprintf(zTemp, "collseq(%.20s)", pColl->zName);      zP3 = zTemp;      break;    }    case P3_FUNCDEF: {      FuncDef *pDef = (FuncDef*)pOp->p3;      char zNum[30];      sprintf(zTemp, "%.*s", nTemp, pDef->zName);      sprintf(zNum,"(%d)", pDef->nArg);      if( strlen(zTemp)+strlen(zNum)+1<=nTemp ){        strcat(zTemp, zNum);      }      zP3 = zTemp;      break;    }    default: {      zP3 = pOp->p3;      if( zP3==0 || pOp->opcode==OP_Noop ){        zP3 = "";      }    }  }  return zP3;}#endif#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)/*** Print a single opcode.  This routine is used for debugging only.*/void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){  char *zP3;  char zPtr[50];  static const char *zFormat1 = "%4d %-13s %4d %4d %s\n";  if( pOut==0 ) pOut = stdout;  zP3 = displayP3(pOp, zPtr, sizeof(zPtr));  fprintf(pOut, zFormat1,      pc, sqlite3OpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3);  fflush(pOut);}#endif/*** Release an array of N Mem elements*/static void releaseMemArray(Mem *p, int N){  if( p ){    while( N-->0 ){      sqlite3VdbeMemRelease(p++);    }  }}#ifndef SQLITE_OMIT_EXPLAIN/*** Give a listing of the program in the virtual machine.**** The interface is the same as sqlite3VdbeExec().  But instead of** running the code, it invokes the callback once for each instruction.** This feature is used to implement "EXPLAIN".*/int sqlite3VdbeList(  Vdbe *p                   /* The VDBE */){  sqlite3 *db = p->db;  int i;  int rc = SQLITE_OK;  assert( p->explain );  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;  assert( db->magic==SQLITE_MAGIC_BUSY );  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );  /* Even though this opcode does not put dynamic strings onto the  ** the stack, they may become dynamic if the user calls  ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.  */  if( p->pTos==&p->aStack[4] ){    releaseMemArray(p->aStack, 5);  }  p->resOnStack = 0;  do{    i = p->pc++;  }while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );  if( i>=p->nOp ){    p->rc = SQLITE_OK;    rc = SQLITE_DONE;  }else if( db->flags & SQLITE_Interrupt ){    db->flags &= ~SQLITE_Interrupt;    p->rc = SQLITE_INTERRUPT;    rc = SQLITE_ERROR;    sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);  }else{    Op *pOp = &p->aOp[i];    Mem *pMem = p->aStack;    pMem->flags = MEM_Int;    pMem->type = SQLITE_INTEGER;    pMem->i = i;                                /* Program counter */    pMem++;    pMem->flags = MEM_Static|MEM_Str|MEM_Term;    pMem->z = sqlite3OpcodeNames[pOp->opcode];  /* Opcode */    pMem->n = strlen(pMem->z);    pMem->type = SQLITE_TEXT;    pMem->enc = SQLITE_UTF8;    pMem++;    pMem->flags = MEM_Int;    pMem->i = pOp->p1;                          /* P1 */    pMem->type = SQLITE_INTEGER;    pMem++;    pMem->flags = MEM_Int;    pMem->i = pOp->p2;                          /* P2 */    pMem->type = SQLITE_INTEGER;    pMem++;    pMem->flags = MEM_Ephem|MEM_Str|MEM_Term;   /* P3 */    pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort));    pMem->n = strlen(pMem->z);    pMem->type = SQLITE_TEXT;    pMem->enc = SQLITE_UTF8;    p->nResColumn = 5 - 2*(p->explain-1);    p->pTos = pMem;    p->rc = SQLITE_OK;    p->resOnStack = 1;    rc = SQLITE_ROW;  }  return rc;}#endif /* SQLITE_OMIT_EXPLAIN *//*** Print the SQL that was used to generate a VDBE program.*/void sqlite3VdbePrintSql(Vdbe *p){#ifdef SQLITE_DEBUG  int nOp = p->nOp;  VdbeOp *pOp;  if( nOp<1 ) return;  pOp = &p->aOp[nOp-1];  if( pOp->opcode==OP_Noop && pOp->p3!=0 ){    const char *z = pOp->p3;    while( isspace(*(u8*)z) ) z++;    printf("SQL: [%s]\n", z);  }#endif}/*** Prepare a virtual machine for execution.  This involves things such** as allocating stack space and initializing the program counter.** After the VDBE has be prepped, it can be executed by one or more** calls to sqlite3VdbeExec().  **** This is the only way to move a VDBE from VDBE_MAGIC_INIT to** VDBE_MAGIC_RUN.*/void sqlite3VdbeMakeReady(  Vdbe *p,                       /* The VDBE */  int nVar,                      /* Number of '?' see in the SQL statement */  int nMem,                      /* Number of memory cells to allocate */  int nCursor,                   /* Number of cursors to allocate */  int isExplain                  /* True if the EXPLAIN keywords is present */){  int n;  assert( p!=0 );  assert( p->magic==VDBE_MAGIC_INIT );  /* There should be at least one opcode.  */  assert( p->nOp>0 );  /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. This   * is because the call to resizeOpArray() below may shrink the   * p->aOp[] array to save memory if called when in VDBE_MAGIC_RUN    * state.   */  p->magic = VDBE_MAGIC_RUN;  /* No instruction ever pushes more than a single element onto the  ** stack.  And the stack never grows on successive executions of the  ** same loop.  So the total number of instructions is an upper bound  ** on the maximum stack depth required.  (Added later:)  The  ** resolveP2Values() call computes a tighter upper bound on the  ** stack size.  **  ** Allocation all the stack space we will ever need.  */  if( p->aStack==0 ){    int nArg;       /* Maximum number of args passed to a user function. */    int nStack;     /* Maximum number of stack entries required */    resolveP2Values(p, &nArg, &nStack);    resizeOpArray(p, p->nOp);    assert( nVar>=0 );    assert( nStack<p->nOp );    nStack = isExplain ? 10 : nStack;    p->aStack = sqliteMalloc(        nStack*sizeof(p->aStack[0])    /* aStack */      + nArg*sizeof(Mem*)              /* apArg */      + nVar*sizeof(Mem)               /* aVar */      + nVar*sizeof(char*)             /* azVar */      + nMem*sizeof(Mem)               /* aMem */      + nCursor*sizeof(Cursor*)        /* apCsr */    );    if( !sqlite3MallocFailed() ){      p->aMem = &p->aStack[nStack];      p->nMem = nMem;      p->aVar = &p->aMem[nMem];      p->nVar = nVar;      p->okVar = 0;      p->apArg = (Mem**)&p->aVar[nVar];      p->azVar = (char**)&p->apArg[nArg];      p->apCsr = (Cursor**)&p->azVar[nVar];      p->nCursor = nCursor;      for(n=0; n<nVar; n++){        p->aVar[n].flags = MEM_Null;      }    }  }  for(n=0; n<p->nMem; n++){    p->aMem[n].flags = MEM_Null;  }#ifdef SQLITE_DEBUG  if( (p->db->flags & SQLITE_VdbeListing)!=0    || sqlite3OsFileExists("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( sqlite3OsFileExists("vdbe_trace") ){    p->trace = stdout;  }#endif  p->pTos = &p->aStack[-1];  p->pc = -1;  p->rc = SQLITE_OK;  p->uniqueCnt = 0;  p->returnDepth = 0;  p->errorAction = OE_Abort;  p->popStack =  0;  p->explain |= isExplain;  p->magic = VDBE_MAGIC_RUN;  p->nChange = 0;  p->cacheCtr = 1;  p->minWriteFileFormat = 255;#ifdef VDBE_PROFILE  {    int i;    for(i=0; i<p->nOp; i++){      p->aOp[i].cnt = 0;      p->aOp[i].cycles = 0;    }  }#endif}/*** Close a cursor and release all the resources that cursor happens** to hold.*/void sqlite3VdbeFreeCursor(Cursor *pCx){  if( pCx==0 ){    return;  }  if( pCx->pCursor ){    sqlite3BtreeCloseCursor(pCx->pCursor);  }  if( pCx->pBt ){    sqlite3BtreeClose(pCx->pBt);  }  sqliteFree(pCx->pData);  sqliteFree(pCx->aType);  sqliteFree(pCx);}/*** Close all cursors*/static void closeAllCursors(Vdbe *p){  int i;  if( p->apCsr==0 ) return;  for(i=0; i<p->nCursor; i++){    sqlite3VdbeFreeCursor(p->apCsr[i]);    p->apCsr[i] = 0;  }}/*** Clean up the VM after execution.**** This routine will automatically close any cursors, lists, and/or** sorters that were left open.  It also deletes the values of** variables in the aVar[] array.*/static void Cleanup(Vdbe *p){  int i;  if( p->aStack ){    releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));    p->pTos = &p->aStack[-1];  }  closeAllCursors(p);  releaseMemArray(p->aMem, p->nMem);  sqlite3VdbeFifoClear(&p->sFifo);  if( p->contextStack ){    for(i=0; i<p->contextStackTop; i++){      sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);    }    sqliteFree(p->contextStack);  }  p->contextStack = 0;  p->contextStackDepth = 0;  p->contextStackTop = 0;  sqliteFree(p->zErrMsg);  p->zErrMsg = 0;}/*** Set the number of result columns that will be returned by this SQL** statement. This is now set at compile time, rather than during** execution of the vdbe program so that sqlite3_column_count() can** be called on an SQL statement before sqlite3_step().*/void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){  Mem *pColName;  int n;  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);  sqliteFree(p->aColName);  n = nResColumn*COLNAME_N;  p->nResColumn = nResColumn;  p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n );  if( p->aColName==0 ) return;  while( n-- > 0 ){    (pColName++)->flags = MEM_Null;  }}/*** Set the name of the idx'th column to be returned by the SQL statement.** zName must be a pointer to a nul terminated string.**** This call must be made after a call to sqlite3VdbeSetNumCols().**** If N==P3_STATIC  it means that zName is a pointer to a constant static** string and we can just copy the pointer. If it is P3_DYNAMIC, then ** the string is freed using sqliteFree() when the vdbe is finished with** it. Otherwise, N bytes of zName are copied.*/int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){  int rc;  Mem *pColName;  assert( idx<p->nResColumn );  assert( var<COLNAME_N );  if( sqlite3MallocFailed() ) return SQLITE_NOMEM;  assert( p->aColName!=0 );  pColName = &(p->aColName[idx+var*p->nResColumn]);  if( N==P3_DYNAMIC || N==P3_STATIC ){    rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC);  }else{    rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT);  }  if( rc==SQLITE_OK && N==P3_DYNAMIC ){    pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn;    pColName->xDel = 0;  }  return rc;}/*** A read or write transaction may or may not be active on database handle** db. If a transaction is active, commit it. If there is a** write-transaction spanning more than one database file, this routine** takes care of the master journal trickery.*/static int vdbeCommit(sqlite3 *db){  int i;  int nTrans = 0;  /* Number of databases with an active write-transaction */  int rc = SQLITE_OK;  int needXcommit = 0;  for(i=0; i<db->nDb; i++){     Btree *pBt = db->aDb[i].pBt;    if( pBt && sqlite3BtreeIsInTrans(pBt) ){      needXcommit = 1;      if( i!=1 ) nTrans++;    }  }  /* If there are any write-transactions at all, invoke the commit hook */  if( needXcommit && db->xCommitCallback ){    sqlite3SafetyOff(db);    rc = db->xCommitCallback(db->pCommitArg);    sqlite3SafetyOn(db);    if( rc ){      return SQLITE_CONSTRAINT;    }  }  /* The simple case - no more than one database file (not counting the  ** TEMP database) has a transaction active.   There is no need for the  ** master-journal.  **  ** If the return value of sqlite3BtreeGetFilename() is a zero length  ** string, it means the main database is :memory:.  In that case we do  ** not support atomic multi-file commits, so use the simple case then  ** too.  */  if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt ){        rc = sqlite3BtreeSync(pBt, 0);      }    }    /* Do the commit only if all databases successfully synced */    if( rc==SQLITE_OK ){      for(i=0; i<db->nDb; i++){        Btree *pBt = db->aDb[i].pBt;        if( pBt ){          sqlite3BtreeCommit(pBt);        }      }    }  }

⌨️ 快捷键说明

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