aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1997-12-29 01:13:37 +0000
committerBruce Momjian <bruce@momjian.us>1997-12-29 01:13:37 +0000
commita01b085c78e11838e2058ce032425079ded6edea (patch)
tree575898e9c06c496b39a66260e62242a2b8aee2d1 /src
parent4ce24c8aa98b26f0b070464ce118ef2a1901064e (diff)
downloadpostgresql-a01b085c78e11838e2058ce032425079ded6edea.tar.gz
postgresql-a01b085c78e11838e2058ce032425079ded6edea.zip
Cleanup of UNION ALL fix. Manual page updates.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/planner.c14
-rw-r--r--src/backend/optimizer/prep/prepunion.c382
-rw-r--r--src/backend/parser/analyze.c75
-rw-r--r--src/backend/parser/parse_clause.c28
-rw-r--r--src/bin/psql/psqlHelp.h9
-rw-r--r--src/include/optimizer/prep.h16
-rw-r--r--src/include/parser/parse_clause.h3
-rw-r--r--src/man/select.l9
8 files changed, 277 insertions, 259 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 5c5e80f333d..bb33f49092d 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -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,
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index c0386d2a126..5cb89aac867 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -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;
@@ -292,6 +290,74 @@ plan_union_query(List *relids,
}
/*
+ * 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
* 'new-relid'.
@@ -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;
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index edc9ae2be6b..0d1d3dcb248 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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;
}
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index ad40222ba6d..5368dc2e269 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -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;
+}
diff --git a/src/bin/psql/psqlHelp.h b/src/bin/psql/psqlHelp.h
index 27f820d26e2..397e6979ad6 100644
--- a/src/bin/psql/psqlHelp.h
+++ b/src/bin/psql/psqlHelp.h
@@ -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 <attr>] <expr1> [as <attr1>], ... <exprN> [as <attrN>]\n\t[into table <class_name>] [from <from_list>]\n\t[where <qual>]\n\t[order by <attr1>\n\t\t[using <op1>],..<attrN> [[using <opN>] | ASC | DESC]];"},
+ "select [distinct on <attr>] <expr1> [as <attr1>], ... <exprN> [as <attrN>]\n\
+\t[into table <class_name>]\n\
+\t[from <from_list>]\n\
+\t[where <qual>]\n\
+\t[order by <attr1> [ASC | DESC] [using <op1>], ... <attrN> ]\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'}"},
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
index 7b22bb5f39e..91e6d189931 100644
--- a/src/include/optimizer/prep.h
+++ b/src/include/optimizer/prep.h
@@ -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 */
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
index 272bbc17b54..d402faeb11a 100644
--- a/src/include/parser/parse_clause.h
+++ b/src/include/parser/parse_clause.h
@@ -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 */
diff --git a/src/man/select.l b/src/man/select.l
index c4ac5b8eec9..cc36b2b5ac5 100644
--- a/src/man/select.l
+++ b/src/man/select.l
@@ -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