]> granicus.if.org Git - postgresql/blobdiff - src/backend/optimizer/prep/prepunion.c
Extend set-operation planning to keep track of the sort ordering induced
[postgresql] / src / backend / optimizer / prep / prepunion.c
index 9424fc7148282623881835c51069522df418113f..b703bf2b86e095c81dcc95435f32e7f16334ca3e 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.108 2004/01/18 00:50:02 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.109 2004/04/07 18:17:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,11 +45,12 @@ typedef struct
 
 static Plan *recurse_set_operations(Node *setOp, Query *parse,
                                           List *colTypes, bool junkOK,
-                                          int flag, List *refnames_tlist);
+                                          int flag, List *refnames_tlist,
+                                          List **sortClauses);
 static Plan *generate_union_plan(SetOperationStmt *op, Query *parse,
-                                       List *refnames_tlist);
+                                       List *refnames_tlist, List **sortClauses);
 static Plan *generate_nonunion_plan(SetOperationStmt *op, Query *parse,
-                                          List *refnames_tlist);
+                                          List *refnames_tlist, List **sortClauses);
 static List *recurse_union_children(Node *setOp, Query *parse,
                                           SetOperationStmt *top_union,
                                           List *refnames_tlist);
@@ -75,9 +76,12 @@ static List *adjust_inherited_tlist(List *tlist, Oid old_relid, Oid new_relid);
  * This routine only deals with the setOperations tree of the given query.
  * Any top-level ORDER BY requested in parse->sortClause will be added
  * when we return to grouping_planner.
+ *
+ * *sortClauses is an output argument: it is set to a list of SortClauses
+ * representing the result ordering of the topmost set operation.
  */
 Plan *
-plan_set_operations(Query *parse)
+plan_set_operations(Query *parse, List **sortClauses)
 {
        SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
        Node       *node;
@@ -113,7 +117,8 @@ plan_set_operations(Query *parse)
         */
        return recurse_set_operations((Node *) topop, parse,
                                                                  topop->colTypes, true, -1,
-                                                                 leftmostQuery->targetList);
+                                                                 leftmostQuery->targetList,
+                                                                 sortClauses);
 }
 
 /*
@@ -124,11 +129,13 @@ plan_set_operations(Query *parse)
  * junkOK: if true, child resjunk columns may be left in the result
  * flag: if >= 0, add a resjunk output column indicating value of flag
  * refnames_tlist: targetlist to take column names from
+ * *sortClauses: receives list of SortClauses for result plan, if any
  */
 static Plan *
 recurse_set_operations(Node *setOp, Query *parse,
                                           List *colTypes, bool junkOK,
-                                          int flag, List *refnames_tlist)
+                                          int flag, List *refnames_tlist,
+                                          List **sortClauses)
 {
        if (IsA(setOp, RangeTblRef))
        {
@@ -155,6 +162,13 @@ recurse_set_operations(Node *setOp, Query *parse,
                                                          NIL,
                                                          rtr->rtindex,
                                                          subplan);
+
+               /*
+                * We don't bother to determine the subquery's output ordering
+                * since it won't be reflected in the set-op result anyhow.
+                */
+               *sortClauses = NIL;
+
                return plan;
        }
        else if (IsA(setOp, SetOperationStmt))
@@ -164,9 +178,11 @@ recurse_set_operations(Node *setOp, Query *parse,
 
                /* UNIONs are much different from INTERSECT/EXCEPT */
                if (op->op == SETOP_UNION)
-                       plan = generate_union_plan(op, parse, refnames_tlist);
+                       plan = generate_union_plan(op, parse, refnames_tlist,
+                                                                          sortClauses);
                else
-                       plan = generate_nonunion_plan(op, parse, refnames_tlist);
+                       plan = generate_nonunion_plan(op, parse, refnames_tlist,
+                                                                                 sortClauses);
 
                /*
                 * If necessary, add a Result node to project the caller-requested
@@ -206,7 +222,8 @@ recurse_set_operations(Node *setOp, Query *parse,
  */
 static Plan *
 generate_union_plan(SetOperationStmt *op, Query *parse,
-                                       List *refnames_tlist)
+                                       List *refnames_tlist,
+                                       List **sortClauses)
 {
        List       *planlist;
        List       *tlist;
@@ -249,7 +266,11 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
                sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
                plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan);
                plan = (Plan *) make_unique(plan, sortList);
+               *sortClauses = sortList;
        }
+       else
+               *sortClauses = NIL;
+
        return plan;
 }
 
@@ -258,23 +279,27 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
  */
 static Plan *
 generate_nonunion_plan(SetOperationStmt *op, Query *parse,
-                                          List *refnames_tlist)
+                                          List *refnames_tlist,
+                                          List **sortClauses)
 {
        Plan       *lplan,
                           *rplan,
                           *plan;
        List       *tlist,
                           *sortList,
-                          *planlist;
+                          *planlist,
+                          *child_sortclauses;
        SetOpCmd        cmd;
 
        /* Recurse on children, ensuring their outputs are marked */
        lplan = recurse_set_operations(op->larg, parse,
                                                                   op->colTypes, false, 0,
-                                                                  refnames_tlist);
+                                                                  refnames_tlist,
+                                                                  &child_sortclauses);
        rplan = recurse_set_operations(op->rarg, parse,
                                                                   op->colTypes, false, 1,
-                                                                  refnames_tlist);
+                                                                  refnames_tlist,
+                                                                  &child_sortclauses);
        planlist = makeList2(lplan, rplan);
 
        /*
@@ -315,6 +340,9 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
                        break;
        }
        plan = (Plan *) make_setop(cmd, plan, sortList, length(op->colTypes) + 1);
+
+       *sortClauses = sortList;
+
        return plan;
 }
 
@@ -329,6 +357,8 @@ recurse_union_children(Node *setOp, Query *parse,
                                           SetOperationStmt *top_union,
                                           List *refnames_tlist)
 {
+       List   *child_sortclauses;
+
        if (IsA(setOp, SetOperationStmt))
        {
                SetOperationStmt *op = (SetOperationStmt *) setOp;
@@ -359,7 +389,8 @@ recurse_union_children(Node *setOp, Query *parse,
         */
        return makeList1(recurse_set_operations(setOp, parse,
                                                                                        top_union->colTypes, false,
-                                                                                       -1, refnames_tlist));
+                                                                                       -1, refnames_tlist,
+                                                                                       &child_sortclauses));
 }
 
 /*