Commit a01b085c authored by Bruce Momjian's avatar Bruce Momjian

Cleanup of UNION ALL fix. Manual page updates.

parent 4ce24c8a
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -76,14 +76,12 @@ planner(Query *parse)
Plan *result_plan = (Plan *) NULL; Plan *result_plan = (Plan *) NULL;
List *primary_qual; List *primary_qual;
int rt_index; Index rt_index;
if (parse->unionClause) if (parse->unionClause)
{ {
result_plan = (Plan *) plan_union_queries( 0, /* none */ result_plan = (Plan *) plan_union_queries(parse);
parse,
UNION_FLAG);
/* XXX do we need to do this? bjm 12/19/97 */ /* XXX do we need to do this? bjm 12/19/97 */
tlist = preprocess_targetlist(tlist, tlist = preprocess_targetlist(tlist,
parse->commandType, parse->commandType,
...@@ -91,11 +89,9 @@ planner(Query *parse) ...@@ -91,11 +89,9 @@ planner(Query *parse)
parse->rtable); parse->rtable);
} }
else if ((rt_index = 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, result_plan = (Plan *) plan_inherit_queries(parse, rt_index);
parse,
INHERITS_FLAG);
/* XXX do we need to do this? bjm 12/19/97 */ /* XXX do we need to do this? bjm 12/19/97 */
tlist = preprocess_targetlist(tlist, tlist = preprocess_targetlist(tlist,
parse->commandType, parse->commandType,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -34,8 +34,8 @@
#include "optimizer/planner.h" #include "optimizer/planner.h"
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
static List *plan_union_query(List *relids, Index rt_index, static List *plan_inherit_query(List *relids, Index rt_index,
RangeTblEntry *rt_entry, Query *parse, UnionFlag flag, RangeTblEntry *rt_entry, Query *parse,
List **union_rtentriesPtr); List **union_rtentriesPtr);
static RangeTblEntry *new_rangetable_entry(Oid new_relid, static RangeTblEntry *new_rangetable_entry(Oid new_relid,
RangeTblEntry *old_entry); RangeTblEntry *old_entry);
...@@ -48,83 +48,158 @@ static Append *make_append(List *unionplans, List *unionrts, Index rt_index, ...@@ -48,83 +48,158 @@ static Append *make_append(List *unionplans, List *unionrts, Index rt_index,
/* /*
* find-all-inheritors - * plan-union-queries--
* Returns a list of relids corresponding to relations that inherit *
* attributes from any relations listed in either of the argument relid * Plans the queries for a given UNION.
* lists. *
* Returns a list containing a list of plans and a list of rangetables
*/ */
List * Append *
find_all_inheritors(List *unexamined_relids, plan_union_queries(Query *parse)
List *examined_relids)
{ {
List *new_inheritors = NIL; List *union_plans = NIL, *ulist, *unionall_queries, *union_rts,
List *new_examined_relids = NIL; *last_union = NIL;
List *new_unexamined_relids = NIL; bool union_all_found = false, union_found = false,
last_unionall_flag = false;
/* /*
* Find all relations which inherit from members of * Do we need to split up our unions because we have UNION
* 'unexamined-relids' and store them in 'new-inheritors'. * 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)), Query *union_query = lfirst(ulist);
newrels);
}
new_inheritors = newrels;
new_examined_relids = (List *) LispUnioni(examined_relids, unexamined_relids); if (union_query->unionall)
new_unexamined_relids = set_differencei(new_inheritors, union_all_found = true;
new_examined_relids); 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 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.
*/
/* /* save off everthing past the last UNION */
* first-matching-rt-entry - unionall_queries = lnext(last_union);
* 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;
foreach(temp, rangetable) /* clip off the list to remove the trailing UNION ALLs */
{ lnext(last_union) = NIL;
RangeTblEntry *rt_entry = lfirst(temp);
/*
* 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: Query *unionall_query = lfirst(ulist);
if (rt_entry->inh)
return count + 1; union_plans = lappend(union_plans, planner(unionall_query));
break; union_rts = lappend(union_rts, unionall_query->rtable);
default:
break;
} }
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. * Plans the queries for a given parent relation.
* *
...@@ -133,122 +208,45 @@ first_matching_rt_entry(List *rangetable, UnionFlag flag) ...@@ -133,122 +208,45 @@ first_matching_rt_entry(List *rangetable, UnionFlag flag)
* XXX - what exactly does this mean, look for make_append * XXX - what exactly does this mean, look for make_append
*/ */
Append * Append *
plan_union_queries(Index rt_index, plan_inherit_queries(Query *parse, Index rt_index)
Query *parse,
UnionFlag flag)
{ {
List *union_plans = NIL; List *union_plans = NIL;
switch (flag) List *rangetable = parse->rtable;
{ RangeTblEntry *rt_entry = rt_fetch(rt_index, rangetable);
case INHERITS_FLAG: List *union_rt_entries = NIL;
{ List *union_relids = NIL;
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 */
union_plans = lcons(planner(parse), NIL); union_relids =
union_rts = lcons(parse->rtable, NIL); find_all_inheritors(lconsi(rt_entry->relid,
foreach(ulist, hold_union) NIL),
{ NIL);
Query *u = lfirst(ulist); /*
* Remove the flag for this relation, since we're about to handle it
union_plans = lappend(union_plans, planner(u)); * (do it before recursing!). XXX destructive parse tree change
union_rts = lappend(union_rts, u->rtable); */
} rt_fetch(rt_index, rangetable)->inh = false;
/* 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;
return (make_append(union_plans, union_rts, union_plans = plan_inherit_query(union_relids, rt_index, rt_entry,
rt_index /* is 0, none */, NULL, parse, &union_rt_entries);
((Plan *) lfirst(union_plans))->targetlist));
}
break;
#ifdef NOT_USED return (make_append(union_plans,
case VERSION_FLAG: NULL,
union_relids = VersionGetParents(rt_entry->relid); rt_index,
break; union_rt_entries,
#endif ((Plan *) lfirst(union_plans))->targetlist));
default:
/* do nothing */
break;
}
return NULL;
return ((Append*)NULL); /* to make gcc happy */
} }
/* /*
* plan-union-query-- * plan-inherit-query--
* Returns a list of plans for 'relids' and a list of range table entries * Returns a list of plans for 'relids' and a list of range table entries
* in union_rtentries. * in union_rtentries.
*/ */
static List * static List *
plan_union_query(List *relids, plan_inherit_query(List *relids,
Index rt_index, Index rt_index,
RangeTblEntry *rt_entry, RangeTblEntry *rt_entry,
Query *root, Query *root,
UnionFlag flag,
List **union_rtentriesPtr) List **union_rtentriesPtr)
{ {
List *i; List *i;
...@@ -291,6 +289,74 @@ plan_union_query(List *relids, ...@@ -291,6 +289,74 @@ plan_union_query(List *relids,
return (union_plans); 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 - * new-rangetable-entry -
* Replaces the name and relid of 'old-entry' with the values for * Replaces the name and relid of 'old-entry' with the values for
...@@ -367,8 +433,6 @@ fix_parsetree_attnums_nodes(Index rt_index, ...@@ -367,8 +433,6 @@ fix_parsetree_attnums_nodes(Index rt_index,
Oid old_typeid, Oid old_typeid,
new_typeid; new_typeid;
/* old_typeid = RelationIdGetTypeId(old_relid);*/
/* new_typeid = RelationIdGetTypeId(new_relid);*/
old_typeid = old_relid; old_typeid = old_relid;
new_typeid = new_relid; new_typeid = new_relid;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -840,77 +840,10 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
finalizeAggregates(pstate, qry); finalizeAggregates(pstate, qry);
qry->unionall = stmt->unionall; /* in child, so unionClause may be false */ qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
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;
}
}
/* A trailing UNION negates the affect of earlier UNION ALLs */ if (qry->unionClause && stmt->sortClause)
if (!union_all_found || elog(WARN, "You can not use ORDER BY with UNION", NULL);
!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;
return (Query *) qry; return (Query *) qry;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -18,6 +18,7 @@
#include "postgres.h" #include "postgres.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "parser/analyze.h"
#include "parser/parse_clause.h" #include "parser/parse_clause.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "parser/parse_node.h" #include "parser/parse_node.h"
...@@ -371,3 +372,28 @@ transformSortClause(ParseState *pstate, ...@@ -371,3 +372,28 @@ transformSortClause(ParseState *pstate,
return sortlist; 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;
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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[] = { ...@@ -179,7 +179,12 @@ static struct _helpStruct QL_HELP[] = {
"rollback [transaction|work]"}, "rollback [transaction|work]"},
{"select", {"select",
"retrieve tuples", "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",
"set run-time environment", "set run-time environment",
"set DateStyle to {'ISO' | 'SQL' | 'Postgres' | 'European' | 'US' | 'NonEuropean'}\nset GEQO to {'ON[=#]' | 'OFF'}\nset R_PLANS to {'ON' | 'OFF'}"}, "set DateStyle to {'ISO' | 'SQL' | 'Postgres' | 'European' | 'US' | 'NonEuropean'}\nset GEQO to {'ON[=#]' | 'OFF'}\nset R_PLANS to {'ON' | 'OFF'}"},
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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); ...@@ -27,18 +27,10 @@ extern List *cnfify(Expr *qual, bool removeAndFlag);
extern List *preprocess_targetlist(List *tlist, int command_type, extern List *preprocess_targetlist(List *tlist, int command_type,
Index result_relation, List *range_table); 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, extern List *find_all_inheritors(List *unexamined_relids,
List *examined_relids); List *examined_relids);
extern int first_matching_rt_entry(List *rangetable, UnionFlag flag); extern int first_inherit_rt_entry(List *rangetable);
extern Append *plan_union_queries(Index rt_index, Query *parse, extern Append *plan_union_queries(Query *parse);
UnionFlag flag); extern Append *plan_inherit_queries(Query *parse, Index rt_index);
#endif /* PREP_H */ #endif /* PREP_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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, ...@@ -26,6 +26,7 @@ extern List *transformGroupClause(ParseState *pstate, List *grouplist,
extern List *transformSortClause(ParseState *pstate, extern List *transformSortClause(ParseState *pstate,
List *orderlist, List *targetlist, List *orderlist, List *targetlist,
char *uniqueFlag); char *uniqueFlag);
extern List *transformUnionClause(List *unionClause, List *targetlist);
#endif /* PARSE_CLAUSE_H */ #endif /* PARSE_CLAUSE_H */
.\" This is -*-nroff-*- .\" This is -*-nroff-*-
.\" XXX standard disclaimer belongs here.... .\" 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 .TH SELECT SQL 11/05/95 PostgreSQL PostgreSQL
.SH NAME .SH NAME
select \(em retrieve instances from a class select \(em retrieve instances from a class
...@@ -12,9 +12,10 @@ select \(em retrieve instances from a class ...@@ -12,9 +12,10 @@ select \(em retrieve instances from a class
[\fBinto\fR \fBtable\fR classname] [\fBinto\fR \fBtable\fR classname]
[\fBfrom\fR from-list] [\fBfrom\fR from-list]
[\fBwhere\fR where-clause] [\fBwhere\fR where-clause]
[\fBgroup by\fR attr_name1 {, attr_name-i....} [\fBgroup by\fR attr_name1 {, attr_name-i....}]
[\fBorder by\fR attr_name1 [\fBorder by\fR attr_name1 [\fBasc\fR | \fBdesc\fR] [\fBusing op1\fR] {, attr_namei...}]
[\fBusing op1\fR] {, attr_namei [\fBusing opi\fR] } [\fBunion {all} select\fR ...]
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
.BR Select .BR Select
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment