📄 vdbe.c
字号:
if( x<0 && (-x)<=p->nLabel && p->aOp ){ if( p->aLabel[-1-x]==p->nOp ) return; assert( p->aLabel[-1-x]<0 ); p->aLabel[-1-x] = p->nOp; for(j=0; j<p->nOp; j++){ if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp; } }}/*** Return the address of the next instruction to be inserted.*/int sqliteVdbeCurrentAddr(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); return p->nOp;}/*** Add a whole list of operations to the operation stack. Return the** address of the first operation added.*/int sqliteVdbeAddOpList(Vdbe *p, int nOp, VdbeOp const *aOp){ int addr; assert( p->magic==VDBE_MAGIC_INIT ); if( p->nOp + nOp >= p->nOpAlloc ){ int oldSize = p->nOpAlloc; Op *aNew; p->nOpAlloc = p->nOpAlloc*2 + nOp + 10; aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op)); if( aNew==0 ){ p->nOpAlloc = oldSize; return 0; } p->aOp = aNew; memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op)); } addr = p->nOp; if( nOp>0 ){ int i; for(i=0; i<nOp; i++){ int p2 = aOp[i].p2; p->aOp[i+addr] = aOp[i]; if( p2<0 ) p->aOp[i+addr].p2 = addr + ADDR(p2); p->aOp[i+addr].p3type = aOp[i].p3 ? P3_STATIC : P3_NOTUSED;#ifndef NDEBUG if( sqlite_vdbe_addop_trace ) vdbePrintOp(0, i+addr, &p->aOp[i+addr]);#endif } p->nOp += nOp; } return addr;}/*** Change the value of the P1 operand for a specific instruction.** This routine is useful when a large program is loaded from a** static array using sqliteVdbeAddOpList but we want to make a** few minor changes to the program.*/void sqliteVdbeChangeP1(Vdbe *p, int addr, int val){ assert( p->magic==VDBE_MAGIC_INIT ); if( p && addr>=0 && p->nOp>addr && p->aOp ){ p->aOp[addr].p1 = val; }}/*** Change the value of the P2 operand for a specific instruction.** This routine is useful for setting a jump destination.*/void sqliteVdbeChangeP2(Vdbe *p, int addr, int val){ assert( val>=0 ); assert( p->magic==VDBE_MAGIC_INIT ); if( p && addr>=0 && p->nOp>addr && p->aOp ){ p->aOp[addr].p2 = val; }}/*** Change the value of the P3 operand for a specific instruction.** This routine is useful when a large program is loaded from a** static array using sqliteVdbeAddOpList but we want to make a** few minor changes to the program.**** If n>=0 then the P3 operand is dynamic, meaning that a copy of** the string is made into memory obtained from sqliteMalloc().** A value of n==0 means copy bytes of zP3 up to and including the** first null byte. If n>0 then copy n+1 bytes of zP3.**** If n==P3_STATIC it means that zP3 is a pointer to a constant static** string and we can just copy the pointer. n==P3_POINTER means zP3 is** a pointer to some object other than a string.**** If addr<0 then change P3 on the most recently inserted instruction.*/void sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p==0 || p->aOp==0 ) return; if( addr<0 || addr>=p->nOp ){ addr = p->nOp - 1; if( addr<0 ) return; } pOp = &p->aOp[addr]; if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); pOp->p3 = 0; } if( zP3==0 ){ pOp->p3 = 0; pOp->p3type = P3_NOTUSED; }else if( n<0 ){ pOp->p3 = (char*)zP3; pOp->p3type = n; }else{ sqliteSetNString(&pOp->p3, zP3, n, 0); pOp->p3type = P3_DYNAMIC; }}/*** If the P3 operand to the specified instruction appears** to be a quoted string token, then this procedure removes ** the quotes.**** The quoting operator can be either a grave ascent (ASCII 0x27)** or a double quote character (ASCII 0x22). Two quotes in a row** resolve to be a single actual quote character within the string.*/void sqliteVdbeDequoteP3(Vdbe *p, int addr){ Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p->aOp==0 || addr<0 || addr>=p->nOp ) return; pOp = &p->aOp[addr]; if( pOp->p3==0 || pOp->p3[0]==0 ) return; if( pOp->p3type==P3_POINTER ) return; if( pOp->p3type!=P3_DYNAMIC ){ pOp->p3 = sqliteStrDup(pOp->p3); pOp->p3type = P3_DYNAMIC; } sqliteDequote(pOp->p3);}/*** On the P3 argument of the given instruction, change all** strings of whitespace characters into a single space and** delete leading and trailing whitespace.*/void sqliteVdbeCompressSpace(Vdbe *p, int addr){ char *z; int i, j; Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p->aOp==0 || addr<0 || addr>=p->nOp ) return; pOp = &p->aOp[addr]; if( pOp->p3type==P3_POINTER ){ return; } if( pOp->p3type!=P3_DYNAMIC ){ pOp->p3 = sqliteStrDup(pOp->p3); pOp->p3type = P3_DYNAMIC; } z = pOp->p3; if( z==0 ) return; i = j = 0; while( isspace(z[i]) ){ i++; } while( z[i] ){ if( isspace(z[i]) ){ z[j++] = ' '; while( isspace(z[++i]) ){} }else{ z[j++] = z[i++]; } } while( j>0 && isspace(z[j-1]) ){ j--; } z[j] = 0;}/*** Search for the current program for the given opcode and P2** value. Return the address plus 1 if found and 0 if not found.*/int sqliteVdbeFindOp(Vdbe *p, int op, int p2){ int i; assert( p->magic==VDBE_MAGIC_INIT ); for(i=0; i<p->nOp; i++){ if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1; } return 0;}/*** Return the opcode for a given address.*/VdbeOp *sqliteVdbeGetOp(Vdbe *p, int addr){ assert( p->magic==VDBE_MAGIC_INIT ); assert( addr>=0 && addr<p->nOp ); return &p->aOp[addr];}/*** The following group or routines are employed by installable functions** to return their results.**** The sqlite_set_result_string() routine can be used to return a string** value or to return a NULL. To return a NULL, pass in NULL for zResult.** A copy is made of the string before this routine returns so it is safe** to pass in an ephemeral string.**** sqlite_set_result_error() works like sqlite_set_result_string() except** that it signals a fatal error. The string argument, if any, is the** error message. If the argument is NULL a generic substitute error message** is used.**** The sqlite_set_result_int() and sqlite_set_result_double() set the return** value of the user function to an integer or a double.**** These routines are defined here in vdbe.c because they depend on knowing** the internals of the sqlite_func structure which is only defined in ** this source file.*/char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){ assert( !p->isStep ); if( p->s.flags & STK_Dyn ){ sqliteFree(p->z); } if( zResult==0 ){ p->s.flags = STK_Null; n = 0; p->z = 0; p->s.n = 0; }else{ if( n<0 ) n = strlen(zResult); if( n<NBFS-1 ){ memcpy(p->s.z, zResult, n); p->s.z[n] = 0; p->s.flags = STK_Str; p->z = p->s.z; }else{ p->z = sqliteMallocRaw( n+1 ); if( p->z ){ memcpy(p->z, zResult, n); p->z[n] = 0; } p->s.flags = STK_Str | STK_Dyn; } p->s.n = n+1; } return p->z;}void sqlite_set_result_int(sqlite_func *p, int iResult){ assert( !p->isStep ); if( p->s.flags & STK_Dyn ){ sqliteFree(p->z); } p->s.i = iResult; p->s.flags = STK_Int;}void sqlite_set_result_double(sqlite_func *p, double rResult){ assert( !p->isStep ); if( p->s.flags & STK_Dyn ){ sqliteFree(p->z); } p->s.r = rResult; p->s.flags = STK_Real;}void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){ assert( !p->isStep ); sqlite_set_result_string(p, zMsg, n); p->isError = 1;}/*** Extract the user data from a sqlite_func structure and return a** pointer to it.**** This routine is defined here in vdbe.c because it depends on knowing** the internals of the sqlite_func structure which is only defined in ** this source file.*/void *sqlite_user_data(sqlite_func *p){ assert( p && p->pFunc ); return p->pFunc->pUserData;}/*** Allocate or return the aggregate context for a user function. A new** context is allocated on the first call. Subsequent calls return the** same context that was returned on prior calls.**** This routine is defined here in vdbe.c because it depends on knowing** the internals of the sqlite_func structure which is only defined in** this source file.*/void *sqlite_aggregate_context(sqlite_func *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); if( p->pAgg==0 ){ if( nByte<=NBFS ){ p->pAgg = (void*)p->z; }else{ p->pAgg = sqliteMalloc( nByte ); } } return p->pAgg;}/*** Return the number of times the Step function of a aggregate has been ** called.**** This routine is defined here in vdbe.c because it depends on knowing** the internals of the sqlite_func structure which is only defined in** this source file.*/int sqlite_aggregate_count(sqlite_func *p){ assert( p && p->pFunc && p->pFunc->xStep ); return p->cnt;}/*** Advance the virtual machine to the next output row.**** The return vale will be either SQLITE_BUSY, SQLITE_DONE, ** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE.**** SQLITE_BUSY means that the virtual machine attempted to open** a locked database and there is no busy callback registered.** Call sqlite_step() again to retry the open. *pN is set to 0** and *pazColName and *pazValue are both set to NULL.**** SQLITE_DONE means that the virtual machine has finished** executing. sqlite_step() should not be called again on this** virtual machine. *pN and *pazColName are set appropriately** but *pazValue is set to NULL.**** SQLITE_ROW means that the virtual machine has generated another** row of the result set. *pN is set to the number of columns in** the row. *pazColName is set to the names of the columns followed** by the column datatypes. *pazValue is set to the values of each** column in the row. The value of the i-th column is (*pazValue)[i].** The name of the i-th column is (*pazColName)[i] and the datatype** of the i-th column is (*pazColName)[i+*pN].**** SQLITE_ERROR means that a run-time error (such as a constraint** violation) has occurred. The details of the error will be returned** by the next call to sqlite_finalize(). sqlite_step() should not** be called again on the VM.**** SQLITE_MISUSE means that the this routine was called inappropriately.** Perhaps it was called on a virtual machine that had already been** finalized or on one that had previously returned SQLITE_ERROR or** SQLITE_DONE. Or it could be the case the the same database connection** is being used simulataneously by two or more threads.*/int sqlite_step( sqlite_vm *pVm, /* The virtual machine to execute */ int *pN, /* OUT: Number of columns in result */ const char ***pazValue, /* OUT: Column data */ const char ***pazColName /* OUT: Column names and datatypes */){ Vdbe *p = (Vdbe*)pVm; sqlite *db; int rc; if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } db = p->db; if( sqliteSafetyOn(db) ){ return SQLITE_MISUSE; } if( p->explain ){ rc = sqliteVdbeList(p); }else{ rc = sqliteVdbeExec(p); } if( rc==SQLITE_DONE || rc==SQLITE_ROW ){ if( pazColName ) *pazColName = (const char**)p->azColName; if( pN ) *pN = p->nResColumn; }else{ if( pazColName) *pazColName = 0; if( pN ) *pN = 0; } if( pazValue ){ if( rc==SQLITE_ROW ){ *pazValue = (const char**)p->azResColumn; }else{ *pazValue = 0; } } if( sqliteSafetyOff(db) ){ return SQLITE_MISUSE; } return rc;}/*** 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.*/static void AggReset(Agg *pAgg){ int i; HashElem *p; for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){ AggElem *pElem = sqliteHashData(p); assert( pAgg->apFunc!=0 ); for(i=0; i<pAgg->nMem; i++){ Mem *pMem = &pElem->aMem[i]; if( pAgg->apFunc[i] && (pMem->s.flags & STK_AggCtx)!=0 ){ sqlite_func ctx; ctx.pFunc = pAgg->apFunc[i]; ctx.s.flags = STK_Null; ctx.z = 0; ctx.pAgg = pMem->z; ctx.cnt = pMem->s.i; ctx.isStep = 0; ctx.isError = 0; (*pAgg->apFunc[i]->xFinalize)(&ctx); if( pMem->z!=0 && pMem->z!=pMem->s.z ){ sqliteFree(pMem->z); } }else if( pMem->s.flags & STK_Dyn ){ sqliteFree(pMem->z); } } sqliteFree(pElem); } sqliteHashClear(&pAgg->hash);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -