Cleanup of UNION ALL fix. Manual page updates.
authorBruce Momjian
Mon, 29 Dec 1997 01:13:37 +0000 (01:13 +0000)
committerBruce Momjian
Mon, 29 Dec 1997 01:13:37 +0000 (01:13 +0000)
src/backend/optimizer/plan/planner.c
src/backend/optimizer/prep/prepunion.c
src/backend/parser/analyze.c
src/backend/parser/parse_clause.c
src/bin/psql/psqlHelp.h
src/include/optimizer/prep.h
src/include/parser/parse_clause.h
src/man/select.l

index 5c5e80f333d23617b0645058c6463b987bd285c2..bb33f49092d90e507657b2666549c296257ecd88 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.17 1997/12/27 06:41:07 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.18 1997/12/29 01:12:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,14 +76,12 @@ planner(Query *parse)
    Plan       *result_plan = (Plan *) NULL;
 
    List       *primary_qual;
-   int         rt_index;
+   Index       rt_index;
    
 
    if (parse->unionClause)
    {
-       result_plan = (Plan *) plan_union_queries(  0, /* none */
-                                                   parse,
-                                                   UNION_FLAG);
+       result_plan = (Plan *) plan_union_queries(parse);
        /* XXX do we need to do this? bjm 12/19/97 */
        tlist = preprocess_targetlist(tlist,
                                      parse->commandType,
@@ -91,11 +89,9 @@ planner(Query *parse)
                                      parse->rtable);
    }
    else if ((rt_index =
-               first_matching_rt_entry(rangetable, INHERITS_FLAG)) != -1)
+               first_inherit_rt_entry(rangetable)) != -1)
    {
-       result_plan = (Plan *) plan_union_queries((Index) rt_index,
-                                                   parse,
-                                                   INHERITS_FLAG);
+       result_plan = (Plan *) plan_inherit_queries(parse, rt_index);
        /* XXX do we need to do this? bjm 12/19/97 */
        tlist = preprocess_targetlist(tlist,
                                      parse->commandType,
index c0386d2a126ad7b14d18bc5c56e05fde9f1b1c09..5cb89aac867f600aae446a67acc04f54fe2c9a65 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.15 1997/12/27 06:41:17 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.16 1997/12/29 01:12:48 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,8 +34,8 @@
 #include "optimizer/planner.h"
 #include "optimizer/planmain.h"
 
-static List *plan_union_query(List *relids, Index rt_index,
-                RangeTblEntry *rt_entry, Query *parse, UnionFlag flag,
+static List *plan_inherit_query(List *relids, Index rt_index,
+                RangeTblEntry *rt_entry, Query *parse,
                 List **union_rtentriesPtr);
 static RangeTblEntry *new_rangetable_entry(Oid new_relid,
                     RangeTblEntry *old_entry);
@@ -48,83 +48,158 @@ static Append *make_append(List *unionplans, List *unionrts, Index rt_index,
 
 
 /*
- * find-all-inheritors -
- *     Returns a list of relids corresponding to relations that inherit
- *     attributes from any relations listed in either of the argument relid
- *     lists.
+ * plan-union-queries--
+ *
+ *   Plans the queries for a given UNION.
+ *
+ * Returns a list containing a list of plans and a list of rangetables
  */
-List      *
-find_all_inheritors(List *unexamined_relids,
-                   List *examined_relids)
+Append    *
+plan_union_queries(Query *parse)
 {
-   List       *new_inheritors = NIL;
-   List       *new_examined_relids = NIL;
-   List       *new_unexamined_relids = NIL;
-
+   List    *union_plans = NIL, *ulist, *unionall_queries, *union_rts,
+           *last_union = NIL;
+   bool    union_all_found = false, union_found = false,
+           last_unionall_flag = false;
+   
    /*
-    * Find all relations which inherit from members of
-    * 'unexamined-relids' and store them in 'new-inheritors'.
+    *  Do we need to split up our unions because we have UNION
+    *  and UNION ALL?
+    *
+    *  We are checking for the case of:
+    *      SELECT 1
+    *      UNION
+    *      SELECT 2
+    *      UNION
+    *      SELECT 3
+    *      UNION ALL
+    *      SELECT 4
+    *      UNION ALL
+    *      SELECT 5
+    *
+    *  where we have to do a DISTINCT on the output of the first three
+    *  queries, then add the rest.  If they have used UNION and
+    *  UNION ALL, we grab all queries up to the last UNION query,
+    *  make them their own UNION with the owner as the first query
+    *  in the list.  Then, we take the remaining queries, which is UNION
+    *  ALL, and add them to the list of union queries.
+    *
+    *  So the above query becomes:
+    *
+    *  Append Node
+    *  {
+    *      Sort and Unique
+    *      {
+    *          Append Node
+    *          {
+    *              SELECT 1                This is really a sub-UNION,
+    *              unionClause             We run a DISTINCT on these.
+    *              {
+    *                  SELECT 2            
+    *                  SELECT 3            
+    *              }
+    *          }
+    *      }
+    *      SELECT 4
+    *      SELECT 5
+    *  }
+    *      
     */
-   List       *rels = NIL;
-   List       *newrels = NIL;
 
-   foreach(rels, unexamined_relids)
+   foreach(ulist, parse->unionClause)
    {
-       newrels = (List *) LispUnioni(find_inheritance_children(lfirsti(rels)),
-                                     newrels);
-   }
-   new_inheritors = newrels;
+       Query   *union_query = lfirst(ulist);
 
-   new_examined_relids = (List *) LispUnioni(examined_relids, unexamined_relids);
-   new_unexamined_relids = set_differencei(new_inheritors,
-                                           new_examined_relids);
+       if (union_query->unionall)
+           union_all_found = true;
+       else
+       {
+           union_found = true;
+           last_union = ulist;
+       }
+       last_unionall_flag = union_query->unionall;
+   }
 
-   if (new_unexamined_relids == NULL)
+   /* Is this a simple one */
+   if (!union_all_found ||
+       !union_found ||
+       /*  A trailing UNION negates the affect of earlier UNION ALLs */
+       !last_unionall_flag)
    {
-       return (new_examined_relids);
+       List *hold_unionClause = parse->unionClause;
+
+       parse->unionClause = NIL;   /* prevent recursion */
+       union_plans = lcons(planner(parse), NIL);
+       union_rts = lcons(parse->rtable, NIL);
+
+       foreach(ulist, hold_unionClause)
+       {
+           Query *union_query = lfirst(ulist);
+
+           union_plans = lappend(union_plans, planner(union_query));
+           union_rts = lappend(union_rts, union_query->rtable);
+       }
    }
    else
    {
-       return (find_all_inheritors(new_unexamined_relids,
-                                   new_examined_relids));
-   }
-}
+       /*
+        *  We have mixed unions and non-unions
+        *
+        *  We need to restructure this to put the UNIONs on their own
+        *  so we can do a DISTINCT.
+        */
 
-/*
- * first-matching-rt-entry -
- *     Given a rangetable, find the first rangetable entry that represents
- *     the appropriate special case.
- *
- *     Returns a rangetable index.,  Returns -1 if no matches
- */
-int
-first_matching_rt_entry(List *rangetable, UnionFlag flag)
-{
-   int         count = 0;
-   List       *temp = NIL;
+        /* save off everthing past the last UNION */
+       unionall_queries = lnext(last_union);
 
-   foreach(temp, rangetable)
-   {
-       RangeTblEntry *rt_entry = lfirst(temp);
+       /* clip off the list to remove the trailing UNION ALLs */
+       lnext(last_union) = NIL;
+
+       /*
+        *  Recursion, but UNION only.
+        *  The last one is a UNION, so it will not come here in recursion,
+        */
+       union_plans = lcons(planner(parse), NIL);
+       union_rts = lcons(parse->rtable, NIL);
 
-       switch (flag)
+       /* Append the remainging UNION ALLs */
+       foreach(ulist, unionall_queries)
        {
-           case INHERITS_FLAG:
-               if (rt_entry->inh)
-                   return count + 1;
-               break;
-           default:
-               break;
+           Query   *unionall_query = lfirst(ulist);
+
+           union_plans = lappend(union_plans, planner(unionall_query));
+           union_rts = lappend(union_rts, unionall_query->rtable);
        }
-       count++;
    }
+       
+   /* We have already split UNION and UNION ALL and we made it consistent */
+   if (!last_unionall_flag)
+   {
+       parse->uniqueFlag = "*";
+       parse->sortClause = transformSortClause(NULL, NIL,
+           ((Plan *) lfirst(union_plans))->targetlist, "*");
+   }
+   else
+   {
+       /* needed so we don't take the flag from the first query */
+       parse->uniqueFlag = NULL;
+       parse->sortClause = NIL;
+   }
+
+   parse->havingQual = NULL;
+   parse->qry_numAgg = 0;
+   parse->qry_aggs = NULL;
 
-   return (-1);
+   return (make_append(union_plans,
+                       union_rts,
+                       0,
+                       NULL,
+                       ((Plan *) lfirst(union_plans))->targetlist));
 }
 
 
 /*
- * plan-union-queries--
+ * plan-inherit-queries--
  *
  *   Plans the queries for a given parent relation.
  *
@@ -133,122 +208,45 @@ first_matching_rt_entry(List *rangetable, UnionFlag flag)
  * XXX - what exactly does this mean, look for make_append
  */
 Append    *
-plan_union_queries(Index rt_index,
-                  Query *parse,
-                  UnionFlag flag)
+plan_inherit_queries(Query *parse, Index rt_index)
 {
    List       *union_plans = NIL;
 
-   switch (flag)
-   {
-       case INHERITS_FLAG:
-           {
-               List       *rangetable = parse->rtable;
-               RangeTblEntry *rt_entry = rt_fetch(rt_index, rangetable);
-               List       *union_rt_entries = NIL;
-               List       *union_relids = NIL;
-   
-               union_relids =
-                   find_all_inheritors(lconsi(rt_entry->relid,
-                                              NIL),
-                                       NIL);
-               /*
-                * Remove the flag for this relation, since we're about to handle it
-                * (do it before recursing!). XXX destructive parse tree change
-                */
-               switch (flag)
-               {
-                   case INHERITS_FLAG:
-                       rt_fetch(rt_index, rangetable)->inh = false;
-                       break;
-                   default:
-                       break;
-               }
-           
-               /*
-                * XXX - can't find any reason to sort union-relids as paul did, so
-                * we're leaving it out for now (maybe forever) - jeff & lp
-                *
-                * [maybe so. btw, jeff & lp did the lisp conversion, according to Paul.
-                * -- ay 10/94.]
-                */
-               union_plans = plan_union_query(union_relids, rt_index, rt_entry,
-                                              parse, flag, &union_rt_entries);
-   
-               return (make_append(union_plans,
-                                   NULL,
-                                   rt_index,
-                                   union_rt_entries,
-                                   ((Plan *) lfirst(union_plans))->targetlist));
-               break;
-           }           
-       case UNION_FLAG:
-           {
-               List *ulist, *hold_union, *union_plans, *union_rts;
-
-               hold_union = parse->unionClause;
-               parse->unionClause = NULL; /* prevent looping */
+   List       *rangetable = parse->rtable;
+   RangeTblEntry *rt_entry = rt_fetch(rt_index, rangetable);
+   List       *union_rt_entries = NIL;
+   List       *union_relids = NIL;
 
-               union_plans = lcons(planner(parse), NIL);
-               union_rts = lcons(parse->rtable, NIL);
-               foreach(ulist, hold_union)
-               {
-                   Query *u = lfirst(ulist);
-
-                   union_plans = lappend(union_plans, planner(u));
-                   union_rts = lappend(union_rts, u->rtable);
-               }
-
-               /* We have already split UNION and UNION ALL */
-               if (!((Query *)lfirst(hold_union))->unionall)
-               {
-                   parse->uniqueFlag = "*";
-                   parse->sortClause = transformSortClause(NULL, NIL,
-                       ((Plan *)lfirst(union_plans))->targetlist, "*");
-               }
-               else
-               {
-               /* needed so we don't take the flag from the first query */
-                   parse->uniqueFlag = NULL;
-                   parse->sortClause = NIL;
-               }
-
-               parse->havingQual = NULL;
-               parse->qry_numAgg = 0;
-               parse->qry_aggs = NULL;
+   union_relids =
+       find_all_inheritors(lconsi(rt_entry->relid,
+                                  NIL),
+                           NIL);
+   /*
+    * Remove the flag for this relation, since we're about to handle it
+    * (do it before recursing!). XXX destructive parse tree change
+    */
+   rt_fetch(rt_index, rangetable)->inh = false;
 
-               return (make_append(union_plans, union_rts,
-                                   rt_index /* is 0, none */, NULL,
-                           ((Plan *) lfirst(union_plans))->targetlist));
-           }
-           break;
+   union_plans = plan_inherit_query(union_relids, rt_index, rt_entry,
+                                  parse, &union_rt_entries);
 
-#ifdef NOT_USED
-       case VERSION_FLAG:
-           union_relids = VersionGetParents(rt_entry->relid);
-           break;
-#endif
-       default:
-           /* do nothing */
-           break;
-   }
-   return NULL;
-   
-   return ((Append*)NULL);     /* to make gcc happy */
+   return (make_append(union_plans,
+                       NULL,
+                       rt_index,
+                       union_rt_entries,
+                       ((Plan *) lfirst(union_plans))->targetlist));
 }
 
-
 /*
- * plan-union-query--
+ * plan-inherit-query--
  *   Returns a list of plans for 'relids' and a list of range table entries
  *   in union_rtentries.
  */
 static List *
-plan_union_query(List *relids,
+plan_inherit_query(List *relids,
                 Index rt_index,
                 RangeTblEntry *rt_entry,
                 Query *root,
-                UnionFlag flag,
                 List **union_rtentriesPtr)
 {
    List       *i;
@@ -291,6 +289,74 @@ plan_union_query(List *relids,
    return (union_plans);
 }
 
+/*
+ * find-all-inheritors -
+ *     Returns a list of relids corresponding to relations that inherit
+ *     attributes from any relations listed in either of the argument relid
+ *     lists.
+ */
+List      *
+find_all_inheritors(List *unexamined_relids,
+                   List *examined_relids)
+{
+   List       *new_inheritors = NIL;
+   List       *new_examined_relids = NIL;
+   List       *new_unexamined_relids = NIL;
+
+   /*
+    * Find all relations which inherit from members of
+    * 'unexamined-relids' and store them in 'new-inheritors'.
+    */
+   List       *rels = NIL;
+   List       *newrels = NIL;
+
+   foreach(rels, unexamined_relids)
+   {
+       newrels = (List *) LispUnioni(find_inheritance_children(lfirsti(rels)),
+                                     newrels);
+   }
+   new_inheritors = newrels;
+
+   new_examined_relids = (List *) LispUnioni(examined_relids, unexamined_relids);
+   new_unexamined_relids = set_differencei(new_inheritors,
+                                           new_examined_relids);
+
+   if (new_unexamined_relids == NULL)
+   {
+       return (new_examined_relids);
+   }
+   else
+   {
+       return (find_all_inheritors(new_unexamined_relids,
+                                   new_examined_relids));
+   }
+}
+
+/*
+ * first-inherit-rt-entry -
+ *     Given a rangetable, find the first rangetable entry that represents
+ *     the appropriate special case.
+ *
+ *     Returns a rangetable index.,  Returns -1 if no matches
+ */
+int
+first_inherit_rt_entry(List *rangetable)
+{
+   int         count = 0;
+   List       *temp = NIL;
+
+   foreach(temp, rangetable)
+   {
+       RangeTblEntry *rt_entry = lfirst(temp);
+
+       if (rt_entry->inh)
+           return count + 1;
+       count++;
+   }
+
+   return -1;
+}
+
 /*
  * new-rangetable-entry -
  *     Replaces the name and relid of 'old-entry' with the values for
@@ -367,8 +433,6 @@ fix_parsetree_attnums_nodes(Index rt_index,
                Oid         old_typeid,
                            new_typeid;
 
-/*         old_typeid = RelationIdGetTypeId(old_relid);*/
-/*         new_typeid = RelationIdGetTypeId(new_relid);*/
                old_typeid = old_relid;
                new_typeid = new_relid;
 
index edc9ae2be6b71a988f739a30f9b0f2eec5b6055a..0d1d3dcb248dc7168aa85ffed8739879b8e8c713 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.57 1997/12/27 06:41:26 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.58 1997/12/29 01:12:55 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -840,77 +840,10 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
        finalizeAggregates(pstate, qry);
 
    qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
-   
-   if (stmt->unionClause)
-   {
-       List *ulist = NIL;
-       QueryTreeList *qlist;
-       int i, last_union = -1;
-       bool union_all_found = false, union_found = false;
-
-       qlist = parse_analyze(stmt->unionClause);
-
-       /*
-        *  Do we need to split up our unions because we have UNION
-        *  and UNION ALL?
-        */
-       for (i=0; i < qlist->len; i++)
-       {
-           if (qlist->qtrees[i]->unionall)
-               union_all_found = true;
-           else
-           {
-               union_found = true;
-               last_union = i;
-           }
-       }
+   qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
 
-       /*  A trailing UNION negates the affect of earlier UNION ALLs */
-       if (!union_all_found ||
-           !union_found ||
-           /* last entry is a UNION */
-           !qlist->qtrees[qlist->len-1]->unionall)
-       {
-           for (i=0; i < qlist->len; i++)
-               ulist = lappend(ulist, qlist->qtrees[i]);
-           qry->unionClause = ulist;
-       }
-       else
-       {
-           List *union_list = NIL;
-           Query *hold_qry;
-
-           /*
-            *  We have mixed unions and non-unions, so we concentrate on
-            *  the last UNION in the list.
-            */
-           for (i=0; i <= last_union; i++)
-           {
-               qlist->qtrees[i]->unionall = false; /*make queries consistent*/
-               union_list = lappend(union_list, qlist->qtrees[i]);
-           }
-
-           /*
-            *  Make the first UNION ALL after the last UNION our new
-            *  top query
-            */
-           hold_qry = qry;
-           qry = qlist->qtrees[last_union + 1];
-           qry->unionClause = lcons(hold_qry, NIL); /* UNION queries */
-           hold_qry->unionall = true;  /* UNION ALL this into other queries */
-           hold_qry->unionClause = union_list;
-           
-           /*
-            *  The first UNION ALL after the last UNION is our anchor,
-            *  we skip it.
-            */
-           for (i=last_union + 2; i < qlist->len; i++)
-               /* all queries are UNION ALL */
-               qry->unionClause = lappend(qry->unionClause, qlist->qtrees[i]);
-       }
-   }
-   else
-       qry->unionClause = NULL;
+   if (qry->unionClause && stmt->sortClause)
+       elog(WARN, "You can not use ORDER BY with UNION", NULL);
 
    return (Query *) qry;
 }
index ad40222ba6d77bf6782c5fcf6b2d007f24aec65b..5368dc2e2698ee530c97107fdb1ac4089d2c6fd2 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.3 1997/11/26 03:42:39 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.4 1997/12/29 01:12:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "postgres.h"
 #include "access/heapam.h"
 #include "catalog/pg_type.h"
+#include "parser/analyze.h"
 #include "parser/parse_clause.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_node.h"
@@ -371,3 +372,28 @@ transformSortClause(ParseState *pstate,
 
    return sortlist;
 }
+
+/*
+ * transformUnionClause -
+ *   transform a Union clause
+ *
+ */
+List *
+transformUnionClause(List *unionClause, List *targetlist)
+{
+   List *union_list = NIL;
+   QueryTreeList *qlist;
+   int i;
+TargetEntry
+   if (unionClause)
+   {
+       qlist = parse_analyze(unionClause);
+
+       for (i=0; i < qlist->len; i++)
+           union_list = lappend(union_list, qlist->qtrees[i]);
+       /* we need to check return types are consistent here */
+       return union_list;
+   }
+   else
+       return NIL;
+}
index 27f820d26e24064eb369a21a9de87e9cc9d4e42e..397e6979ad6b2a54b03be1284efeaed40cefb5ad 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: psqlHelp.h,v 1.34 1997/12/04 00:27:37 scrappy Exp $
+ * $Id: psqlHelp.h,v 1.35 1997/12/29 01:13:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -179,7 +179,12 @@ static struct _helpStruct QL_HELP[] = {
    "rollback [transaction|work]"},
    {"select",
        "retrieve tuples",
-   "select [distinct on  [as ], ...  [as ]\n\t[into table ] [from ]\n\t[where ]\n\t[order by \n\t\t[using ],.. [[using ] | ASC | DESC]];"},
+   "select [distinct on  [as ], ...  [as ]\n\
+\t[into table ]\n\
+\t[from ]\n\
+\t[where ]\n\
+\t[order by  [ASC | DESC] [using ], ...  ]\n\
+\t[union [all] select ...];"},
    {"set",
        "set run-time environment",
    "set DateStyle to {'ISO' | 'SQL' | 'Postgres' | 'European' | 'US' | 'NonEuropean'}\nset GEQO to {'ON[=#]' | 'OFF'}\nset R_PLANS to {'ON' | 'OFF'}"},
index 7b22bb5f39e25a260b342fc500b5dd3425daf4f0..91e6d189931d58be0e57d172f39b166023abbaaf 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: prep.h,v 1.10 1997/12/24 06:06:58 momjian Exp $
+ * $Id: prep.h,v 1.11 1997/12/29 01:13:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,18 +27,10 @@ extern List *cnfify(Expr *qual, bool removeAndFlag);
 extern List *preprocess_targetlist(List *tlist, int command_type,
                      Index result_relation, List *range_table);
 
-/*
- * prototypes for prepunion.h
- */
-typedef enum UnionFlag
-{
-   INHERITS_FLAG, UNION_FLAG, VERSION_FLAG
-} UnionFlag;
-
 extern List *find_all_inheritors(List *unexamined_relids,
                    List *examined_relids);
-extern int first_matching_rt_entry(List *rangetable, UnionFlag flag);
-extern Append *plan_union_queries(Index rt_index, Query *parse,
-                  UnionFlag flag);
+extern int first_inherit_rt_entry(List *rangetable);
+extern Append *plan_union_queries(Query *parse);
+extern Append *plan_inherit_queries(Query *parse, Index rt_index);
 
 #endif                         /* PREP_H */
index 272bbc17b54e667a5476effb5823b035baa9194c..d402faeb11af9ca14d20322ed51befe1303a15ad 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_clause.h,v 1.3 1997/11/26 03:43:09 momjian Exp $
+ * $Id: parse_clause.h,v 1.4 1997/12/29 01:13:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@ extern List *transformGroupClause(ParseState *pstate, List *grouplist,
 extern List *transformSortClause(ParseState *pstate,
                    List *orderlist, List *targetlist,
                    char *uniqueFlag);
+extern List *transformUnionClause(List *unionClause, List *targetlist);
 
 #endif                         /* PARSE_CLAUSE_H */
 
index c4ac5b8eec96f7ec4d06aa0adc03cd8cdcb5c1a7..cc36b2b5ac592a81b1675304085229070e0ff870 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/select.l,v 1.2 1996/12/11 00:28:09 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/select.l,v 1.3 1997/12/29 01:13:37 momjian Exp $
 .TH SELECT SQL 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 select \(em retrieve instances from a class
@@ -12,9 +12,10 @@ select \(em retrieve instances from a class
     [\fBinto\fR \fBtable\fR classname]
     [\fBfrom\fR from-list]
     [\fBwhere\fR where-clause]    
-    [\fBgroup by\fR attr_name1 {, attr_name-i....}
-    [\fBorder by\fR attr_name1
-   [\fBusing op1\fR] {, attr_namei [\fBusing opi\fR] }
+    [\fBgroup by\fR attr_name1 {, attr_name-i....}]
+    [\fBorder by\fR attr_name1 [\fBasc\fR | \fBdesc\fR] [\fBusing op1\fR] {, attr_namei...}]
+[\fBunion {all} select\fR ...]
+
 .fi
 .SH DESCRIPTION
 .BR Select