mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Rearrange the querytree representation of ORDER BY/GROUP BY/DISTINCT items
as per my recent proposal: 1. Fold SortClause and GroupClause into a single node type SortGroupClause. We were already relying on them to be struct-equivalent, so using two node tags wasn't accomplishing much except to get in the way of comparing items with equal(). 2. Add an "eqop" field to SortGroupClause to carry the associated equality operator. This is cheap for the parser to get at the same time it's looking up the sort operator, and storing it eliminates the need for repeated not-so-cheap lookups during planning. In future this will also let us represent GROUP/DISTINCT operations on datatypes that have hash opclasses but no btree opclasses (ie, they have equality but no natural sort order). The previous representation simply didn't work for that, since its only indicator of comparison semantics was a sort operator. 3. Add a hasDistinctOn boolean to struct Query to explicitly record whether the distinctClause came from DISTINCT or DISTINCT ON. This allows removing some complicated and not 100% bulletproof code that attempted to figure that out from the distinctClause alone. This patch doesn't in itself create any new capability, but it's necessary infrastructure for future attempts to use hash-based grouping for DISTINCT and UNION/INTERSECT/EXCEPT.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.171 2008/06/27 03:56:55 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.172 2008/08/02 21:31:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -963,11 +963,12 @@ compare_tlist_datatypes(List *tlist, List *colTypes,
|
||||
*
|
||||
* 4. If the subquery uses DISTINCT ON, we must not push down any quals that
|
||||
* refer to non-DISTINCT output columns, because that could change the set
|
||||
* of rows returned. This condition is vacuous for DISTINCT, because then
|
||||
* there are no non-DISTINCT output columns, but unfortunately it's fairly
|
||||
* expensive to tell the difference between DISTINCT and DISTINCT ON in the
|
||||
* parsetree representation. It's cheaper to just make sure all the Vars
|
||||
* in the qual refer to DISTINCT columns.
|
||||
* of rows returned. (This condition is vacuous for DISTINCT, because then
|
||||
* there are no non-DISTINCT output columns, so we needn't check. But note
|
||||
* we are assuming that the qual can't distinguish values that the DISTINCT
|
||||
* operator sees as equal. This is a bit shaky but we have no way to test
|
||||
* for the case, and it's unlikely enough that we shouldn't refuse the
|
||||
* optimization just because it could theoretically happen.)
|
||||
*
|
||||
* 5. We must not push down any quals that refer to subselect outputs that
|
||||
* return sets, else we'd introduce functions-returning-sets into the
|
||||
@ -1030,8 +1031,8 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
|
||||
Assert(tle != NULL);
|
||||
Assert(!tle->resjunk);
|
||||
|
||||
/* If subquery uses DISTINCT or DISTINCT ON, check point 4 */
|
||||
if (subquery->distinctClause != NIL &&
|
||||
/* If subquery uses DISTINCT ON, check point 4 */
|
||||
if (subquery->hasDistinctOn &&
|
||||
!targetIsInSortList(tle, InvalidOid, subquery->distinctClause))
|
||||
{
|
||||
/* non-DISTINCT column, so fail */
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.10 2008/03/31 16:59:26 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.11 2008/08/02 21:31:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -355,7 +355,7 @@ add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
|
||||
* class it is a member of; if none, build a new single-member
|
||||
* EquivalenceClass for it.
|
||||
*
|
||||
* sortref is the SortGroupRef of the originating SortClause, if any,
|
||||
* sortref is the SortGroupRef of the originating SortGroupClause, if any,
|
||||
* or zero if not.
|
||||
*
|
||||
* This can be used safely both before and after EquivalenceClass merging;
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.93 2008/01/09 20:42:28 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.94 2008/08/02 21:31:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -227,8 +227,8 @@ canonicalize_pathkeys(PlannerInfo *root, List *pathkeys)
|
||||
* a PathKey. If canonicalize = true, the result is a "canonical"
|
||||
* PathKey, otherwise not. (But note it might be redundant anyway.)
|
||||
*
|
||||
* If the PathKey is being generated from a SortClause, sortref should be
|
||||
* the SortClause's SortGroupRef; otherwise zero.
|
||||
* If the PathKey is being generated from a SortGroupClause, sortref should be
|
||||
* the SortGroupClause's SortGroupRef; otherwise zero.
|
||||
*
|
||||
* canonicalize should always be TRUE after EquivalenceClass merging has
|
||||
* been performed, but FALSE if we haven't done EquivalenceClass merging yet.
|
||||
@ -823,7 +823,7 @@ build_join_pathkeys(PlannerInfo *root,
|
||||
/*
|
||||
* make_pathkeys_for_sortclauses
|
||||
* Generate a pathkeys list that represents the sort order specified
|
||||
* by a list of SortClauses (GroupClauses will work too!)
|
||||
* by a list of SortGroupClauses
|
||||
*
|
||||
* If canonicalize is TRUE, the resulting PathKeys are all in canonical form;
|
||||
* otherwise not. canonicalize should always be TRUE after EquivalenceClass
|
||||
@ -832,7 +832,7 @@ build_join_pathkeys(PlannerInfo *root,
|
||||
* be able to represent requested pathkeys before the equivalence classes have
|
||||
* been created for the query.)
|
||||
*
|
||||
* 'sortclauses' is a list of SortClause or GroupClause nodes
|
||||
* 'sortclauses' is a list of SortGroupClause nodes
|
||||
* 'tlist' is the targetlist to find the referenced tlist entries in
|
||||
*/
|
||||
List *
|
||||
@ -846,11 +846,12 @@ make_pathkeys_for_sortclauses(PlannerInfo *root,
|
||||
|
||||
foreach(l, sortclauses)
|
||||
{
|
||||
SortClause *sortcl = (SortClause *) lfirst(l);
|
||||
SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
|
||||
Expr *sortkey;
|
||||
PathKey *pathkey;
|
||||
|
||||
sortkey = (Expr *) get_sortgroupclause_expr(sortcl, tlist);
|
||||
Assert(OidIsValid(sortcl->sortop));
|
||||
pathkey = make_pathkey_from_sortinfo(root,
|
||||
sortkey,
|
||||
sortcl->sortop,
|
||||
|
Reference in New Issue
Block a user