mirror of
https://github.com/sqlite/sqlite.git
synced 2025-12-04 20:02:48 +03:00
Change the OP_Trace opcode to OP_Init and give it the ability to jump to the
initialization code at the bottom of the program, thus avoiding the need for an extra OP_Goto. FossilOrigin-Name: 192dea97316144f15f6dd0eabff08a0bf9ef203e
This commit is contained in:
81
src/build.c
81
src/build.c
@@ -149,10 +149,11 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
** transaction on each used database and to verify the schema cookie
|
||||
** on each used database.
|
||||
*/
|
||||
if( pParse->cookieGoto>0 ){
|
||||
if( db->mallocFailed==0 && pParse->cookieMask ){
|
||||
yDbMask mask;
|
||||
int iDb, i, addr;
|
||||
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
|
||||
int iDb, i;
|
||||
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
|
||||
sqlite3VdbeJumpHere(v, 0);
|
||||
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
|
||||
if( (mask & pParse->cookieMask)==0 ) continue;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
@@ -184,17 +185,16 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
sqlite3AutoincrementBegin(pParse);
|
||||
|
||||
/* Code constant expressions that where factored out of inner loops */
|
||||
addr = pParse->cookieGoto;
|
||||
if( pParse->pConstExpr ){
|
||||
ExprList *pEL = pParse->pConstExpr;
|
||||
pParse->cookieGoto = 0;
|
||||
pParse->okConstFactor = 0;
|
||||
for(i=0; i<pEL->nExpr; i++){
|
||||
sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, jump back to the beginning of the executable code. */
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,6 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
pParse->nSet = 0;
|
||||
pParse->nVar = 0;
|
||||
pParse->cookieMask = 0;
|
||||
pParse->cookieGoto = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3826,59 +3825,29 @@ int sqlite3OpenTempDatabase(Parse *pParse){
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate VDBE code that will verify the schema cookie and start
|
||||
** a read-transaction for all named database files.
|
||||
**
|
||||
** It is important that all schema cookies be verified and all
|
||||
** read transactions be started before anything else happens in
|
||||
** the VDBE program. But this routine can be called after much other
|
||||
** code has been generated. So here is what we do:
|
||||
**
|
||||
** The first time this routine is called, we code an OP_Goto that
|
||||
** will jump to a subroutine at the end of the program. Then we
|
||||
** record every database that needs its schema verified in the
|
||||
** pParse->cookieMask field. Later, after all other code has been
|
||||
** generated, the subroutine that does the cookie verifications and
|
||||
** starts the transactions will be coded and the OP_Goto P2 value
|
||||
** will be made to point to that subroutine. The generation of the
|
||||
** cookie verification subroutine code happens in sqlite3FinishCoding().
|
||||
**
|
||||
** If iDb<0 then code the OP_Goto only - don't set flag to verify the
|
||||
** schema on any databases. This can be used to position the OP_Goto
|
||||
** early in the code, before we know if any database tables will be used.
|
||||
** Record the fact that the schema cookie will need to be verified
|
||||
** for database iDb. The code to actually verify the schema cookie
|
||||
** will occur at the end of the top-level VDBE and will be generated
|
||||
** later, by sqlite3FinishCoding().
|
||||
*/
|
||||
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
sqlite3 *db = pToplevel->db;
|
||||
yDbMask mask;
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
if( pToplevel!=pParse ){
|
||||
/* This branch is taken if a trigger is currently being coded. In this
|
||||
** case, set cookieGoto to a non-zero value to show that this function
|
||||
** has been called. This is used by the sqlite3ExprCodeConstants()
|
||||
** function. */
|
||||
pParse->cookieGoto = -1;
|
||||
}
|
||||
#endif
|
||||
if( pToplevel->cookieGoto==0 ){
|
||||
Vdbe *v = sqlite3GetVdbe(pToplevel);
|
||||
if( v==0 ) return; /* This only happens if there was a prior error */
|
||||
pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
|
||||
}
|
||||
if( iDb>=0 ){
|
||||
sqlite3 *db = pToplevel->db;
|
||||
yDbMask mask;
|
||||
|
||||
assert( iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
|
||||
assert( iDb<SQLITE_MAX_ATTACHED+2 );
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
mask = ((yDbMask)1)<<iDb;
|
||||
if( (pToplevel->cookieMask & mask)==0 ){
|
||||
pToplevel->cookieMask |= mask;
|
||||
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
sqlite3OpenTempDatabase(pToplevel);
|
||||
}
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
|
||||
assert( iDb<SQLITE_MAX_ATTACHED+2 );
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
mask = ((yDbMask)1)<<iDb;
|
||||
if( (pToplevel->cookieMask & mask)==0 ){
|
||||
pToplevel->cookieMask |= mask;
|
||||
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
sqlite3OpenTempDatabase(pToplevel);
|
||||
}
|
||||
if( pToplevel==pParse && OptimizationEnabled(db,SQLITE_FactorOutConst) ){
|
||||
pParse->okConstFactor = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user