mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
UNION work for UNION ALL and other union stuff.
This commit is contained in:
parent
2730c4a45c
commit
4ce24c8aa9
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.9 1997/09/08 21:43:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.10 1997/12/27 06:40:50 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,7 @@
|
|||||||
* nil nil ... ... ...
|
* nil nil ... ... ...
|
||||||
* subplans
|
* subplans
|
||||||
*
|
*
|
||||||
* Append nodes are currently used to support inheritance
|
* Append nodes are currently used to unions, and to support inheritance
|
||||||
* queries, where several relations need to be scanned.
|
* queries, where several relations need to be scanned.
|
||||||
* For example, in our standard person/student/employee/student-emp
|
* For example, in our standard person/student/employee/student-emp
|
||||||
* example, where student and employee inherit from person
|
* example, where student and employee inherit from person
|
||||||
@ -85,6 +85,7 @@ exec_append_initialize_next(Append *node)
|
|||||||
|
|
||||||
int whichplan;
|
int whichplan;
|
||||||
int nplans;
|
int nplans;
|
||||||
|
List *rts;
|
||||||
List *rtentries;
|
List *rtentries;
|
||||||
ResTarget *rtentry;
|
ResTarget *rtentry;
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ exec_append_initialize_next(Append *node)
|
|||||||
|
|
||||||
whichplan = unionstate->as_whichplan;
|
whichplan = unionstate->as_whichplan;
|
||||||
nplans = unionstate->as_nplans;
|
nplans = unionstate->as_nplans;
|
||||||
|
rts = node->unionrts;
|
||||||
rtentries = node->unionrtentries;
|
rtentries = node->unionrtentries;
|
||||||
|
|
||||||
if (whichplan < 0)
|
if (whichplan < 0)
|
||||||
@ -140,27 +142,28 @@ exec_append_initialize_next(Append *node)
|
|||||||
if (node->unionrelid > 0)
|
if (node->unionrelid > 0)
|
||||||
{
|
{
|
||||||
rtentry = nth(whichplan, rtentries);
|
rtentry = nth(whichplan, rtentries);
|
||||||
if (rtentry == NULL)
|
Assert(rtentry != NULL);
|
||||||
elog(DEBUG, "exec_append_initialize_next: rtentry is nil");
|
|
||||||
|
|
||||||
unionrelid = node->unionrelid;
|
unionrelid = node->unionrelid;
|
||||||
|
|
||||||
rt_store(unionrelid, rangeTable, rtentry);
|
rt_store(unionrelid, rangeTable, rtentry);
|
||||||
|
|
||||||
if (unionstate->as_junkFilter_list)
|
|
||||||
{
|
|
||||||
estate->es_junkFilter =
|
|
||||||
(JunkFilter *) nth(whichplan,
|
|
||||||
unionstate->as_junkFilter_list);
|
|
||||||
}
|
|
||||||
if (unionstate->as_result_relation_info_list)
|
|
||||||
{
|
|
||||||
estate->es_result_relation_info =
|
|
||||||
(RelationInfo *) nth(whichplan,
|
|
||||||
unionstate->as_result_relation_info_list);
|
|
||||||
}
|
|
||||||
result_slot->ttc_whichplan = whichplan;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
estate->es_range_table = nth(whichplan, rts);
|
||||||
|
|
||||||
|
if (unionstate->as_junkFilter_list)
|
||||||
|
{
|
||||||
|
estate->es_junkFilter =
|
||||||
|
(JunkFilter *) nth(whichplan,
|
||||||
|
unionstate->as_junkFilter_list);
|
||||||
|
}
|
||||||
|
if (unionstate->as_result_relation_info_list)
|
||||||
|
{
|
||||||
|
estate->es_result_relation_info =
|
||||||
|
(RelationInfo *) nth(whichplan,
|
||||||
|
unionstate->as_result_relation_info_list);
|
||||||
|
}
|
||||||
|
result_slot->ttc_whichplan = whichplan;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -439,8 +442,7 @@ ExecProcAppend(Append *node)
|
|||||||
if (exec_append_initialize_next(node))
|
if (exec_append_initialize_next(node))
|
||||||
{
|
{
|
||||||
ExecSetSlotDescriptorIsNew(result_slot, true);
|
ExecSetSlotDescriptorIsNew(result_slot, true);
|
||||||
return
|
return ExecProcAppend(node);
|
||||||
ExecProcAppend(node);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return ExecClearTuple(result_slot);
|
return ExecClearTuple(result_slot);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.13 1997/12/23 19:50:54 thomas Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.14 1997/12/27 06:40:54 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||||
@ -194,7 +194,7 @@ _outQuery(StringInfo str, Query *node)
|
|||||||
sprintf(buf, " :qual ");
|
sprintf(buf, " :qual ");
|
||||||
appendStringInfo(str, buf);
|
appendStringInfo(str, buf);
|
||||||
_outNode(str, node->qual);
|
_outNode(str, node->qual);
|
||||||
|
/* how are we handling aggregates, sort, and group by? bjm 1997/12/26 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.11 1997/12/18 12:53:59 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.12 1997/12/27 06:40:59 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||||
@ -119,6 +119,7 @@ _readQuery()
|
|||||||
|
|
||||||
token = lsptok(NULL, &length); /* skip :qual */
|
token = lsptok(NULL, &length); /* skip :qual */
|
||||||
local_node->qual = nodeRead(true);
|
local_node->qual = nodeRead(true);
|
||||||
|
/* how are we handling aggregates, sort, and group by? bjm 1997/12/26 */
|
||||||
|
|
||||||
return (local_node);
|
return (local_node);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.16 1997/12/24 06:06:01 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.17 1997/12/27 06:41:07 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -72,8 +72,6 @@ planner(Query *parse)
|
|||||||
{
|
{
|
||||||
List *tlist = parse->targetList;
|
List *tlist = parse->targetList;
|
||||||
List *rangetable = parse->rtable;
|
List *rangetable = parse->rtable;
|
||||||
char *uniqueflag = parse->uniqueFlag;
|
|
||||||
List *sortclause = parse->sortClause;
|
|
||||||
|
|
||||||
Plan *result_plan = (Plan *) NULL;
|
Plan *result_plan = (Plan *) NULL;
|
||||||
|
|
||||||
@ -83,7 +81,7 @@ planner(Query *parse)
|
|||||||
|
|
||||||
if (parse->unionClause)
|
if (parse->unionClause)
|
||||||
{
|
{
|
||||||
result_plan = (Plan *) plan_union_queries(0, /* none */
|
result_plan = (Plan *) plan_union_queries( 0, /* none */
|
||||||
parse,
|
parse,
|
||||||
UNION_FLAG);
|
UNION_FLAG);
|
||||||
/* XXX do we need to do this? bjm 12/19/97 */
|
/* XXX do we need to do this? bjm 12/19/97 */
|
||||||
@ -173,16 +171,16 @@ planner(Query *parse)
|
|||||||
* the optimization step later.
|
* the optimization step later.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (uniqueflag)
|
if (parse->uniqueFlag)
|
||||||
{
|
{
|
||||||
Plan *sortplan = make_sortplan(tlist, sortclause, result_plan);
|
Plan *sortplan = make_sortplan(tlist, parse->sortClause, result_plan);
|
||||||
|
|
||||||
return ((Plan *) make_unique(tlist, sortplan, uniqueflag));
|
return ((Plan *) make_unique(tlist, sortplan, parse->uniqueFlag));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sortclause)
|
if (parse->sortClause)
|
||||||
return (make_sortplan(tlist, sortclause, result_plan));
|
return (make_sortplan(tlist, parse->sortClause, result_plan));
|
||||||
else
|
else
|
||||||
return ((Plan *) result_plan);
|
return ((Plan *) result_plan);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.14 1997/12/26 06:02:26 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.15 1997/12/27 06:41:17 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#include "nodes/relation.h"
|
#include "nodes/relation.h"
|
||||||
|
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
|
#include "parser/parse_clause.h"
|
||||||
|
|
||||||
#include "utils/elog.h"
|
#include "utils/elog.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
@ -42,7 +43,7 @@ static Query *subst_rangetable(Query *root, Index index,
|
|||||||
RangeTblEntry *new_entry);
|
RangeTblEntry *new_entry);
|
||||||
static void fix_parsetree_attnums(Index rt_index, Oid old_relid,
|
static void fix_parsetree_attnums(Index rt_index, Oid old_relid,
|
||||||
Oid new_relid, Query *parsetree);
|
Oid new_relid, Query *parsetree);
|
||||||
static Append *make_append(List *unionplans, Index rt_index,
|
static Append *make_append(List *unionplans, List *unionrts, Index rt_index,
|
||||||
List *union_rt_entries, List *tlist);
|
List *union_rt_entries, List *tlist);
|
||||||
|
|
||||||
|
|
||||||
@ -136,73 +137,102 @@ plan_union_queries(Index rt_index,
|
|||||||
Query *parse,
|
Query *parse,
|
||||||
UnionFlag flag)
|
UnionFlag flag)
|
||||||
{
|
{
|
||||||
List *rangetable = parse->rtable;
|
|
||||||
RangeTblEntry *rt_entry = rt_fetch(rt_index, rangetable);
|
|
||||||
List *union_relids = NIL;
|
|
||||||
List *union_plans = NIL;
|
List *union_plans = NIL;
|
||||||
List *union_rt_entries = NIL;
|
|
||||||
|
|
||||||
switch (flag)
|
switch (flag)
|
||||||
{
|
{
|
||||||
case INHERITS_FLAG:
|
case INHERITS_FLAG:
|
||||||
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:
|
List *rangetable = parse->rtable;
|
||||||
rt_fetch(rt_index, rangetable)->inh = false;
|
RangeTblEntry *rt_entry = rt_fetch(rt_index, rangetable);
|
||||||
break;
|
List *union_rt_entries = NIL;
|
||||||
default:
|
List *union_relids = NIL;
|
||||||
break;
|
|
||||||
}
|
union_relids =
|
||||||
|
find_all_inheritors(lconsi(rt_entry->relid,
|
||||||
/*
|
NIL),
|
||||||
* XXX - can't find any reason to sort union-relids as paul did, so
|
NIL);
|
||||||
* we're leaving it out for now (maybe forever) - jeff & lp
|
/*
|
||||||
*
|
* Remove the flag for this relation, since we're about to handle it
|
||||||
* [maybe so. btw, jeff & lp did the lisp conversion, according to Paul.
|
* (do it before recursing!). XXX destructive parse tree change
|
||||||
* -- ay 10/94.]
|
*/
|
||||||
*/
|
switch (flag)
|
||||||
union_plans = plan_union_query(union_relids, rt_index, rt_entry,
|
{
|
||||||
parse, flag, &union_rt_entries);
|
case INHERITS_FLAG:
|
||||||
|
rt_fetch(rt_index, rangetable)->inh = false;
|
||||||
return (make_append(union_plans,
|
break;
|
||||||
rt_index,
|
default:
|
||||||
union_rt_entries,
|
break;
|
||||||
((Plan *) lfirst(union_plans))->targetlist));
|
}
|
||||||
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:
|
case UNION_FLAG:
|
||||||
{
|
{
|
||||||
List *ulist, *hold_union, *union_plans;
|
List *ulist, *hold_union, *union_plans, *union_rts;
|
||||||
|
|
||||||
hold_union = parse->unionClause;
|
hold_union = parse->unionClause;
|
||||||
parse->unionClause = NULL; /* prevent looping */
|
parse->unionClause = NULL; /* prevent looping */
|
||||||
|
|
||||||
union_plans = lcons(planner(parse), NIL);
|
union_plans = lcons(planner(parse), NIL);
|
||||||
|
union_rts = lcons(parse->rtable, NIL);
|
||||||
foreach(ulist, hold_union)
|
foreach(ulist, hold_union)
|
||||||
union_plans = lappend(union_plans, planner(lfirst(ulist)));
|
{
|
||||||
return (make_append(union_plans,
|
Query *u = lfirst(ulist);
|
||||||
rt_index, rangetable,
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return (make_append(union_plans, union_rts,
|
||||||
|
rt_index /* is 0, none */, NULL,
|
||||||
((Plan *) lfirst(union_plans))->targetlist));
|
((Plan *) lfirst(union_plans))->targetlist));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef NOT_USED
|
||||||
case VERSION_FLAG:
|
case VERSION_FLAG:
|
||||||
union_relids = VersionGetParents(rt_entry->relid);
|
union_relids = VersionGetParents(rt_entry->relid);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return ((Append*)NULL); /* to make gcc happy */
|
return ((Append*)NULL); /* to make gcc happy */
|
||||||
}
|
}
|
||||||
@ -392,6 +422,7 @@ fix_parsetree_attnums(Index rt_index,
|
|||||||
|
|
||||||
static Append *
|
static Append *
|
||||||
make_append(List *unionplans,
|
make_append(List *unionplans,
|
||||||
|
List *unionrts,
|
||||||
Index rt_index,
|
Index rt_index,
|
||||||
List *union_rt_entries,
|
List *union_rt_entries,
|
||||||
List *tlist)
|
List *tlist)
|
||||||
@ -399,6 +430,7 @@ make_append(List *unionplans,
|
|||||||
Append *node = makeNode(Append);
|
Append *node = makeNode(Append);
|
||||||
|
|
||||||
node->unionplans = unionplans;
|
node->unionplans = unionplans;
|
||||||
|
node->unionrts = unionrts;
|
||||||
node->unionrelid = rt_index;
|
node->unionrelid = rt_index;
|
||||||
node->unionrtentries = union_rt_entries;
|
node->unionrtentries = union_rt_entries;
|
||||||
node->plan.cost = 0.0;
|
node->plan.cost = 0.0;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.56 1997/12/24 06:06:18 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.57 1997/12/27 06:41:26 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -839,16 +839,75 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
|
|||||||
if (pstate->p_numAgg > 0)
|
if (pstate->p_numAgg > 0)
|
||||||
finalizeAggregates(pstate, qry);
|
finalizeAggregates(pstate, qry);
|
||||||
|
|
||||||
|
qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
|
||||||
|
|
||||||
if (stmt->unionClause)
|
if (stmt->unionClause)
|
||||||
{
|
{
|
||||||
List *ulist = NIL;
|
List *ulist = NIL;
|
||||||
QueryTreeList *qlist;
|
QueryTreeList *qlist;
|
||||||
int i;
|
int i, last_union = -1;
|
||||||
|
bool union_all_found = false, union_found = false;
|
||||||
|
|
||||||
qlist = parse_analyze(stmt->unionClause);
|
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++)
|
for (i=0; i < qlist->len; i++)
|
||||||
ulist = lappend(ulist, qlist->qtrees[i]);
|
{
|
||||||
qry->unionClause = ulist;
|
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 (!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
|
else
|
||||||
qry->unionClause = NULL;
|
qry->unionClause = NULL;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parsenodes.h,v 1.39 1997/12/24 06:06:53 momjian Exp $
|
* $Id: parsenodes.h,v 1.40 1997/12/27 06:41:39 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -43,7 +43,8 @@ typedef struct Query
|
|||||||
char *into; /* portal (cursor) name */
|
char *into; /* portal (cursor) name */
|
||||||
bool isPortal; /* is this a retrieve into portal? */
|
bool isPortal; /* is this a retrieve into portal? */
|
||||||
bool isBinary; /* binary portal? */
|
bool isBinary; /* binary portal? */
|
||||||
|
bool unionall; /* union without unique sort */
|
||||||
|
|
||||||
char *uniqueFlag; /* NULL, '*', or Unique attribute name */
|
char *uniqueFlag; /* NULL, '*', or Unique attribute name */
|
||||||
List *sortClause; /* a list of SortClause's */
|
List *sortClause; /* a list of SortClause's */
|
||||||
|
|
||||||
@ -636,7 +637,7 @@ typedef struct RetrieveStmt
|
|||||||
Node *havingClause; /* having conditional-expression */
|
Node *havingClause; /* having conditional-expression */
|
||||||
List *unionClause; /* union subselect parameters */
|
List *unionClause; /* union subselect parameters */
|
||||||
List *sortClause; /* sort clause (a list of SortGroupBy's) */
|
List *sortClause; /* sort clause (a list of SortGroupBy's) */
|
||||||
int unionall; /* union without unique sort */
|
bool unionall; /* union without unique sort */
|
||||||
} RetrieveStmt;
|
} RetrieveStmt;
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: plannodes.h,v 1.11 1997/12/18 12:54:37 momjian Exp $
|
* $Id: plannodes.h,v 1.12 1997/12/27 06:41:41 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -119,6 +119,7 @@ typedef struct Append
|
|||||||
{
|
{
|
||||||
Plan plan;
|
Plan plan;
|
||||||
List *unionplans;
|
List *unionplans;
|
||||||
|
List *unionrts;
|
||||||
Index unionrelid;
|
Index unionrelid;
|
||||||
List *unionrtentries;
|
List *unionrtentries;
|
||||||
AppendState *unionstate;
|
AppendState *unionstate;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user