1
0
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:
drh
2009-11-17 18:31:47 +00:00
parent 68ff78b1b0
commit 039fc32e84
6 changed files with 156 additions and 49 deletions

View File

@@ -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++;
}