mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Implement the "lookaside" memory allocation cache. Use of this cache makes
the speed1.test script run about 15% faster. Added new interfaces to control the cache. (CVS 5488) FossilOrigin-Name: e48f9697e9fea339e150ddc32940760027dd07d9
This commit is contained in:
117
src/select.c
117
src/select.c
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.459 2008/07/24 15:50:41 drh Exp $
|
||||
** $Id: select.c,v 1.460 2008/07/28 19:34:53 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -21,16 +21,16 @@
|
||||
** Delete all the content of a Select structure but do not deallocate
|
||||
** the select structure itself.
|
||||
*/
|
||||
static void clearSelect(Select *p){
|
||||
sqlite3ExprListDelete(p->pEList);
|
||||
sqlite3SrcListDelete(p->pSrc);
|
||||
sqlite3ExprDelete(p->pWhere);
|
||||
sqlite3ExprListDelete(p->pGroupBy);
|
||||
sqlite3ExprDelete(p->pHaving);
|
||||
sqlite3ExprListDelete(p->pOrderBy);
|
||||
sqlite3SelectDelete(p->pPrior);
|
||||
sqlite3ExprDelete(p->pLimit);
|
||||
sqlite3ExprDelete(p->pOffset);
|
||||
static void clearSelect(sqlite3 *db, Select *p){
|
||||
sqlite3ExprListDelete(db, p->pEList);
|
||||
sqlite3SrcListDelete(db, p->pSrc);
|
||||
sqlite3ExprDelete(db, p->pWhere);
|
||||
sqlite3ExprListDelete(db, p->pGroupBy);
|
||||
sqlite3ExprDelete(db, p->pHaving);
|
||||
sqlite3ExprListDelete(db, p->pOrderBy);
|
||||
sqlite3SelectDelete(db, p->pPrior);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pOffset);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -88,7 +88,7 @@ Select *sqlite3SelectNew(
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
pNew->addrOpenEphm[2] = -1;
|
||||
if( pNew==&standin) {
|
||||
clearSelect(pNew);
|
||||
clearSelect(db, pNew);
|
||||
pNew = 0;
|
||||
}
|
||||
return pNew;
|
||||
@@ -97,10 +97,10 @@ Select *sqlite3SelectNew(
|
||||
/*
|
||||
** Delete the given Select structure and all of its substructures.
|
||||
*/
|
||||
void sqlite3SelectDelete(Select *p){
|
||||
void sqlite3SelectDelete(sqlite3 *db, Select *p){
|
||||
if( p ){
|
||||
clearSelect(p);
|
||||
sqlite3_free(p);
|
||||
clearSelect(db, p);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,6 +1163,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
if( pTab==0 ){
|
||||
return 0;
|
||||
}
|
||||
pTab->db = db;
|
||||
pTab->nRef = 1;
|
||||
pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
|
||||
pEList = pSelect->pEList;
|
||||
@@ -1196,7 +1197,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
zName = sqlite3MPrintf(db, "%T", &p->span);
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
sqlite3_free(zName);
|
||||
sqlite3DbFree(db, zName);
|
||||
break;
|
||||
}
|
||||
sqlite3Dequote(zName);
|
||||
@@ -1207,8 +1208,11 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
nName = strlen(zName);
|
||||
for(j=cnt=0; j<i; j++){
|
||||
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
|
||||
char *zNewName;
|
||||
zName[nName] = 0;
|
||||
zName = sqlite3MPrintf(db, "%z:%d", zName, ++cnt);
|
||||
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
|
||||
sqlite3DbFree(db, zName);
|
||||
zName = zNewName;
|
||||
j = -1;
|
||||
if( zName==0 ) break;
|
||||
}
|
||||
@@ -1474,10 +1478,10 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
||||
}
|
||||
rc = 1;
|
||||
}
|
||||
sqlite3_free(zTName);
|
||||
sqlite3DbFree(db, zTName);
|
||||
}
|
||||
}
|
||||
sqlite3ExprListDelete(pEList);
|
||||
sqlite3ExprListDelete(db, pEList);
|
||||
p->pEList = pNew;
|
||||
}
|
||||
#if SQLITE_MAX_COLUMN
|
||||
@@ -1538,11 +1542,11 @@ static int matchOrderByTermToExprList(
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
char *zAs = pEList->a[i].zName;
|
||||
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
||||
sqlite3_free(zCol);
|
||||
sqlite3DbFree(db, zCol);
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zCol);
|
||||
sqlite3DbFree(db, zCol);
|
||||
}
|
||||
|
||||
/* Resolve all names in the ORDER BY term expression
|
||||
@@ -1631,7 +1635,7 @@ static int processOrderGroupBy(
|
||||
if( iCol>0 ){
|
||||
CollSeq *pColl = pE->pColl;
|
||||
int flags = pE->flags & EP_ExpCollate;
|
||||
sqlite3ExprDelete(pE);
|
||||
sqlite3ExprDelete(db, pE);
|
||||
pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
|
||||
pOrderBy->a[i].pExpr = pE;
|
||||
if( pE && pColl && flags ){
|
||||
@@ -1702,7 +1706,7 @@ static int processCompoundOrderBy(
|
||||
assert(pDup);
|
||||
iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
|
||||
}
|
||||
sqlite3ExprDelete(pDup);
|
||||
sqlite3ExprDelete(db, pDup);
|
||||
if( iCol<0 ){
|
||||
return 1;
|
||||
}
|
||||
@@ -1882,6 +1886,7 @@ static int multiSelect(
|
||||
Vdbe *v; /* Generate code to this VDBE */
|
||||
SelectDest dest; /* Alternative data destination */
|
||||
Select *pDelete = 0; /* Chain of simple selects to delete */
|
||||
sqlite3 *db; /* Database connection */
|
||||
|
||||
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
|
||||
** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
|
||||
@@ -1890,6 +1895,7 @@ static int multiSelect(
|
||||
rc = 1;
|
||||
goto multi_select_end;
|
||||
}
|
||||
db = pParse->db;
|
||||
pPrior = p->pPrior;
|
||||
assert( pPrior->pRightmost!=pPrior );
|
||||
assert( pPrior->pRightmost==p->pRightmost );
|
||||
@@ -2026,11 +2032,11 @@ static int multiSelect(
|
||||
rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0);
|
||||
/* Query flattening in sqlite3Select() might refill p->pOrderBy.
|
||||
** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
|
||||
sqlite3ExprListDelete(p->pOrderBy);
|
||||
sqlite3ExprListDelete(db, p->pOrderBy);
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
p->pOrderBy = 0;
|
||||
sqlite3ExprDelete(p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
p->pOffset = pOffset;
|
||||
p->iLimit = 0;
|
||||
@@ -2109,7 +2115,7 @@ static int multiSelect(
|
||||
rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0);
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
sqlite3ExprDelete(p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
p->pOffset = pOffset;
|
||||
if( rc ){
|
||||
@@ -2162,20 +2168,20 @@ static int multiSelect(
|
||||
|
||||
assert( p->pRightmost==p );
|
||||
nCol = p->pEList->nExpr;
|
||||
pKeyInfo = sqlite3DbMallocZero(pParse->db,
|
||||
pKeyInfo = sqlite3DbMallocZero(db,
|
||||
sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
|
||||
if( !pKeyInfo ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto multi_select_end;
|
||||
}
|
||||
|
||||
pKeyInfo->enc = ENC(pParse->db);
|
||||
pKeyInfo->enc = ENC(db);
|
||||
pKeyInfo->nField = nCol;
|
||||
|
||||
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
|
||||
*apColl = multiSelectCollSeq(pParse, p, i);
|
||||
if( 0==*apColl ){
|
||||
*apColl = pParse->db->pDfltColl;
|
||||
*apColl = db->pDfltColl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2193,13 +2199,13 @@ static int multiSelect(
|
||||
pLoop->addrOpenEphm[i] = -1;
|
||||
}
|
||||
}
|
||||
sqlite3_free(pKeyInfo);
|
||||
sqlite3DbFree(db, pKeyInfo);
|
||||
}
|
||||
|
||||
multi_select_end:
|
||||
pDest->iMem = dest.iMem;
|
||||
pDest->nMem = dest.nMem;
|
||||
sqlite3SelectDelete(pDelete);
|
||||
sqlite3SelectDelete(db, pDelete);
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
|
||||
@@ -2622,9 +2628,9 @@ static int multiSelectOrderBy(
|
||||
}else{
|
||||
regLimitA = regLimitB = 0;
|
||||
}
|
||||
sqlite3ExprDelete(p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
p->pLimit = 0;
|
||||
sqlite3ExprDelete(p->pOffset);
|
||||
sqlite3ExprDelete(db, p->pOffset);
|
||||
p->pOffset = 0;
|
||||
|
||||
regAddrA = ++pParse->nMem;
|
||||
@@ -2786,7 +2792,7 @@ static int multiSelectOrderBy(
|
||||
/* Reassembly the compound query so that it will be freed correctly
|
||||
** by the calling function */
|
||||
if( p->pPrior ){
|
||||
sqlite3SelectDelete(p->pPrior);
|
||||
sqlite3SelectDelete(db, p->pPrior);
|
||||
}
|
||||
p->pPrior = pPrior;
|
||||
|
||||
@@ -3155,9 +3161,9 @@ static int flattenSubquery(
|
||||
nSubSrc = pSubSrc->nSrc;
|
||||
jointype = pSubitem->jointype;
|
||||
sqlite3DeleteTable(pSubitem->pTab);
|
||||
sqlite3_free(pSubitem->zDatabase);
|
||||
sqlite3_free(pSubitem->zName);
|
||||
sqlite3_free(pSubitem->zAlias);
|
||||
sqlite3DbFree(db, pSubitem->zDatabase);
|
||||
sqlite3DbFree(db, pSubitem->zName);
|
||||
sqlite3DbFree(db, pSubitem->zAlias);
|
||||
pSubitem->pTab = 0;
|
||||
pSubitem->zDatabase = 0;
|
||||
pSubitem->zName = 0;
|
||||
@@ -3254,7 +3260,7 @@ static int flattenSubquery(
|
||||
/* Finially, delete what is left of the subquery and return
|
||||
** success.
|
||||
*/
|
||||
sqlite3SelectDelete(pSub1);
|
||||
sqlite3SelectDelete(db, pSub1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -3525,33 +3531,6 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
pAggInfo->directMode = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** This function is used when a SELECT statement is used to create a
|
||||
** temporary table for iterating through when running an INSTEAD OF
|
||||
** UPDATE or INSTEAD OF DELETE trigger.
|
||||
**
|
||||
** If possible, the SELECT statement is modified so that NULL values
|
||||
** are stored in the temporary table for all columns for which the
|
||||
** corresponding bit in argument mask is not set. If mask takes the
|
||||
** special value 0xffffffff, then all columns are populated.
|
||||
*/
|
||||
void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){
|
||||
if( p && !p->pPrior && !p->isDistinct && mask!=0xffffffff ){
|
||||
ExprList *pEList;
|
||||
int i;
|
||||
sqlite3SelectResolve(pParse, p, 0);
|
||||
pEList = p->pEList;
|
||||
for(i=0; pEList && i<pEList->nExpr && i<32; i++){
|
||||
if( !(mask&((u32)1<<i)) ){
|
||||
sqlite3ExprDelete(pEList->a[i].pExpr);
|
||||
pEList->a[i].pExpr = sqlite3Expr(pParse->db, TK_NULL, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Generate code for the given SELECT statement.
|
||||
**
|
||||
@@ -4144,7 +4123,7 @@ int sqlite3Select(
|
||||
resetAccumulator(pParse, &sAggInfo);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
|
||||
if( pWInfo==0 ){
|
||||
sqlite3ExprListDelete(pDel);
|
||||
sqlite3ExprListDelete(db, pDel);
|
||||
goto select_end;
|
||||
}
|
||||
updateAccumulator(pParse, &sAggInfo);
|
||||
@@ -4161,7 +4140,7 @@ int sqlite3Select(
|
||||
selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,
|
||||
pDest, addrEnd, addrEnd);
|
||||
|
||||
sqlite3ExprListDelete(pDel);
|
||||
sqlite3ExprListDelete(db, pDel);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, addrEnd);
|
||||
|
||||
@@ -4208,8 +4187,8 @@ select_end:
|
||||
generateColumnNames(pParse, pTabList, pEList);
|
||||
}
|
||||
|
||||
sqlite3_free(sAggInfo.aCol);
|
||||
sqlite3_free(sAggInfo.aFunc);
|
||||
sqlite3DbFree(db, sAggInfo.aCol);
|
||||
sqlite3DbFree(db, sAggInfo.aFunc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user