1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Allocate Parse objects off of the stack where appropriate for a substantial

performance increase and a size reduction.

FossilOrigin-Name: ea8affa9e453b201b479162f621b591e7a65a489
This commit is contained in:
drh
2016-10-03 01:21:51 +00:00
parent 1a7df58c1a
commit cb43a937e5
6 changed files with 53 additions and 71 deletions

View File

@@ -518,20 +518,14 @@ static int sqlite3Prepare(
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
Parse *pParse; /* Parsing context */
char *zErrMsg = 0; /* Error message */
int rc = SQLITE_OK; /* Result code */
int i; /* Loop counter */
Parse sParse; /* Parsing context */
/* Allocate the parsing context */
pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
if( pParse==0 ){
rc = SQLITE_NOMEM_BKPT;
goto end_prepare;
}
memset(pParse, 0, PARSE_HDR_SZ);
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
pParse->pReprepare = pReprepare;
memset(&sParse, 0, PARSE_HDR_SZ);
memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
sParse.pReprepare = pReprepare;
assert( ppStmt && *ppStmt==0 );
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
assert( sqlite3_mutex_held(db->mutex) );
@@ -575,8 +569,7 @@ static int sqlite3Prepare(
sqlite3VtabUnlockList(db);
pParse->db = db;
pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */
sParse.db = db;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -589,61 +582,61 @@ static int sqlite3Prepare(
}
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);
pParse->zTail = &zSql[pParse->zTail-zSqlCopy];
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
sqlite3DbFree(db, zSqlCopy);
}else{
pParse->zTail = &zSql[nBytes];
sParse.zTail = &zSql[nBytes];
}
}else{
sqlite3RunParser(pParse, zSql, &zErrMsg);
sqlite3RunParser(&sParse, zSql, &zErrMsg);
}
assert( 0==pParse->nQueryLoop );
assert( 0==sParse.nQueryLoop );
if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
if( pParse->checkSchema ){
schemaIsValid(pParse);
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM_BKPT;
sParse.rc = SQLITE_NOMEM_BKPT;
}
if( pzTail ){
*pzTail = pParse->zTail;
*pzTail = sParse.zTail;
}
rc = pParse->rc;
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"selectid", "order", "from", "detail"
};
int iFirst, mx;
if( pParse->explain==2 ){
sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
if( sParse.explain==2 ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
iFirst = 8;
mx = 12;
}else{
sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
iFirst = 0;
mx = 8;
}
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
azColName[i], SQLITE_STATIC);
}
}
#endif
if( db->init.busy==0 ){
Vdbe *pVdbe = pParse->pVdbe;
sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
Vdbe *pVdbe = sParse.pVdbe;
sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
}
if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(pParse->pVdbe);
if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(sParse.pVdbe);
assert(!(*ppStmt));
}else{
*ppStmt = (sqlite3_stmt*)pParse->pVdbe;
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
}
if( zErrMsg ){
@@ -654,16 +647,15 @@ static int sqlite3Prepare(
}
/* Delete any TriggerPrg structures allocated while parsing this statement. */
while( pParse->pTriggerPrg ){
TriggerPrg *pT = pParse->pTriggerPrg;
pParse->pTriggerPrg = pT->pNext;
while( sParse.pTriggerPrg ){
TriggerPrg *pT = sParse.pTriggerPrg;
sParse.pTriggerPrg = pT->pNext;
sqlite3DbFree(db, pT);
}
end_prepare:
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
sqlite3ParserReset(&sParse);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
return rc;