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

📄 vdbeaux.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
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;  i = p->pc++;  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_Short|MEM_Str|MEM_Term;   /* P3 */    pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort));    pMem->type = SQLITE_TEXT;    pMem->enc = SQLITE_UTF8;    p->nResColumn = 5;    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 nAgg,                      /* Number of aggregate contexts required */  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 */      + nAgg*sizeof(Agg)               /* Aggregate contexts */    );    if( !sqlite3_malloc_failed ){      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];      if( nAgg>0 ){        p->nAgg = nAgg;        p->apAgg = (Agg*)&p->apCsr[nCursor];      }      p->nCursor = nCursor;      for(n=0; n<nVar; n++){        p->aVar[n].flags = MEM_Null;      }    }  }  p->pAgg = p->apAgg;  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;#ifdef VDBE_PROFILE  {    int i;    for(i=0; i<p->nOp; i++){      p->aOp[i].cnt = 0;      p->aOp[i].cycles = 0;    }  }#endif}/*** Remove any elements that remain on the sorter for the VDBE given.*/void sqlite3VdbeSorterReset(Vdbe *p){  while( p->pSort ){    Sorter *pSorter = p->pSort;    p->pSort = pSorter->pNext;    sqliteFree(pSorter->zKey);    sqlite3VdbeMemRelease(&pSorter->data);    sqliteFree(pSorter);  }  p->pSortTail = 0;}/*** Free all resources allociated with AggElem pElem, an element of** aggregate pAgg.*/static void freeAggElem(AggElem *pElem, Agg *pAgg){  int i;  for(i=0; i<pAgg->nMem; i++){    Mem *pMem = &pElem->aMem[i];    if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){      sqlite3_context ctx;      ctx.pFunc = pAgg->apFunc[i];      ctx.s.flags = MEM_Null;      ctx.pAgg = pMem->z;      ctx.cnt = pMem->i;      ctx.isError = 0;      (*ctx.pFunc->xFinalize)(&ctx);      pMem->z = ctx.pAgg;      if( pMem->z!=0 && pMem->z!=pMem->zShort ){        sqliteFree(pMem->z);      }      sqlite3VdbeMemRelease(&ctx.s);    }else{      sqlite3VdbeMemRelease(pMem);    }  }  sqliteFree(pElem);}/*** Reset an Agg structure.  Delete all its contents.**** For installable aggregate functions, if the step function has been** called, make sure the finalizer function has also been called.  The** finalizer might need to free memory that was allocated as part of its** private context.  If the finalizer has not been called yet, call it** now.**** If db is NULL, then this is being called from sqliteVdbeReset(). In** this case clean up all references to the temp-table used for** aggregates (if it was ever opened).**** If db is not NULL, then this is being called from with an OP_AggReset** opcode. Open the temp-table, if it has not already been opened and** delete the contents of the table used for aggregate information, ready** for the next round of aggregate processing.*/int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){  int rc = 0;  BtCursor *pCsr;  if( !pAgg ) return SQLITE_OK;  pCsr = pAgg->pCsr;  assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0)         || sqlite3_malloc_failed );  /* If pCsr is not NULL, then the table used for aggregate information  ** is open. Loop through it and free the AggElem* structure pointed at  ** by each entry. If the finalizer has not been called for an AggElem,  ** do that too. Finally, clear the btree table itself.  */  if( pCsr ){    int res;    assert( pAgg->pBtree );    assert( pAgg->nTab>0 );    rc=sqlite3BtreeFirst(pCsr, &res);    while( res==0 && rc==SQLITE_OK ){      AggElem *pElem;      rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);      if( rc!=SQLITE_OK ){        return rc;      }      assert( pAgg->apFunc!=0 );      freeAggElem(pElem, pAgg);      rc=sqlite3BtreeNext(pCsr, &res);    }    if( rc!=SQLITE_OK ){      return rc;    }    sqlite3BtreeCloseCursor(pCsr);    sqlite3BtreeClearTable(pAgg->pBtree, pAgg->nTab);  }else{     /* The cursor may not be open because the aggregator was never used,    ** or it could be that it was used but there was no GROUP BY clause.    */    if( pAgg->pCurrent ){      freeAggElem(pAgg->pCurrent, pAgg);    }  }  /* If db is not NULL and we have not yet and we have not yet opened  ** the temporary btree then do so and create the table to store aggregate  ** information.  **  ** If db is NULL, then close the temporary btree if it is open.  */  if( db ){    if( !pAgg->pBtree ){      assert( pAgg->nTab==0 );#ifndef SQLITE_OMIT_MEMORYDB      rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree);#else      rc = sqlite3BtreeFactory(db, 0, 0, TEMP_PAGES, &pAgg->pBtree);#endif      if( rc!=SQLITE_OK ) return rc;      sqlite3BtreeBeginTrans(pAgg->pBtree, 1);      rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0);      if( rc!=SQLITE_OK ) return rc;    }    assert( pAgg->nTab!=0 );    rc = sqlite3BtreeCursor(pAgg->pBtree, pAgg->nTab, 1,        sqlite3VdbeRecordCompare, pKeyInfo, &pAgg->pCsr);    if( rc!=SQLITE_OK ) return rc;  }else{    if( pAgg->pBtree ){      sqlite3BtreeClose(pAgg->pBtree);      pAgg->pBtree = 0;      pAgg->nTab = 0;    }    pAgg->pCsr = 0;  }  if( pAgg->apFunc ){     sqliteFree(pAgg->apFunc);    pAgg->apFunc = 0;  }  pAgg->pCurrent = 0;  pAgg->nMem = 0;  pAgg->searching = 0;  return SQLITE_OK;}/*** Delete a keylist*/void sqlite3VdbeKeylistFree(Keylist *p){  while( p ){    Keylist *pNext = p->pNext;    sqliteFree(p);    p = pNext;  }}/*** 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.**

⌨️ 快捷键说明

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