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

📄 vdbeaux.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      case P4_REAL:      case P4_INT64:      case P4_MPRINTF:      case P4_DYNAMIC:      case P4_KEYINFO:      case P4_INTARRAY:      case P4_KEYINFO_HANDOFF: {        sqlite3DbFree(db, p4);        break;      }      case P4_VDBEFUNC: {        VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;        freeEphemeralFunction(db, pVdbeFunc->pFunc);        sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);        sqlite3DbFree(db, pVdbeFunc);        break;      }      case P4_FUNCDEF: {        freeEphemeralFunction(db, (FuncDef*)p4);        break;      }      case P4_MEM: {        sqlite3ValueFree((sqlite3_value*)p4);        break;      }    }  }}/*** Change N opcodes starting at addr to No-ops.*/void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){  if( p && p->aOp ){    VdbeOp *pOp = &p->aOp[addr];    sqlite3 *db = p->db;    while( N-- ){      freeP4(db, pOp->p4type, pOp->p4.p);      memset(pOp, 0, sizeof(pOp[0]));      pOp->opcode = OP_Noop;      pOp++;    }  }}/*** Change the value of the P4 operand for a specific instruction.** This routine is useful when a large program is loaded from a** static array using sqlite3VdbeAddOpList but we want to make a** few minor changes to the program.**** If n>=0 then the P4 operand is dynamic, meaning that a copy of** the string is made into memory obtained from sqlite3_malloc().** A value of n==0 means copy bytes of zP4 up to and including the** first null byte.  If n>0 then copy n+1 bytes of zP4.**** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure.** A copy is made of the KeyInfo structure into memory obtained from** sqlite3_malloc, to be freed when the Vdbe is finalized.** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure** stored in memory that the caller has obtained from sqlite3_malloc. The ** caller should not free the allocation, it will be freed when the Vdbe is** finalized.** ** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points** to a string or structure that is guaranteed to exist for the lifetime of** the Vdbe. In these cases we can just copy the pointer.**** If addr<0 then change P4 on the most recently inserted instruction.*/void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){  Op *pOp;  sqlite3 *db;  assert( p!=0 );  db = p->db;  assert( p->magic==VDBE_MAGIC_INIT );  if( p->aOp==0 || db->mallocFailed ){    if (n != P4_KEYINFO) {      freeP4(db, n, (void*)*(char**)&zP4);    }    return;  }  assert( addr<p->nOp );  if( addr<0 ){    addr = p->nOp - 1;    if( addr<0 ) return;  }  pOp = &p->aOp[addr];  freeP4(db, pOp->p4type, pOp->p4.p);  pOp->p4.p = 0;  if( n==P4_INT32 ){    /* Note: this cast is safe, because the origin data point was an int    ** that was cast to a (const char *). */    pOp->p4.i = SQLITE_PTR_TO_INT(zP4);    pOp->p4type = n;  }else if( zP4==0 ){    pOp->p4.p = 0;    pOp->p4type = P4_NOTUSED;  }else if( n==P4_KEYINFO ){    KeyInfo *pKeyInfo;    int nField, nByte;    nField = ((KeyInfo*)zP4)->nField;    nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;    pKeyInfo = sqlite3Malloc( nByte );    pOp->p4.pKeyInfo = pKeyInfo;    if( pKeyInfo ){      u8 *aSortOrder;      memcpy(pKeyInfo, zP4, nByte);      aSortOrder = pKeyInfo->aSortOrder;      if( aSortOrder ){        pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];        memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);      }      pOp->p4type = P4_KEYINFO;    }else{      p->db->mallocFailed = 1;      pOp->p4type = P4_NOTUSED;    }  }else if( n==P4_KEYINFO_HANDOFF ){    pOp->p4.p = (void*)zP4;    pOp->p4type = P4_KEYINFO;  }else if( n<0 ){    pOp->p4.p = (void*)zP4;    pOp->p4type = n;  }else{    if( n==0 ) n = strlen(zP4);    pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);    pOp->p4type = P4_DYNAMIC;  }}#ifndef NDEBUG/*** Change the comment on the the most recently coded instruction.  Or** insert a No-op and add the comment to that new instruction.  This** makes the code easier to read during debugging.  None of this happens** in a production build.*/void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){  va_list ap;  assert( p->nOp>0 || p->aOp==0 );  assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );  if( p->nOp ){    char **pz = &p->aOp[p->nOp-1].zComment;    va_start(ap, zFormat);    sqlite3DbFree(p->db, *pz);    *pz = sqlite3VMPrintf(p->db, zFormat, ap);    va_end(ap);  }}void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){  va_list ap;  sqlite3VdbeAddOp0(p, OP_Noop);  assert( p->nOp>0 || p->aOp==0 );  assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );  if( p->nOp ){    char **pz = &p->aOp[p->nOp-1].zComment;    va_start(ap, zFormat);    sqlite3DbFree(p->db, *pz);    *pz = sqlite3VMPrintf(p->db, zFormat, ap);    va_end(ap);  }}#endif  /* NDEBUG *//*** 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) || p->db->mallocFailed );  return ((addr>=0 && addr<p->nOp)?(&p->aOp[addr]):0);}#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)/*** Compute a string that describes the P4 parameter for an opcode.** Use zTemp for any required temporary buffer space.*/static char *displayP4(Op *pOp, char *zTemp, int nTemp){  char *zP4 = zTemp;  assert( nTemp>=20 );  switch( pOp->p4type ){    case P4_KEYINFO_STATIC:    case P4_KEYINFO: {      int i, j;      KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;      sqlite3_snprintf(nTemp, 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 ){            memcpy(&zTemp[i],",...",4);            break;          }          zTemp[i++] = ',';          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){            zTemp[i++] = '-';          }          memcpy(&zTemp[i], pColl->zName,n+1);          i += n;        }else if( i+4<nTemp-6 ){          memcpy(&zTemp[i],",nil",4);          i += 4;        }      }      zTemp[i++] = ')';      zTemp[i] = 0;      assert( i<nTemp );      break;    }    case P4_COLLSEQ: {      CollSeq *pColl = pOp->p4.pColl;      sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName);      break;    }    case P4_FUNCDEF: {      FuncDef *pDef = pOp->p4.pFunc;      sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);      break;    }    case P4_INT64: {      sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64);      break;    }    case P4_INT32: {      sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i);      break;    }    case P4_REAL: {      sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal);      break;    }    case P4_MEM: {      Mem *pMem = pOp->p4.pMem;      assert( (pMem->flags & MEM_Null)==0 );      if( pMem->flags & MEM_Str ){        zP4 = pMem->z;      }else if( pMem->flags & MEM_Int ){        sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);      }else if( pMem->flags & MEM_Real ){        sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);      }      break;    }#ifndef SQLITE_OMIT_VIRTUALTABLE    case P4_VTAB: {      sqlite3_vtab *pVtab = pOp->p4.pVtab;      sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);      break;    }#endif    case P4_INTARRAY: {      sqlite3_snprintf(nTemp, zTemp, "intarray");      break;    }    default: {      zP4 = pOp->p4.z;      if( zP4==0 ){        zP4 = zTemp;        zTemp[0] = 0;      }    }  }  assert( zP4!=0 );  return zP4;}#endif/*** Declare to the Vdbe that the BTree object at db->aDb[i] is used.***/void sqlite3VdbeUsesBtree(Vdbe *p, int i){  int mask;  assert( i>=0 && i<p->db->nDb );  assert( i<sizeof(p->btreeMask)*8 );  mask = 1<<i;  if( (p->btreeMask & mask)==0 ){    p->btreeMask |= mask;    sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt);  }}#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 *zP4;  char zPtr[50];  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";  if( pOut==0 ) pOut = stdout;  zP4 = displayP4(pOp, zPtr, sizeof(zPtr));  fprintf(pOut, zFormat1, pc,       sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,#ifdef SQLITE_DEBUG      pOp->zComment ? pOp->zComment : ""#else      ""#endif  );  fflush(pOut);}#endif/*** Release an array of N Mem elements*/static void releaseMemArray(Mem *p, int N){  if( p && N ){    sqlite3 *db = p->db;    int malloc_failed = db->mallocFailed;    while( N-->0 ){      assert( N<2 || p[0].db==p[1].db );      sqlite3VdbeMemRelease(p);      p->flags = MEM_Null;      p++;    }    db->mallocFailed = malloc_failed;  }}#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENTint sqlite3VdbeReleaseBuffers(Vdbe *p){  int ii;  int nFree = 0;  assert( sqlite3_mutex_held(p->db->mutex) );  for(ii=1; ii<=p->nMem; ii++){    Mem *pMem = &p->aMem[ii];    if( pMem->z && pMem->flags&MEM_Dyn ){      assert( !pMem->xDel );      nFree += sqlite3DbMallocSize(pMem->db, pMem->z);      sqlite3VdbeMemRelease(pMem);    }  }  return nFree;}#endif#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".**** When p->explain==1, each instruction is listed.  When** p->explain==2, only OP_Explain instructions are listed and these** are shown in a different format.  p->explain==2 is used to implement** EXPLAIN QUERY PLAN.*/int sqlite3VdbeList(  Vdbe *p                   /* The VDBE */){  sqlite3 *db = p->db;  int i;  int rc = SQLITE_OK;  Mem *pMem = p->pResultSet = &p->aMem[1];  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 use dynamic strings for  ** the result, result columns may become dynamic if the user calls  ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.  */  releaseMemArray(pMem, p->nMem);  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->u1.isInterrupted ){    p->rc = SQLITE_INTERRUPT;    rc = SQLITE_ERROR;    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc));  }else{    char *z;    Op *pOp = &p->aOp[i];    if( p->explain==1 ){      pMem->flags = MEM_Int;      pMem->type = SQLITE_INTEGER;      pMem->u.i = i;                                /* Program counter */      pMem++;        pMem->flags = MEM_Static|MEM_Str|MEM_Term;      pMem->z = (char*)sqlite3OpcodeName(pOp->opcode);  /* Opcode */      assert( pMem->z!=0 );      pMem->n = strlen(pMem->z);      pMem->type = SQLITE_TEXT;      pMem->enc = SQLITE_UTF8;      pMem++;    }    pMem->flags = MEM_Int;    pMem->u.i = pOp->p1;                          /* P1 */    pMem->type = SQLITE_INTEGER;    pMem++;    pMem->flags = MEM_Int;    pMem->u.i = pOp->p2;                          /* P2 */    pMem->type = SQLITE_INTEGER;    pMem++;    if( p->explain==1 ){      pMem->flags = MEM_Int;      pMem->u.i = pOp->p3;                          /* P3 */      pMem->type = SQLITE_INTEGER;      pMem++;    }    if( sqlite3VdbeMemGrow(pMem, 32, 0) ){            /* P4 */      p->db->mallocFailed = 1;      return SQLITE_NOMEM;    }    pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;    z = displayP4(pOp, pMem->z, 32);    if( z!=pMem->z ){      sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);    }else{      assert( pMem->z!=0 );      pMem->n = strlen(pMem->z);      pMem->enc = SQLITE_UTF8;    }    pMem->type = SQLITE_TEXT;    pMem++;    if( p->explain==1 ){      if( sqlite3VdbeMemGrow(pMem, 4, 0) ){        p->db->mallocFailed = 1;        return SQLITE_NOMEM;      }      pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;      pMem->n = 2;

⌨️ 快捷键说明

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