Optimizations on the SELECT code generator. (CVS 1926)

FossilOrigin-Name: 9c411c3c8dde2061c98513a413ef58c5c2de45af
This commit is contained in:
drh 2004-09-01 03:06:34 +00:00
parent c8d7441eb4
commit 91bb0eedd1
5 changed files with 129 additions and 121 deletions

View File

@ -1,5 +1,5 @@
C Changes\sto\ssupport\scompiling\sunder\swindows.\s(CVS\s1925) C Optimizations\son\sthe\sSELECT\scode\sgenerator.\s(CVS\s1926)
D 2004-08-31T23:41:26 D 2004-09-01T03:06:35
F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -34,7 +34,7 @@ F src/build.c 35275654d9c5ce6c1c0c78e391f85e6915a8a66b
F src/date.c edff4aa851eeca8abbc737dc3933a2f0671156ce F src/date.c edff4aa851eeca8abbc737dc3933a2f0671156ce
F src/delete.c cebfdde83e7bf68d8118e1c13e40c99787302fbf F src/delete.c cebfdde83e7bf68d8118e1c13e40c99787302fbf
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
F src/expr.c 3c3dd119fd7910dca40676a46c85785222cdf311 F src/expr.c d618305952f75567514824cf9bdd5de74db5e00a
F src/func.c ab1d6436edea1333f2a9398800a6404942661724 F src/func.c ab1d6436edea1333f2a9398800a6404942661724
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
@ -58,10 +58,10 @@ F src/parse.y 581a2ce014b843506805b2470c02b7865ad034d5
F src/pragma.c b39177b96bb5f7354511468c933357ce65a0dd4c F src/pragma.c b39177b96bb5f7354511468c933357ce65a0dd4c
F src/printf.c 17b28a1eedfe8129b05de981719306c18c3f1327 F src/printf.c 17b28a1eedfe8129b05de981719306c18c3f1327
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c 400b2dcc8e05c0101a65a370f7ebb33c9c85f0b3 F src/select.c 14534579535579a082fda8bbc7d621d7d170f406
F src/shell.c 4f1a2760ced81c829defb47b0a3b61ffec61b604 F src/shell.c 4f1a2760ced81c829defb47b0a3b61ffec61b604
F src/sqlite.h.in b89ced1acc705bc9c79a2a4e725ac0eb64bd0614 F src/sqlite.h.in b89ced1acc705bc9c79a2a4e725ac0eb64bd0614
F src/sqliteInt.h 89c1555ceba68d460ee13530eb8a51944e57fad2 F src/sqliteInt.h 71de4b0400b50579d5dfab70b59adbb7776e77d8
F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49 F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49
F src/tclsqlite.c b7dd8b3531b70188d03354db530de0f2ffcac697 F src/tclsqlite.c b7dd8b3531b70188d03354db530de0f2ffcac697
F src/test1.c 3670f318c473b5a81cae548d9cc42da3f6a6efee F src/test1.c 3670f318c473b5a81cae548d9cc42da3f6a6efee
@ -246,7 +246,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 8fd65e704888a8e2f4a712a94fd0e3f866c10ef3 P 68a712f3728587ee20f6f15900e9826eeeaaa0de
R 0d8f5ad503e5312e676ca00f78eae116 R f53925f0e4c6a8f88635f4df0bffa0ca
U drh U drh
Z 56bb610aa487540418fc40b7a4941024 Z 2051ba3a1de049c2a1d8955c57b2b831

View File

@ -1 +1 @@
68a712f3728587ee20f6f15900e9826eeeaaa0de 9c411c3c8dde2061c98513a413ef58c5c2de45af

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and ** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite. ** for generating VDBE code that evaluates expressions in SQLite.
** **
** $Id: expr.c,v 1.158 2004/08/31 13:45:12 drh Exp $ ** $Id: expr.c,v 1.159 2004/09/01 03:06:35 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -219,6 +219,20 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
return pNew; return pNew;
} }
/*
** Join two expressions using an AND operator. If either expression is
** NULL, then just return the other expression.
*/
Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){
if( pLeft==0 ){
return pRight;
}else if( pRight==0 ){
return pLeft;
}else{
return sqlite3Expr(TK_AND, pLeft, pRight, 0);
}
}
/* /*
** Set the Expr.span field of the given expression to span all ** Set the Expr.span field of the given expression to span all
** text between the two given tokens. ** text between the two given tokens.

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** to handle SELECT statements in SQLite.
** **
** $Id: select.c,v 1.205 2004/08/29 16:25:04 drh Exp $ ** $Id: select.c,v 1.206 2004/09/01 03:06:35 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -144,6 +144,16 @@ static int columnIndex(Table *pTab, const char *zCol){
return -1; return -1;
} }
/*
** Set the value of a token to a '\000'-terminated string.
*/
static void setToken(Token *p, const char *z){
p->z = z;
p->n = strlen(z);
p->dyn = 0;
}
/* /*
** Add a term to the WHERE expression in *ppExpr that requires the ** Add a term to the WHERE expression in *ppExpr that requires the
** zCol column to be equal in the two tables pTab1 and pTab2. ** zCol column to be equal in the two tables pTab1 and pTab2.
@ -159,26 +169,18 @@ static void addWhereTerm(
Expr *pE2a, *pE2b, *pE2c; Expr *pE2a, *pE2b, *pE2c;
Expr *pE; Expr *pE;
dummy.z = zCol; setToken(&dummy, zCol);
dummy.n = strlen(zCol);
dummy.dyn = 0;
pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy); pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy);
pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy); pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy);
dummy.z = pTab1->zName; setToken(&dummy, pTab1->zName);
dummy.n = strlen(dummy.z);
pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy); pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy);
dummy.z = pTab2->zName; setToken(&dummy, pTab2->zName);
dummy.n = strlen(dummy.z);
pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy); pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy);
pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0); pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0);
pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0); pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);
pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0); pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0);
ExprSetProperty(pE, EP_FromJoin); ExprSetProperty(pE, EP_FromJoin);
if( *ppExpr ){ *ppExpr = sqlite3ExprAnd(*ppExpr, pE);
*ppExpr = sqlite3Expr(TK_AND, *ppExpr, pE, 0);
}else{
*ppExpr = pE;
}
} }
/* /*
@ -204,55 +206,62 @@ static void setJoinExpr(Expr *p){
** ON and USING clauses are converted into extra terms of the WHERE clause. ** ON and USING clauses are converted into extra terms of the WHERE clause.
** NATURAL joins also create extra WHERE clause terms. ** NATURAL joins also create extra WHERE clause terms.
** **
** The terms of a FROM clause are contained in the Select.pSrc structure.
** The left most table is the first entry in Select.pSrc. The right-most
** table is the last entry. The join operator is held in the entry to
** the left. Thus entry 0 contains the join operator for the join between
** entries 0 and 1. Any ON or USING clauses associated with the join are
** also attached to the left entry.
**
** This routine returns the number of errors encountered. ** This routine returns the number of errors encountered.
*/ */
static int sqliteProcessJoin(Parse *pParse, Select *p){ static int sqliteProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc; SrcList *pSrc; /* All tables in the FROM clause */
int i, j; int i, j; /* Loop counters */
pSrc = p->pSrc; struct SrcList_item *pLeft; /* Left table being joined */
for(i=0; i<pSrc->nSrc-1; i++){ struct SrcList_item *pRight; /* Right table being joined */
struct SrcList_item *pTerm = &pSrc->a[i];
struct SrcList_item *pOther = &pSrc->a[i+1];
if( pTerm->pTab==0 || pOther->pTab==0 ) continue; pSrc = p->pSrc;
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
Table *pLeftTab = pLeft->pTab;
Table *pRightTab = pRight->pTab;
if( pLeftTab==0 || pRightTab==0 ) continue;
/* When the NATURAL keyword is present, add WHERE clause terms for /* When the NATURAL keyword is present, add WHERE clause terms for
** every column that the two tables have in common. ** every column that the two tables have in common.
*/ */
if( pTerm->jointype & JT_NATURAL ){ if( pLeft->jointype & JT_NATURAL ){
Table *pTab; if( pLeft->pOn || pLeft->pUsing ){
if( pTerm->pOn || pTerm->pUsing ){
sqlite3ErrorMsg(pParse, "a NATURAL join may not have " sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
"an ON or USING clause", 0); "an ON or USING clause", 0);
return 1; return 1;
} }
pTab = pTerm->pTab; for(j=0; j<pLeftTab->nCol; j++){
for(j=0; j<pTab->nCol; j++){ char *zName = pLeftTab->aCol[j].zName;
if( columnIndex(pOther->pTab, pTab->aCol[j].zName)>=0 ){ if( columnIndex(pRightTab, zName)>=0 ){
addWhereTerm(pTab->aCol[j].zName, pTab, pOther->pTab, &p->pWhere); addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere);
} }
} }
} }
/* Disallow both ON and USING clauses in the same join /* Disallow both ON and USING clauses in the same join
*/ */
if( pTerm->pOn && pTerm->pUsing ){ if( pLeft->pOn && pLeft->pUsing ){
sqlite3ErrorMsg(pParse, "cannot have both ON and USING " sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
"clauses in the same join"); "clauses in the same join");
return 1; return 1;
} }
/* Add the ON clause to the end of the WHERE clause, connected by /* Add the ON clause to the end of the WHERE clause, connected by
** and AND operator. ** an AND operator.
*/ */
if( pTerm->pOn ){ if( pLeft->pOn ){
setJoinExpr(pTerm->pOn); setJoinExpr(pLeft->pOn);
if( p->pWhere==0 ){ p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn);
p->pWhere = pTerm->pOn; pLeft->pOn = 0;
}else{
p->pWhere = sqlite3Expr(TK_AND, p->pWhere, pTerm->pOn, 0);
}
pTerm->pOn = 0;
} }
/* Create extra terms on the WHERE clause for each column named /* Create extra terms on the WHERE clause for each column named
@ -262,19 +271,16 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
** Report an error if any column mentioned in the USING clause is ** Report an error if any column mentioned in the USING clause is
** not contained in both tables to be joined. ** not contained in both tables to be joined.
*/ */
if( pTerm->pUsing ){ if( pLeft->pUsing ){
IdList *pList; IdList *pList = pLeft->pUsing;
int j;
assert( i<pSrc->nSrc-1 );
pList = pTerm->pUsing;
for(j=0; j<pList->nId; j++){ for(j=0; j<pList->nId; j++){
if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 || char *zName = pList->a[j].zName;
columnIndex(pOther->pTab, pList->a[j].zName)<0 ){ if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){
sqlite3ErrorMsg(pParse, "cannot join using column %s - column " sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", pList->a[j].zName); "not present in both tables", zName);
return 1; return 1;
} }
addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere); addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere);
} }
} }
} }
@ -821,32 +827,29 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
Expr *pR; Expr *pR;
char *zType; char *zType;
char *zName;
Expr *p = pEList->a[i].pExpr; Expr *p = pEList->a[i].pExpr;
assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
if( pEList->a[i].zName ){ if( (zName = pEList->a[i].zName)!=0 ){
pCol->zName = sqliteStrDup(pEList->a[i].zName); zName = sqliteStrDup(zName);
}else if( p->op==TK_DOT }else if( p->op==TK_DOT
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
int cnt; int cnt;
sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, 0); zName = sqlite3MPrintf("%T", &pR->token);
for(j=cnt=0; j<i; j++){ for(j=cnt=0; j<i; j++){
if( sqlite3StrICmp(aCol[j].zName, pCol->zName)==0 ){ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
int n; sqliteFree(zName);
char zBuf[30]; zName = sqlite3MPrintf("%T_%d", &pR->token, ++cnt);
sprintf(zBuf,"_%d",++cnt);
n = strlen(zBuf);
sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, zBuf,n,0);
j = -1; j = -1;
} }
} }
}else if( p->span.z && p->span.z[0] ){ }else if( p->span.z && p->span.z[0] ){
sqlite3SetNString(&pCol->zName, p->span.z, p->span.n, 0); zName = sqlite3MPrintf("%T", &p->span);
}else{ }else{
char zBuf[30]; zName = sqlite3MPrintf("column%d", i+1);
sprintf(zBuf, "column%d", i+1);
pCol->zName = sqliteStrDup(zBuf);
} }
sqlite3Dequote(pCol->zName); sqlite3Dequote(zName);
pCol->zName = zName;
zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p)); zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
pCol->zType = zType; pCol->zType = zType;
@ -907,9 +910,8 @@ static int fillInColumnList(Parse *pParse, Select *p){
/* A sub-query in the FROM clause of a SELECT */ /* A sub-query in the FROM clause of a SELECT */
assert( pFrom->pSelect!=0 ); assert( pFrom->pSelect!=0 );
if( pFrom->zAlias==0 ){ if( pFrom->zAlias==0 ){
char zFakeName[60]; pFrom->zAlias =
sprintf(zFakeName, "sqlite_subquery_%p_", (void*)pFrom->pSelect); sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect);
sqlite3SetString(&pFrom->zAlias, zFakeName, 0);
} }
pFrom->pTab = pTab = pFrom->pTab = pTab =
sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
@ -1009,31 +1011,29 @@ static int fillInColumnList(Parse *pParse, Select *p){
Expr *pExpr, *pLeft, *pRight; Expr *pExpr, *pLeft, *pRight;
char *zName = pTab->aCol[j].zName; char *zName = pTab->aCol[j].zName;
if( i>0 && (pTabList->a[i-1].jointype & JT_NATURAL)!=0 && if( i>0 ){
columnIndex(pTabList->a[i-1].pTab, zName)>=0 ){ struct SrcList_item *pLeft = &pTabList->a[i-1];
/* In a NATURAL join, omit the join columns from the if( (pLeft->jointype & JT_NATURAL)!=0 &&
** table on the right */ columnIndex(pLeft->pTab, zName)>=0 ){
continue; /* In a NATURAL join, omit the join columns from the
} ** table on the right */
if( i>0 && sqlite3IdListIndex(pTabList->a[i-1].pUsing, zName)>=0 ){ continue;
/* In a join with a USING clause, omit columns in the }
** using clause from the table on the right. */ if( sqlite3IdListIndex(pLeft->pUsing, zName)>=0 ){
continue; /* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */
continue;
}
} }
pRight = sqlite3Expr(TK_ID, 0, 0, 0); pRight = sqlite3Expr(TK_ID, 0, 0, 0);
if( pRight==0 ) break; if( pRight==0 ) break;
pRight->token.z = zName; setToken(&pRight->token, zName);
pRight->token.n = strlen(zName);
pRight->token.dyn = 0;
if( zTabName && pTabList->nSrc>1 ){ if( zTabName && pTabList->nSrc>1 ){
pLeft = sqlite3Expr(TK_ID, 0, 0, 0); pLeft = sqlite3Expr(TK_ID, 0, 0, 0);
pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0);
if( pExpr==0 ) break; if( pExpr==0 ) break;
pLeft->token.z = zTabName; setToken(&pLeft->token, zTabName);
pLeft->token.n = strlen(zTabName); setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName));
pLeft->token.dyn = 0;
sqlite3SetString((char**)&pExpr->span.z, zTabName, ".", zName, 0);
pExpr->span.n = strlen(pExpr->span.z);
pExpr->span.dyn = 1; pExpr->span.dyn = 1;
pExpr->token.z = 0; pExpr->token.z = 0;
pExpr->token.n = 0; pExpr->token.n = 0;
@ -1078,16 +1078,17 @@ static int fillInColumnList(Parse *pParse, Select *p){
void sqlite3SelectUnbind(Select *p){ void sqlite3SelectUnbind(Select *p){
int i; int i;
SrcList *pSrc = p->pSrc; SrcList *pSrc = p->pSrc;
struct SrcList_item *pItem;
Table *pTab; Table *pTab;
if( p==0 ) return; if( p==0 ) return;
for(i=0; i<pSrc->nSrc; i++){ for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
if( (pTab = pSrc->a[i].pTab)!=0 ){ if( (pTab = pItem->pTab)!=0 ){
if( pTab->isTransient ){ if( pTab->isTransient ){
sqlite3DeleteTable(0, pTab); sqlite3DeleteTable(0, pTab);
} }
pSrc->a[i].pTab = 0; pItem->pTab = 0;
if( pSrc->a[i].pSelect ){ if( pItem->pSelect ){
sqlite3SelectUnbind(pSrc->a[i].pSelect); sqlite3SelectUnbind(pItem->pSelect);
} }
} }
} }
@ -1263,7 +1264,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
nColumn = p->pEList->nExpr; nColumn = p->pEList->nExpr;
pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) ); pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) );
if( pKeyInfo==0 ) return 0; if( pKeyInfo==0 ) return 0;
pKeyInfo->enc = pParse->db->enc; pKeyInfo->enc = db->enc;
pKeyInfo->nField = nColumn; pKeyInfo->nField = nColumn;
for(i=0; i<nColumn; i++){ for(i=0; i<nColumn; i++){
pKeyInfo->aColl[i] = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr); pKeyInfo->aColl[i] = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
@ -1836,15 +1837,17 @@ static int flattenSubquery(
SrcList *pSubSrc; /* The FROM clause of the subquery */ SrcList *pSubSrc; /* The FROM clause of the subquery */
ExprList *pList; /* The result set of the outer query */ ExprList *pList; /* The result set of the outer query */
int iParent; /* VDBE cursor number of the pSub result set temp table */ int iParent; /* VDBE cursor number of the pSub result set temp table */
int i; int i; /* Loop counter */
Expr *pWhere; Expr *pWhere; /* The WHERE clause */
struct SrcList_item *pSubitem; /* The subquery */
/* Check to see if flattening is permitted. Return 0 if not. /* Check to see if flattening is permitted. Return 0 if not.
*/ */
if( p==0 ) return 0; if( p==0 ) return 0;
pSrc = p->pSrc; pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSub = pSrc->a[iFrom].pSelect; pSubitem = &pSrc->a[iFrom];
pSub = pSubitem->pSelect;
assert( pSub!=0 ); assert( pSub!=0 );
if( isAgg && subqueryIsAgg ) return 0; if( isAgg && subqueryIsAgg ) return 0;
if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
@ -1903,17 +1906,18 @@ static int flattenSubquery(
** those references with expressions that resolve to the subquery FROM ** those references with expressions that resolve to the subquery FROM
** elements we are now copying in. ** elements we are now copying in.
*/ */
iParent = pSrc->a[iFrom].iCursor; iParent = pSubitem->iCursor;
{ {
int nSubSrc = pSubSrc->nSrc; int nSubSrc = pSubSrc->nSrc;
int jointype = pSrc->a[iFrom].jointype; int jointype = pSubitem->jointype;
Table *pTab = pSubitem->pTab;
if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){ if( pTab && pTab->isTransient ){
sqlite3DeleteTable(0, pSrc->a[iFrom].pTab); sqlite3DeleteTable(0, pSubitem->pTab);
} }
sqliteFree(pSrc->a[iFrom].zDatabase); sqliteFree(pSubitem->zDatabase);
sqliteFree(pSrc->a[iFrom].zName); sqliteFree(pSubitem->zName);
sqliteFree(pSrc->a[iFrom].zAlias); sqliteFree(pSubitem->zAlias);
if( nSubSrc>1 ){ if( nSubSrc>1 ){
int extra = nSubSrc - 1; int extra = nSubSrc - 1;
for(i=1; i<nSubSrc; i++){ for(i=1; i<nSubSrc; i++){
@ -1972,23 +1976,12 @@ static int flattenSubquery(
p->pHaving = p->pWhere; p->pHaving = p->pWhere;
p->pWhere = pWhere; p->pWhere = pWhere;
substExpr(p->pHaving, iParent, pSub->pEList); substExpr(p->pHaving, iParent, pSub->pEList);
if( pSub->pHaving ){ p->pHaving = sqlite3ExprAnd(p->pHaving, sqlite3ExprDup(pSub->pHaving));
Expr *pHaving = sqlite3ExprDup(pSub->pHaving);
if( p->pHaving ){
p->pHaving = sqlite3Expr(TK_AND, p->pHaving, pHaving, 0);
}else{
p->pHaving = pHaving;
}
}
assert( p->pGroupBy==0 ); assert( p->pGroupBy==0 );
p->pGroupBy = sqlite3ExprListDup(pSub->pGroupBy); p->pGroupBy = sqlite3ExprListDup(pSub->pGroupBy);
}else if( p->pWhere==0 ){
p->pWhere = pWhere;
}else{ }else{
substExpr(p->pWhere, iParent, pSub->pEList); substExpr(p->pWhere, iParent, pSub->pEList);
if( pWhere ){ p->pWhere = sqlite3ExprAnd(p->pWhere, pWhere);
p->pWhere = sqlite3Expr(TK_AND, p->pWhere, pWhere, 0);
}
} }
/* The flattened query is distinct if either the inner or the /* The flattened query is distinct if either the inner or the

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.317 2004/08/31 00:52:37 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.318 2004/09/01 03:06:35 drh Exp $
*/ */
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@ -1208,6 +1208,7 @@ int sqlite3KeywordCode(const char*, int);
int sqlite3RunParser(Parse*, const char*, char **); int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*); void sqlite3FinishCoding(Parse*);
Expr *sqlite3Expr(int, Expr*, Expr*, Token*); Expr *sqlite3Expr(int, Expr*, Expr*, Token*);
Expr *sqlite3ExprAnd(Expr*, Expr*);
void sqlite3ExprSpan(Expr*,Token*,Token*); void sqlite3ExprSpan(Expr*,Token*,Token*);
Expr *sqlite3ExprFunction(ExprList*, Token*); Expr *sqlite3ExprFunction(ExprList*, Token*);
void sqlite3ExprDelete(Expr*); void sqlite3ExprDelete(Expr*);