mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-15 11:41:13 +03:00
Code generator tries to avoid pointless OP_IsNull and OP_Affinity opcodes.
FossilOrigin-Name: ebb0c8a3e977dc741704e733b5a5d931d9b27028
This commit is contained in:
92
src/where.c
92
src/where.c
@@ -2594,14 +2594,39 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
||||
** Code an OP_Affinity opcode to apply the column affinity string zAff
|
||||
** to the n registers starting at base.
|
||||
**
|
||||
** This routine assumes that zAff is dynamic and makes its own copy.
|
||||
** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
|
||||
** beginning and end of zAff are ignored. If all entries in zAff are
|
||||
** SQLITE_AFF_NONE, then no code gets generated.
|
||||
**
|
||||
** This routine makes its own copy of zAff so that the caller is free
|
||||
** to modify zAff after this routine returns.
|
||||
*/
|
||||
static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
if( zAff==0 ){
|
||||
assert( pParse->db->mallocFailed );
|
||||
return;
|
||||
}
|
||||
assert( v!=0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
||||
sqlite3VdbeChangeP4(v, -1, zAff, 0);
|
||||
sqlite3ExprCacheAffinityChange(pParse, base, n);
|
||||
|
||||
/* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
|
||||
** and end of the affinity string.
|
||||
*/
|
||||
while( n>0 && zAff[0]==SQLITE_AFF_NONE ){
|
||||
n--;
|
||||
base++;
|
||||
zAff++;
|
||||
}
|
||||
while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){
|
||||
n--;
|
||||
}
|
||||
|
||||
/* Code the OP_Affinity opcode if there is anything left to do. */
|
||||
if( n>0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
||||
sqlite3VdbeChangeP4(v, -1, zAff, n);
|
||||
sqlite3ExprCacheAffinityChange(pParse, base, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2672,7 +2697,7 @@ static int codeEqualityTerm(
|
||||
|
||||
/*
|
||||
** Generate code that will evaluate all == and IN constraints for an
|
||||
** index. The values for all constraints are left on the stack.
|
||||
** index.
|
||||
**
|
||||
** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
|
||||
** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
|
||||
@@ -2684,7 +2709,8 @@ static int codeEqualityTerm(
|
||||
**
|
||||
** In the example above nEq==2. But this subroutine works for any value
|
||||
** of nEq including 0. If nEq==0, this routine is nearly a no-op.
|
||||
** The only thing it does is allocate the pLevel->iMem memory cell.
|
||||
** The only thing it does is allocate the pLevel->iMem memory cell and
|
||||
** compute the affinity string.
|
||||
**
|
||||
** This routine always allocates at least one memory cell and returns
|
||||
** the index of that memory cell. The code that
|
||||
@@ -2762,11 +2788,17 @@ static int codeAllEqualityTerms(
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||
if( zAff
|
||||
&& sqlite3CompareAffinity(pTerm->pExpr->pRight, zAff[j])==SQLITE_AFF_NONE
|
||||
){
|
||||
zAff[j] = SQLITE_AFF_NONE;
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
if( sqlite3ExprCanBeNull(pRight) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||
}
|
||||
if( zAff ){
|
||||
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
|
||||
zAff[j] = SQLITE_AFF_NONE;
|
||||
}
|
||||
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
|
||||
zAff[j] = SQLITE_AFF_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3093,14 +3125,17 @@ static Bitmask codeOneLoopStart(
|
||||
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||
if( zAff
|
||||
&& sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE
|
||||
){
|
||||
/* Since the comparison is to be performed with no conversions applied
|
||||
** to the operands, set the affinity to apply to pRight to
|
||||
** SQLITE_AFF_NONE. */
|
||||
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||
}
|
||||
if( zAff ){
|
||||
if( sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE){
|
||||
/* Since the comparison is to be performed with no conversions
|
||||
** applied to the operands, set the affinity to apply to pRight to
|
||||
** SQLITE_AFF_NONE. */
|
||||
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||
}
|
||||
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[nConstraint]) ){
|
||||
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||
}
|
||||
}
|
||||
nConstraint++;
|
||||
}else if( isMinQuery ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
||||
@@ -3128,14 +3163,17 @@ static Bitmask codeOneLoopStart(
|
||||
sqlite3ExprCacheRemove(pParse, regBase+nEq);
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||
if( zAff
|
||||
&& sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE
|
||||
){
|
||||
/* Since the comparison is to be performed with no conversions applied
|
||||
** to the operands, set the affinity to apply to pRight to
|
||||
** SQLITE_AFF_NONE. */
|
||||
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||
}
|
||||
if( zAff ){
|
||||
if( sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE){
|
||||
/* Since the comparison is to be performed with no conversions
|
||||
** applied to the operands, set the affinity to apply to pRight to
|
||||
** SQLITE_AFF_NONE. */
|
||||
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||
}
|
||||
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[nConstraint]) ){
|
||||
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||
}
|
||||
}
|
||||
codeApplyAffinity(pParse, regBase, nEq+1, zAff);
|
||||
nConstraint++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user