mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-16 23:02:26 +03:00
Changes to reduce the heap space consumed by triggers, views and tables in the in-memory representation of the schema. Also to reduce the space used by prepared statements slightly. (CVS 6305)
FossilOrigin-Name: d9f6ffbc5ea090ba0daac571fc9a6c68b9c864e4
This commit is contained in:
65
src/where.c
65
src/where.c
@@ -16,7 +16,7 @@
|
||||
** so is applicable. Because this module is responsible for selecting
|
||||
** indices, you might also think of this module as the "query optimizer".
|
||||
**
|
||||
** $Id: where.c,v 1.368 2009/02/04 03:59:25 shane Exp $
|
||||
** $Id: where.c,v 1.369 2009/02/19 14:39:25 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -431,8 +431,11 @@ static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){
|
||||
}
|
||||
mask = exprTableUsage(pMaskSet, p->pRight);
|
||||
mask |= exprTableUsage(pMaskSet, p->pLeft);
|
||||
mask |= exprListTableUsage(pMaskSet, p->pList);
|
||||
mask |= exprSelectTableUsage(pMaskSet, p->pSelect);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect);
|
||||
}else{
|
||||
mask |= exprListTableUsage(pMaskSet, p->x.pList);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
|
||||
@@ -634,7 +637,7 @@ static int isLikeOrGlob(
|
||||
#ifdef SQLITE_EBCDIC
|
||||
if( *pnoCase ) return 0;
|
||||
#endif
|
||||
pList = pExpr->pList;
|
||||
pList = pExpr->x.pList;
|
||||
pRight = pList->a[0].pExpr;
|
||||
if( pRight->op!=TK_STRING ){
|
||||
return 0;
|
||||
@@ -689,7 +692,7 @@ static int isMatchOfColumn(
|
||||
sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){
|
||||
return 0;
|
||||
}
|
||||
pList = pExpr->pList;
|
||||
pList = pExpr->x.pList;
|
||||
if( pList->nExpr!=2 ){
|
||||
return 0;
|
||||
}
|
||||
@@ -953,17 +956,18 @@ static void exprAnalyzeOrTerm(
|
||||
assert( pOrTerm->eOperator==WO_EQ );
|
||||
assert( pOrTerm->leftCursor==iCursor );
|
||||
assert( pOrTerm->u.leftColumn==iColumn );
|
||||
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight);
|
||||
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
|
||||
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
|
||||
pLeft = pOrTerm->pExpr->pLeft;
|
||||
}
|
||||
assert( pLeft!=0 );
|
||||
pDup = sqlite3ExprDup(db, pLeft);
|
||||
pDup = sqlite3ExprDup(db, pLeft, 0);
|
||||
pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0);
|
||||
if( pNew ){
|
||||
int idxNew;
|
||||
transferJoinMarkings(pNew, pExpr);
|
||||
pNew->pList = pList;
|
||||
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
||||
pNew->x.pList = pList;
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
@@ -1026,8 +1030,11 @@ static void exprAnalyze(
|
||||
op = pExpr->op;
|
||||
if( op==TK_IN ){
|
||||
assert( pExpr->pRight==0 );
|
||||
pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)
|
||||
| exprSelectTableUsage(pMaskSet, pExpr->pSelect);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect);
|
||||
}else{
|
||||
pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList);
|
||||
}
|
||||
}else if( op==TK_ISNULL ){
|
||||
pTerm->prereqRight = 0;
|
||||
}else{
|
||||
@@ -1057,7 +1064,7 @@ static void exprAnalyze(
|
||||
Expr *pDup;
|
||||
if( pTerm->leftCursor>=0 ){
|
||||
int idxNew;
|
||||
pDup = sqlite3ExprDup(db, pExpr);
|
||||
pDup = sqlite3ExprDup(db, pExpr, 0);
|
||||
if( db->mallocFailed ){
|
||||
sqlite3ExprDelete(db, pDup);
|
||||
return;
|
||||
@@ -1100,7 +1107,7 @@ static void exprAnalyze(
|
||||
** BETWEEN term is skipped.
|
||||
*/
|
||||
else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
|
||||
ExprList *pList = pExpr->pList;
|
||||
ExprList *pList = pExpr->x.pList;
|
||||
int i;
|
||||
static const u8 ops[] = {TK_GE, TK_LE};
|
||||
assert( pList!=0 );
|
||||
@@ -1108,8 +1115,8 @@ static void exprAnalyze(
|
||||
for(i=0; i<2; i++){
|
||||
Expr *pNewExpr;
|
||||
int idxNew;
|
||||
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft),
|
||||
sqlite3ExprDup(db, pList->a[i].pExpr), 0);
|
||||
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0),
|
||||
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
|
||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
@@ -1148,18 +1155,18 @@ static void exprAnalyze(
|
||||
Expr *pNewExpr1, *pNewExpr2;
|
||||
int idxNew1, idxNew2;
|
||||
|
||||
pLeft = pExpr->pList->a[1].pExpr;
|
||||
pRight = pExpr->pList->a[0].pExpr;
|
||||
pLeft = pExpr->x.pList->a[1].pExpr;
|
||||
pRight = pExpr->x.pList->a[0].pExpr;
|
||||
pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
|
||||
if( pStr1 ){
|
||||
sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
|
||||
pStr1->token.n = nPattern;
|
||||
pStr1->flags = EP_Dequoted;
|
||||
}
|
||||
pStr2 = sqlite3ExprDup(db, pStr1);
|
||||
pStr2 = sqlite3ExprDup(db, pStr1, 0);
|
||||
if( !db->mallocFailed ){
|
||||
u8 c, *pC;
|
||||
assert( pStr2->token.dyn );
|
||||
/* assert( pStr2->token.dyn ); */
|
||||
pC = (u8*)&pStr2->token.z[nPattern-1];
|
||||
c = *pC;
|
||||
if( noCase ){
|
||||
@@ -1168,11 +1175,11 @@ static void exprAnalyze(
|
||||
}
|
||||
*pC = c + 1;
|
||||
}
|
||||
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
|
||||
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft,0),pStr1,0);
|
||||
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew1==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew1);
|
||||
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);
|
||||
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft,0),pStr2,0);
|
||||
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew2==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew2);
|
||||
@@ -1198,13 +1205,13 @@ static void exprAnalyze(
|
||||
WhereTerm *pNewTerm;
|
||||
Bitmask prereqColumn, prereqExpr;
|
||||
|
||||
pRight = pExpr->pList->a[0].pExpr;
|
||||
pLeft = pExpr->pList->a[1].pExpr;
|
||||
pRight = pExpr->x.pList->a[0].pExpr;
|
||||
pLeft = pExpr->x.pList->a[1].pExpr;
|
||||
prereqExpr = exprTableUsage(pMaskSet, pRight);
|
||||
prereqColumn = exprTableUsage(pMaskSet, pLeft);
|
||||
if( (prereqExpr & prereqColumn)==0 ){
|
||||
Expr *pNewExpr;
|
||||
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight), 0);
|
||||
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0), 0);
|
||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
pNewTerm = &pWC->a[idxNew];
|
||||
@@ -1776,10 +1783,12 @@ static void bestIndex(
|
||||
pCost->rCost = 0;
|
||||
pCost->nRow = 1;
|
||||
return;
|
||||
}else if( (pExpr = pTerm->pExpr)->pList!=0 ){
|
||||
}else if( !ExprHasProperty((pExpr = pTerm->pExpr), EP_xIsSelect)
|
||||
&& pExpr->x.pList
|
||||
){
|
||||
/* Rowid IN (LIST): cost is NlogN where N is the number of list
|
||||
** elements. */
|
||||
pCost->rCost = pCost->nRow = pExpr->pList->nExpr;
|
||||
pCost->rCost = pCost->nRow = pExpr->x.pList->nExpr;
|
||||
pCost->rCost *= estLog(pCost->rCost);
|
||||
}else{
|
||||
/* Rowid IN (SELECT): cost is NlogN where N is the number of rows
|
||||
@@ -1925,10 +1934,10 @@ static void bestIndex(
|
||||
if( pTerm->eOperator & WO_IN ){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
wsFlags |= WHERE_COLUMN_IN;
|
||||
if( pExpr->pSelect!=0 ){
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
inMultiplier *= 25;
|
||||
}else if( pExpr->pList ){
|
||||
inMultiplier *= pExpr->pList->nExpr + 1;
|
||||
}else if( pExpr->x.pList ){
|
||||
inMultiplier *= pExpr->x.pList->nExpr + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user