Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b4210ae

Browse files
committed
Fix problems with grouping/aggregation in queries that use
inheritance ... basically it was completely busted :-(
1 parent 08abe0a commit b4210ae

File tree

5 files changed

+87
-131
lines changed

5 files changed

+87
-131
lines changed

src/backend/optimizer/plan/planner.c

+27-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.54 1999/05/25 16:09:37 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.55 1999/06/06 17:38:10 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -122,14 +122,36 @@ union_planner(Query *parse)
122122
}
123123
else if ((rt_index = first_inherit_rt_entry(rangetable)) != -1)
124124
{
125-
if (parse->rowMark != NULL)
126-
elog(ERROR, "SELECT FOR UPDATE is not supported for inherit queries");
127-
result_plan = (Plan *) plan_inherit_queries(parse, rt_index);
128-
/* XXX do we need to do this? bjm 12/19/97 */
125+
List *sub_tlist;
126+
127+
/*
128+
* Generate appropriate target list for subplan; may be different
129+
* from tlist if grouping or aggregation is needed.
130+
*/
131+
sub_tlist = make_subplanTargetList(parse, tlist, &groupColIdx);
132+
133+
/*
134+
* Recursively plan the subqueries needed for inheritance
135+
*/
136+
result_plan = (Plan *) plan_inherit_queries(parse, sub_tlist,
137+
rt_index);
138+
139+
/*
140+
* Fix up outer target list. NOTE: unlike the case for non-inherited
141+
* query, we pass the unfixed tlist to subplans, which do their own
142+
* fixing. But we still want to fix the outer target list afterwards.
143+
* I *think* this is correct --- doing the fix before recursing is
144+
* definitely wrong, because preprocess_targetlist() will do the
145+
* wrong thing if invoked twice on the same list. Maybe that is a bug?
146+
* tgl 6/6/99
147+
*/
129148
tlist = preprocess_targetlist(tlist,
130149
parse->commandType,
131150
parse->resultRelation,
132151
parse->rtable);
152+
153+
if (parse->rowMark != NULL)
154+
elog(ERROR, "SELECT FOR UPDATE is not supported for inherit queries");
133155
}
134156
else
135157
{

src/backend/optimizer/plan/setrefs.c

+1-90
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.49 1999/05/26 12:55:28 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.50 1999/06/06 17:38:10 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -45,7 +45,6 @@ static Var *replace_joinvar_refs(Var *var,
4545
static List *tlist_noname_references(Oid nonameid, List *tlist);
4646
static bool OperandIsInner(Node *opnd, int inner_relid);
4747
static List *pull_agg_clause(Node *clause);
48-
static Node *del_agg_clause(Node *clause);
4948
static void set_result_tlist_references(Result *resultNode);
5049
static void replace_vars_with_subplan_refs(Node *clause,
5150
Index subvarno,
@@ -874,94 +873,6 @@ pull_agg_clause(Node *clause)
874873
}
875874

876875

877-
/*
878-
* del_agg_tlist_references
879-
* Remove the Agg nodes from the target list
880-
* We do this so inheritance only does aggregates in the upper node
881-
*/
882-
void
883-
del_agg_tlist_references(List *tlist)
884-
{
885-
List *tl;
886-
887-
foreach(tl, tlist)
888-
{
889-
TargetEntry *tle = lfirst(tl);
890-
891-
tle->expr = del_agg_clause(tle->expr);
892-
}
893-
}
894-
895-
static Node *
896-
del_agg_clause(Node *clause)
897-
{
898-
List *t;
899-
900-
if (clause == NULL)
901-
return clause;
902-
903-
if (IsA(clause, Var))
904-
return clause;
905-
else if (is_funcclause(clause))
906-
{
907-
908-
/*
909-
* This is a function. Recursively call this routine for its
910-
* arguments...
911-
*/
912-
foreach(t, ((Expr *) clause)->args)
913-
lfirst(t) = del_agg_clause(lfirst(t));
914-
}
915-
else if (IsA(clause, Aggref))
916-
{
917-
918-
/* here is the real action, to remove the Agg node */
919-
return del_agg_clause(((Aggref *) clause)->target);
920-
921-
}
922-
else if (IsA(clause, ArrayRef))
923-
{
924-
ArrayRef *aref = (ArrayRef *) clause;
925-
926-
/*
927-
* This is an arrayref. Recursively call this routine for its
928-
* expression and its index expression...
929-
*/
930-
foreach(t, aref->refupperindexpr)
931-
lfirst(t) = del_agg_clause(lfirst(t));
932-
foreach(t, aref->reflowerindexpr)
933-
lfirst(t) = del_agg_clause(lfirst(t));
934-
aref->refexpr = del_agg_clause(aref->refexpr);
935-
aref->refassgnexpr = del_agg_clause(aref->refassgnexpr);
936-
}
937-
else if (is_opclause(clause))
938-
{
939-
940-
/*
941-
* This is an operator. Recursively call this routine for both its
942-
* left and right operands
943-
*/
944-
Node *left = (Node *) get_leftop((Expr *) clause);
945-
Node *right = (Node *) get_rightop((Expr *) clause);
946-
947-
if (left != (Node *) NULL)
948-
left = del_agg_clause(left);
949-
if (right != (Node *) NULL)
950-
right = del_agg_clause(right);
951-
}
952-
else if (IsA(clause, Param) ||IsA(clause, Const))
953-
return clause;
954-
else
955-
{
956-
957-
/*
958-
* Ooops! we can not handle that!
959-
*/
960-
elog(ERROR, "del_agg_clause: Can not handle this tlist!\n");
961-
}
962-
return NULL;
963-
}
964-
965876
/*
966877
* check_having_for_ungrouped_vars takes the havingQual and the list of
967878
* GROUP BY clauses and checks for subplans in the havingQual that are being

src/backend/optimizer/prep/prepunion.c

+51-30
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.31 1999/05/25 16:09:47 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.32 1999/06/06 17:38:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -35,7 +35,7 @@
3535
#include "optimizer/planmain.h"
3636

3737
static List *plan_inherit_query(Relids relids, Index rt_index,
38-
RangeTblEntry *rt_entry, Query *parse,
38+
RangeTblEntry *rt_entry, Query *parse, List *tlist,
3939
List **union_rtentriesPtr);
4040
static RangeTblEntry *new_rangetable_entry(Oid new_relid,
4141
RangeTblEntry *old_entry);
@@ -208,32 +208,46 @@ plan_union_queries(Query *parse)
208208
*
209209
* Plans the queries for a given parent relation.
210210
*
211-
* Returns a list containing a list of plans and a list of rangetable
212-
* entries to be inserted into an APPEND node.
213-
* XXX - what exactly does this mean, look for make_append
211+
* Inputs:
212+
* parse = parent parse tree
213+
* tlist = target list for inheritance subqueries (not same as parent's!)
214+
* rt_index = rangetable index for current inheritance item
215+
*
216+
* Returns an APPEND node that forms the result of performing the given
217+
* query for each member relation of the inheritance group.
218+
*
219+
* If grouping, aggregation, or sorting is specified in the parent plan,
220+
* the subplans should not do any of those steps --- we must do those
221+
* operations just once above the APPEND node. The given tlist has been
222+
* modified appropriately to remove group/aggregate expressions, but the
223+
* Query node still has the relevant fields set. We remove them in the
224+
* copies used for subplans (see plan_inherit_query).
225+
*
226+
* NOTE: this can be invoked recursively if more than one inheritance wildcard
227+
* is present. At each level of recursion, the first wildcard remaining in
228+
* the rangetable is expanded.
214229
*/
215230
Append *
216-
plan_inherit_queries(Query *parse, Index rt_index)
231+
plan_inherit_queries(Query *parse, List *tlist, Index rt_index)
217232
{
218-
List *union_plans = NIL;
219-
220233
List *rangetable = parse->rtable;
221234
RangeTblEntry *rt_entry = rt_fetch(rt_index, rangetable);
222235
List *inheritrtable = NIL;
223-
List *union_relids = NIL;
236+
List *union_relids;
237+
List *union_plans;
224238

225239
union_relids = find_all_inheritors(lconsi(rt_entry->relid,
226240
NIL),
227241
NIL);
228242

229243
/*
230244
* Remove the flag for this relation, since we're about to handle it
231-
* (do it before recursing!). XXX destructive parse tree change
245+
* (do it before recursing!). XXX destructive change to parent parse tree
232246
*/
233-
rt_fetch(rt_index, rangetable)->inh = false;
247+
rt_entry->inh = false;
234248

235249
union_plans = plan_inherit_query(union_relids, rt_index, rt_entry,
236-
parse, &inheritrtable);
250+
parse, tlist, &inheritrtable);
237251

238252
return (make_append(union_plans,
239253
NULL,
@@ -252,11 +266,12 @@ plan_inherit_query(Relids relids,
252266
Index rt_index,
253267
RangeTblEntry *rt_entry,
254268
Query *root,
269+
List *tlist,
255270
List **union_rtentriesPtr)
256271
{
257-
List *i;
258272
List *union_plans = NIL;
259273
List *union_rtentries = NIL;
274+
List *i;
260275

261276
foreach(i, relids)
262277
{
@@ -268,19 +283,21 @@ plan_inherit_query(Relids relids,
268283
new_rt_entry);
269284

270285
/*
271-
* reset the uniqueflag and sortclause in parse tree root, so that
272-
* sorting will only be done once after append
286+
* Insert the desired simplified tlist into the subquery
287+
*/
288+
new_root->targetList = copyObject(tlist);
289+
290+
/*
291+
* Clear the sorting and grouping qualifications in the subquery,
292+
* so that sorting will only be done once after append
273293
*/
274294
new_root->uniqueFlag = NULL;
275295
new_root->sortClause = NULL;
276296
new_root->groupClause = NULL;
277297
new_root->havingQual = NULL;
298+
new_root->hasAggs = false; /* shouldn't be any left ... */
278299

279-
if (new_root->hasAggs)
280-
{
281-
new_root->hasAggs = false;
282-
del_agg_tlist_references(new_root->targetList);
283-
}
300+
/* Fix attribute numbers as necessary */
284301
fix_parsetree_attnums(rt_index,
285302
rt_entry->relid,
286303
relid,
@@ -346,7 +363,7 @@ int
346363
first_inherit_rt_entry(List *rangetable)
347364
{
348365
int count = 0;
349-
List *temp = NIL;
366+
List *temp;
350367

351368
foreach(temp, rangetable)
352369
{
@@ -393,8 +410,8 @@ static Query *
393410
subst_rangetable(Query *root, Index index, RangeTblEntry *new_entry)
394411
{
395412
Query *new_root = copyObject(root);
396-
List *temp = NIL;
397-
int i = 0;
413+
List *temp;
414+
int i;
398415

399416
for (temp = new_root->rtable, i = 1; i < index; temp = lnext(temp), i++)
400417
;
@@ -403,6 +420,15 @@ subst_rangetable(Query *root, Index index, RangeTblEntry *new_entry)
403420
return new_root;
404421
}
405422

423+
/*
424+
* Adjust varnos for child tables. This routine makes it possible for
425+
* child tables to have different column positions for the "same" attribute
426+
* as a parent, which helps ALTER TABLE ADD COLUMN. Unfortunately this isn't
427+
* nearly enough to make it work transparently; there are other places where
428+
* things fall down if children and parents don't have the same column numbers
429+
* for inherited attributes. It'd be better to rip this code out and fix
430+
* ALTER TABLE...
431+
*/
406432
static void
407433
fix_parsetree_attnums_nodes(Index rt_index,
408434
Oid old_relid,
@@ -433,16 +459,11 @@ fix_parsetree_attnums_nodes(Index rt_index,
433459
case T_Var:
434460
{
435461
Var *var = (Var *) node;
436-
Oid old_typeid,
437-
new_typeid;
438-
439-
old_typeid = old_relid;
440-
new_typeid = new_relid;
441462

442463
if (var->varno == rt_index && var->varattno != 0)
443464
{
444-
var->varattno = get_attnum(new_typeid,
445-
get_attname(old_typeid, var->varattno));
465+
var->varattno = get_attnum(new_relid,
466+
get_attname(old_relid, var->varattno));
446467
}
447468
}
448469
break;

src/include/optimizer/planmain.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: planmain.h,v 1.27 1999/05/26 12:56:36 momjian Exp $
9+
* $Id: planmain.h,v 1.28 1999/06/06 17:38:09 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -58,7 +58,6 @@ extern void replace_tlist_with_subplan_refs(List *tlist,
5858
Index subvarno,
5959
List *subplanTargetList);
6060
extern bool set_agg_tlist_references(Agg *aggNode);
61-
extern void del_agg_tlist_references(List *tlist);
6261
extern void check_having_for_ungrouped_vars(Node *clause,
6362
List *groupClause,
6463
List *targetList);

src/include/optimizer/prep.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: prep.h,v 1.14 1999/02/13 23:21:52 momjian Exp $
9+
* $Id: prep.h,v 1.15 1999/06/06 17:38:10 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -17,20 +17,23 @@
1717
#include <nodes/parsenodes.h>
1818

1919
/*
20-
* prototypes for prepqual.h
20+
* prototypes for prepqual.c
2121
*/
2222
extern List *cnfify(Expr *qual, bool removeAndFlag);
2323

2424
/*
25-
* prototypes for preptlist.h
25+
* prototypes for preptlist.c
2626
*/
2727
extern List *preprocess_targetlist(List *tlist, int command_type,
2828
Index result_relation, List *range_table);
2929

30+
/*
31+
* prototypes for prepunion.c
32+
*/
3033
extern List *find_all_inheritors(List *unexamined_relids,
3134
List *examined_relids);
3235
extern int first_inherit_rt_entry(List *rangetable);
3336
extern Append *plan_union_queries(Query *parse);
34-
extern Append *plan_inherit_queries(Query *parse, Index rt_index);
37+
extern Append *plan_inherit_queries(Query *parse, List *tlist, Index rt_index);
3538

3639
#endif /* PREP_H */

0 commit comments

Comments
 (0)