mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Improvements to the constant-propagation optimization in order to better
deal with unusual affinities. See [forum:/forumpost/6a06202608|forum post 6a06202608] for more detail. FossilOrigin-Name: 9be208a6d70582c6808abe6e016ab9cd8d10f0deefb8c7a8c0543372cca15b12
This commit is contained in:
62
src/select.c
62
src/select.c
@@ -4417,6 +4417,7 @@ struct WhereConst {
|
||||
Parse *pParse; /* Parsing context */
|
||||
int nConst; /* Number for COLUMN=CONSTANT terms */
|
||||
int nChng; /* Number of times a constant is propagated */
|
||||
int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */
|
||||
Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
|
||||
};
|
||||
|
||||
@@ -4455,6 +4456,9 @@ static void constInsert(
|
||||
return; /* Already present. Return without doing anything. */
|
||||
}
|
||||
}
|
||||
if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
|
||||
pConst->bHasAffBlob = 1;
|
||||
}
|
||||
|
||||
pConst->nConst++;
|
||||
pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
|
||||
@@ -4496,26 +4500,34 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a Walker expression callback. pExpr is a candidate expression
|
||||
** to be replaced by a value. If pExpr is equivalent to one of the
|
||||
** columns named in pWalker->u.pConst, then overwrite it with its
|
||||
** corresponding value.
|
||||
** This is a helper function for Walker callback propagateConstantExprRewrite().
|
||||
**
|
||||
** Argument pExpr is a candidate expression to be replaced by a value. If
|
||||
** pExpr is equivalent to one of the columns named in pWalker->u.pConst,
|
||||
** then overwrite it with the corresponding value. Except, do not do so
|
||||
** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr
|
||||
** is SQLITE_AFF_BLOB.
|
||||
*/
|
||||
static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
|
||||
static int propagateConstantExprRewriteOne(
|
||||
WhereConst *pConst,
|
||||
Expr *pExpr,
|
||||
int bIgnoreAffBlob
|
||||
){
|
||||
int i;
|
||||
WhereConst *pConst;
|
||||
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
|
||||
if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
|
||||
testcase( ExprHasProperty(pExpr, EP_FixedCol) );
|
||||
testcase( ExprHasProperty(pExpr, EP_FromJoin) );
|
||||
return WRC_Continue;
|
||||
}
|
||||
pConst = pWalker->u.pConst;
|
||||
for(i=0; i<pConst->nConst; i++){
|
||||
Expr *pColumn = pConst->apExpr[i*2];
|
||||
if( pColumn==pExpr ) continue;
|
||||
if( pColumn->iTable!=pExpr->iTable ) continue;
|
||||
if( pColumn->iColumn!=pExpr->iColumn ) continue;
|
||||
if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
|
||||
break;
|
||||
}
|
||||
/* A match is found. Add the EP_FixedCol property */
|
||||
pConst->nChng++;
|
||||
ExprClearProperty(pExpr, EP_Leaf);
|
||||
@@ -4527,6 +4539,41 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a Walker expression callback. pExpr is a node from the WHERE
|
||||
** clause of a SELECT statement. This function examines pExpr to see if
|
||||
** any substitutions based on the contents of pWalker->u.pConst should
|
||||
** be made to pExpr or its immediate children.
|
||||
**
|
||||
** A substitution is made if:
|
||||
**
|
||||
** + pExpr is a column with an affinity other than BLOB that matches
|
||||
** one of the columns in pWalker->u.pConst, or
|
||||
**
|
||||
** + pExpr is a binary comparison operator (=, <=, >=, <, >) that
|
||||
** uses an affinity other than TEXT and one of its immediate
|
||||
** children is a column that matches one of the columns in
|
||||
** pWalker->u.pConst.
|
||||
*/
|
||||
static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
|
||||
WhereConst *pConst = pWalker->u.pConst;
|
||||
assert( TK_GT==TK_EQ+1 );
|
||||
assert( TK_LE==TK_EQ+2 );
|
||||
assert( TK_LT==TK_EQ+3 );
|
||||
assert( TK_GE==TK_EQ+4 );
|
||||
if( pConst->bHasAffBlob ){
|
||||
if( (pExpr->op>=TK_EQ && pExpr->op<=TK_GE)
|
||||
|| pExpr->op==TK_IS
|
||||
){
|
||||
propagateConstantExprRewriteOne(pConst, pExpr->pLeft, 0);
|
||||
if( sqlite3ExprAffinity(pExpr->pLeft)!=SQLITE_AFF_TEXT ){
|
||||
propagateConstantExprRewriteOne(pConst, pExpr->pRight, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return propagateConstantExprRewriteOne(pConst, pExpr, pConst->bHasAffBlob);
|
||||
}
|
||||
|
||||
/*
|
||||
** The WHERE-clause constant propagation optimization.
|
||||
**
|
||||
@@ -4575,6 +4622,7 @@ static int propagateConstants(
|
||||
x.nConst = 0;
|
||||
x.nChng = 0;
|
||||
x.apExpr = 0;
|
||||
x.bHasAffBlob = 0;
|
||||
findConstInWhere(&x, p->pWhere);
|
||||
if( x.nConst ){
|
||||
memset(&w, 0, sizeof(w));
|
||||
|
||||
Reference in New Issue
Block a user