1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Improvements and tests for detection of redundant DISTINCT qualifiers.

FossilOrigin-Name: 7337293c87fb563604dd6ad284f2d1e30c938b4c
This commit is contained in:
dan
2011-07-01 14:21:38 +00:00
parent 38cc40c216
commit 50118cdfdb
5 changed files with 161 additions and 36 deletions

View File

@@ -3848,18 +3848,6 @@ int sqlite3Select(
}
#endif
/* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
** GROUP BY might use an index, DISTINCT never does.
*/
#if 0
assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
p->selFlags &= ~SF_Distinct;
}
#endif
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then disable the ORDER BY clause since the GROUP BY
** will cause elements to come out in the correct order. This is
@@ -3872,6 +3860,30 @@ int sqlite3Select(
pOrderBy = 0;
}
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
**
** SELECT DISTINCT xyz FROM ... ORDER BY xyz
**
** is transformed to:
**
** SELECT xyz FROM ... GROUP BY xyz
**
** The second form is preferred as a single index (or temp-table) may be
** used for both the ORDER BY and DISTINCT processing. As originally
** written the query must use a temp-table for at least one of the ORDER
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(pOrderBy, p->pEList)==0
){
p->selFlags &= ~SF_Distinct;
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
pOrderBy = 0;
}
/* If there is an ORDER BY clause, then this sorting
** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
@@ -3935,6 +3947,10 @@ int sqlite3Select(
}
if( pWInfo->eDistinct ){
VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
assert( isDistinct );
assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
|| pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
@@ -3947,11 +3963,9 @@ int sqlite3Select(
int iBase = pParse->nMem+1;
int iBase2 = iBase + pEList->nExpr;
pParse->nMem += (pEList->nExpr*2);
VdbeOp *pOp;
/* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
** OP_Integer initializes the "first row" flag. */
pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
pOp->opcode = OP_Integer;
pOp->p1 = 1;
pOp->p2 = iFlag;
@@ -3970,6 +3984,8 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
assert( sqlite3VdbeCurrentAddr(v)==iJump );
sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
}else{
pOp->opcode = OP_Noop;
}
}