📄 vdbeaux.c
字号:
case P4_DYNAMIC: case P4_KEYINFO: case P4_KEYINFO_HANDOFF: { sqlite3_free(p3); break; } case P4_VDBEFUNC: { VdbeFunc *pVdbeFunc = (VdbeFunc *)p3; freeEphemeralFunction(pVdbeFunc->pFunc); sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); sqlite3_free(pVdbeFunc); break; } case P4_FUNCDEF: { freeEphemeralFunction((FuncDef*)p3); break; } case P4_MEM: { sqlite3ValueFree((sqlite3_value*)p3); 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]; while( N-- ){ freeP4(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; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); if( p->aOp==0 || p->db->mallocFailed ){ if (n != P4_KEYINFO) { freeP4(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(pOp->p4type, pOp->p4.p); pOp->p4.p = 0; if( n==P4_INT32 ){ pOp->p4.i = (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 = sqlite3_malloc( nByte ); pOp->p4.pKeyInfo = pKeyInfo; if( pKeyInfo ){ memcpy(pKeyInfo, zP4, nByte); /* In the current implementation, P4_KEYINFO is only ever used on ** KeyInfo structures that have no aSortOrder component. Elements ** with an aSortOrder always use P4_KEYINFO_HANDOFF. So we do not ** need to bother with duplicating the aSortOrder. */ assert( pKeyInfo->aSortOrder==0 );#if 0 aSortOrder = pKeyInfo->aSortOrder; if( aSortOrder ){ pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField]; memcpy(pKeyInfo->aSortOrder, aSortOrder, nField); }#endif 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.*/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); sqlite3_free(*pz); *pz = sqlite3VMPrintf(p->db, zFormat, ap); 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) || 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: { 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 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 ){ while( N-->0 ){ assert( N<2 || p[0].db==p[1].db ); sqlite3VdbeMemSetNull(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".**** 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, sqlite3ErrStr(p->rc), (char*)0); }else{ 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++; } pMem->flags = MEM_Ephem|MEM_Str|MEM_Term; /* P4 */ pMem->z = displayP4(pOp, pMem->zShort, sizeof(pMem->zShort)); assert( pMem->z!=0 ); pMem->n = strlen(pMem->z); pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; pMem++; if( p->explain==1 ){ pMem->flags = MEM_Str|MEM_Term|MEM_Short; pMem->n = sprintf(pMem->zShort, "%.2x", pOp->p5); /* P5 */ pMem->z = pMem->zShort; pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; pMem++; pMem->flags = MEM_Null; /* Comment */#ifdef SQLITE_DEBUG if( pOp->zComment ){ pMem->flags = MEM_Str|MEM_Term; pMem->z = pOp->zComment; pMem->n = strlen(pMem->z); pMem->enc = SQLITE_UTF8; }#endif } p->nResColumn = 8 - 5*(p->explain-1); p->rc = SQLITE_OK; rc = SQLITE_ROW; } return rc;}#endif /* SQLITE_OMIT_EXPLAIN */#ifdef SQLITE_DEBUG/*** Print the SQL that was used to generate a VDBE program.*/void sqlite3VdbePrintSql(Vdbe *p){ int nOp = p->nOp; VdbeOp *pOp; if( nOp<1 ) return; pOp = &p->aOp[0]; if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ const char *z = pOp->p4.z; while( isspace(*(u8*)z) ) z++; printf("SQL: [%s]\n", z); }}#endif#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)/*** Print an IOTRACE message showing SQL content.*/void sqlite3VdbeIOTraceSql(Vdbe *p){ int nOp = p->nOp; VdbeOp *pOp; if( sqlite3_io_trace==0 ) return; if( nOp<1 ) return; pOp = &p->aOp[0]; if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ int i, j; char z[1000]; sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z); for(i=0; isspace((unsigned char)z[i]); i++){} for(j=0; z[i]; i++){ if( isspace((unsigned char)z[i]) ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -