📄 vdbeaux.c
字号:
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 + -