As evidenced by [forum:/forumpost/f3f546025a|forum post f3f546025a], the
new RIGHT JOIN related restriction on the push-down optimization implemented by [da3fba18742b6e0b] also needs to apply to the automatic index (a.k.a. hash-join) optimization and to the Bloom filter optimization. Computation of the restriction is now moved into the sqlite3ExprIsSingleTableConstraint() routine. FossilOrigin-Name: 4902015dcf3869f08d9986e422faa231d9218a5e0fc59ba8df0f407e4eb3d605
This commit is contained in:
+38
-6
@@ -2378,10 +2378,11 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
}
|
||||
|
||||
/*
|
||||
** Check pExpr to see if it is an constraint on the single data source pSrc.
|
||||
** In other words, check to see if pExpr constrains pSrc but does not depend
|
||||
** on any other tables or data sources anywhere else in the query. Return
|
||||
** true (non-zero) if pExpr is a constraint on pSrc only.
|
||||
** Check pExpr to see if it is an constraint on the single data source
|
||||
** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr
|
||||
** constrains pSrc but does not depend on any other tables or data
|
||||
** sources anywhere else in the query. Return true (non-zero) if pExpr
|
||||
** is a constraint on pSrc only.
|
||||
**
|
||||
** This is an optimization. False negatives will perhaps cause slower
|
||||
** queries, but false positives will yield incorrect answers. So when in
|
||||
@@ -2398,13 +2399,31 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
**
|
||||
** (4) If pSrc is the right operand of a LEFT JOIN, then...
|
||||
** (4a) pExpr must come from an ON clause..
|
||||
(4b) and specifically the ON clause associated with the LEFT JOIN.
|
||||
** (4b) and specifically the ON clause associated with the LEFT JOIN.
|
||||
**
|
||||
** (5) If pSrc is not the right operand of a LEFT JOIN or the left
|
||||
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
|
||||
** clause, not an ON clause.
|
||||
**
|
||||
** (6) Either:
|
||||
**
|
||||
** (6a) pExpr does not originate in an ON or USING clause, or
|
||||
**
|
||||
** (6b) The ON or USING clause from which pExpr is derived is
|
||||
** not to the left of a RIGHT JOIN (or FULL JOIN).
|
||||
**
|
||||
** Without this restriction, accepting pExpr as a single-table
|
||||
** constraint might move the the ON/USING filter expression
|
||||
** from the left side of a RIGHT JOIN over to the right side,
|
||||
** which leads to incorrect answers. See also restriction (9)
|
||||
** on push-down.
|
||||
*/
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr *pExpr, const SrcItem *pSrc){
|
||||
int sqlite3ExprIsSingleTableConstraint(
|
||||
Expr *pExpr, /* The constraint */
|
||||
const SrcList *pSrcList, /* Complete FROM clause */
|
||||
int iSrc /* Which element of pSrcList to use */
|
||||
){
|
||||
const SrcItem *pSrc = &pSrcList->a[iSrc];
|
||||
if( pSrc->fg.jointype & JT_LTORJ ){
|
||||
return 0; /* rule (3) */
|
||||
}
|
||||
@@ -2414,6 +2433,19 @@ int sqlite3ExprIsSingleTableConstraint(Expr *pExpr, const SrcItem *pSrc){
|
||||
}else{
|
||||
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */
|
||||
}
|
||||
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) /* (6a) */
|
||||
&& (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (6b) */
|
||||
){
|
||||
int jj;
|
||||
for(jj=0; jj<iSrc; jj++){
|
||||
if( pExpr->w.iJoin==pSrcList->a[jj].iCursor ){
|
||||
if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){
|
||||
return 0; /* restriction (6) */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -5119,7 +5119,8 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
|
||||
**
|
||||
** Without this restriction, the push-down optimization might move
|
||||
** the ON/USING filter expression from the left side of a RIGHT JOIN
|
||||
** over to the right side, which leads to incorrect answers.
|
||||
** over to the right side, which leads to incorrect answers. See
|
||||
** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
|
||||
**
|
||||
** (10) The inner query is not the right-hand table of a RIGHT JOIN.
|
||||
**
|
||||
@@ -5204,6 +5205,7 @@ static int pushDownWhereTerms(
|
||||
pWhere = pWhere->pLeft;
|
||||
}
|
||||
|
||||
#if 0 /* These checks now done by sqlite3ExprIsSingleTableConstraint() */
|
||||
if( ExprHasProperty(pWhere, EP_OuterON|EP_InnerON) /* (9a) */
|
||||
&& (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (9c) */
|
||||
){
|
||||
@@ -5221,8 +5223,6 @@ static int pushDownWhereTerms(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* These checks now done by sqlite3ExprIsSingleTableConstraint() */
|
||||
if( isLeftJoin
|
||||
&& (ExprHasProperty(pWhere,EP_OuterON)==0
|
||||
|| pWhere->w.iJoin!=iCursor)
|
||||
@@ -5236,7 +5236,7 @@ static int pushDownWhereTerms(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrc) ){
|
||||
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
|
||||
nChng++;
|
||||
pSubq->selFlags |= SF_PushDown;
|
||||
while( pSubq ){
|
||||
|
||||
+1
-1
@@ -4906,7 +4906,7 @@ int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcItem*);
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
int sqlite3ExprContainsSubquery(Expr*);
|
||||
#endif
|
||||
|
||||
+10
-4
@@ -895,6 +895,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
u8 useBloomFilter = 0; /* True to also add a Bloom filter */
|
||||
Expr *pPartial = 0; /* Partial Index Expression */
|
||||
int iContinue = 0; /* Jump here to skip excluded rows */
|
||||
SrcList *pTabList; /* The complete FROM clause */
|
||||
SrcItem *pSrc; /* The FROM clause term to get the next index */
|
||||
int addrCounter = 0; /* Address where integer counter is initialized */
|
||||
int regBase; /* Array of registers where record is assembled */
|
||||
@@ -911,7 +912,8 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
/* Count the number of columns that will be added to the index
|
||||
** and used to match WHERE clause constraints */
|
||||
nKeyCol = 0;
|
||||
pSrc = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
|
||||
pTabList = pWC->pWInfo->pTabList;
|
||||
pSrc = &pTabList->a[pLevel->iFrom];
|
||||
pTable = pSrc->pTab;
|
||||
pWCEnd = &pWC->a[pWC->nTerm];
|
||||
pLoop = pLevel->pWLoop;
|
||||
@@ -922,7 +924,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
** WHERE clause (or the ON clause of a LEFT join) that constrain which
|
||||
** rows of the target table (pSrc) that can be used. */
|
||||
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pSrc)
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
|
||||
){
|
||||
pPartial = sqlite3ExprAnd(pParse, pPartial,
|
||||
sqlite3ExprDup(pParse->db, pExpr, 0));
|
||||
@@ -1150,9 +1152,11 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
|
||||
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
do{
|
||||
const SrcList *pTabList;
|
||||
const SrcItem *pItem;
|
||||
const Table *pTab;
|
||||
u64 sz;
|
||||
int iSrc;
|
||||
sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel);
|
||||
addrCont = sqlite3VdbeMakeLabel(pParse);
|
||||
iCur = pLevel->iTabCur;
|
||||
@@ -1166,7 +1170,9 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
** testing complicated. By basing the blob size on the value in the
|
||||
** sqlite_stat1 table, testing is much easier.
|
||||
*/
|
||||
pItem = &pWInfo->pTabList->a[pLevel->iFrom];
|
||||
pTabList = pWInfo->pTabList;
|
||||
iSrc = pLevel->iFrom;
|
||||
pItem = &pTabList->a[iSrc];
|
||||
assert( pItem!=0 );
|
||||
pTab = pItem->pTab;
|
||||
assert( pTab!=0 );
|
||||
@@ -1183,7 +1189,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pItem)
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
|
||||
){
|
||||
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user