Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9446718

Browse files
committed
Previous patch to mark UNION outputs with common typmod (if any) breaks
three-or-more-way UNIONs, as per example from Josh Berkus. Cause is afragile assumption that one tlist's entries will exactly match another.Restructure code to make that assumption a little less fragile.
1 parent17b6baf commit9446718

File tree

1 file changed

+118
-62
lines changed

1 file changed

+118
-62
lines changed

‎src/backend/optimizer/prep/prepunion.c

Lines changed: 118 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.70 2002/03/01 06:01:20 tgl Exp $
17+
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.71 2002/03/05 05:10:24 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -63,7 +63,9 @@ static List *generate_setop_tlist(List *colTypes, int flag,
6363
boolhack_constants,
6464
List*input_tlist,
6565
List*refnames_tlist);
66-
staticvoidmerge_tlist_typmods(List*tlist,List*planlist);
66+
staticList*generate_append_tlist(List*colTypes,boolflag,
67+
List*input_plans,
68+
List*refnames_tlist);
6769
staticbooltlist_same_datatypes(List*tlist,List*colTypes,booljunkOK);
6870
staticNode*adjust_inherited_attrs_mutator(Node*node,
6971
adjust_inherited_attrs_context*context);
@@ -169,13 +171,11 @@ recurse_set_operations(Node *setOp, Query *parse,
169171
*
170172
* XXX you don't really want to know about this: setrefs.c will apply
171173
* replace_vars_with_subplan_refs() to the Result node's tlist.
172-
* This would fail if the input plan's non-resjunk tlist entries
173-
* were not all simple Vars equal() to the referencing Vars
174-
* generated by generate_setop_tlist(). However, since the input
175-
* plan was generated by generate_union_plan() or
176-
* generate_nonunion_plan(), the referencing Vars will equal the
177-
* tlist entries they reference. Ugly but I don't feel like making
178-
* that code more general right now.
174+
* This would fail if the Vars generated by generate_setop_tlist()
175+
* were not exactly equal() to the corresponding tlist entries of
176+
* the subplan. However, since the subplan was generated by
177+
* generate_union_plan() or generate_nonunion_plan(), and hence its
178+
* tlist was generated by generate_append_tlist(), this will work.
179179
*/
180180
if (flag >=0||
181181
!tlist_same_datatypes(plan->targetlist,colTypes,junkOK))
@@ -226,10 +226,8 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
226226
* concerned, but we must make it look real anyway for the benefit of
227227
* the next plan level up.
228228
*/
229-
tlist=generate_setop_tlist(op->colTypes,-1, false,
230-
((Plan*)lfirst(planlist))->targetlist,
231-
refnames_tlist);
232-
merge_tlist_typmods(tlist,planlist);
229+
tlist=generate_append_tlist(op->colTypes, false,
230+
planlist,refnames_tlist);
233231

234232
/*
235233
* Append the child results together.
@@ -285,10 +283,8 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
285283
* flag column is shown as a variable not a constant, else setrefs.c
286284
* will get confused.
287285
*/
288-
tlist=generate_setop_tlist(op->colTypes,2, false,
289-
lplan->targetlist,
290-
refnames_tlist);
291-
merge_tlist_typmods(tlist,planlist);
286+
tlist=generate_append_tlist(op->colTypes, true,
287+
planlist,refnames_tlist);
292288

293289
/*
294290
* Append the child results together.
@@ -368,8 +364,7 @@ recurse_union_children(Node *setOp, Query *parse,
368364
* Generate targetlist for a set-operation plan node
369365
*
370366
* colTypes: column datatypes for non-junk columns
371-
* flag: -1 if no flag column needed, 0 or 1 to create a const flag column,
372-
* 2 to create a variable flag column
367+
* flag: -1 if no flag column needed, 0 or 1 to create a const flag column
373368
* hack_constants: true to copy up constants (see comments in code)
374369
* input_tlist: targetlist of this node's input node
375370
* refnames_tlist: targetlist to take column names from
@@ -450,71 +445,132 @@ generate_setop_tlist(List *colTypes, int flag,
450445
-1,
451446
pstrdup("flag"),
452447
true);
453-
if (flag <=1)
454-
{
455-
/* flag value is the given constant */
456-
expr= (Node*)makeConst(INT4OID,
457-
sizeof(int4),
458-
Int32GetDatum(flag),
459-
false,
460-
true,
461-
false,
462-
false);
463-
}
464-
else
465-
{
466-
/* flag value is being copied up from subplan */
467-
expr= (Node*)makeVar(0,
468-
resdom->resno,
469-
INT4OID,
470-
-1,
471-
0);
472-
}
448+
/* flag value is the given constant */
449+
expr= (Node*)makeConst(INT4OID,
450+
sizeof(int4),
451+
Int32GetDatum(flag),
452+
false,
453+
true,
454+
false,
455+
false);
473456
tlist=lappend(tlist,makeTargetEntry(resdom,expr));
474457
}
475458

476459
returntlist;
477460
}
478461

479462
/*
480-
* Merge typmods of a list of set-operation subplans.
463+
* Generate targetlist for a set-operation Append node
464+
*
465+
* colTypes: column datatypes for non-junk columns
466+
* flag: true to create a flag column copied up from subplans
467+
* input_plans: list of sub-plans of the Append
468+
* refnames_tlist: targetlist to take column names from
481469
*
482-
* If the inputs all agree on type and typmod of a particular column,
483-
* use that typmod; else use -1. We assume the result tlist has been
484-
* initialized with the types and typmods of the first input subplan.
470+
* The entries in the Append's targetlist should always be simple Vars;
471+
* we just have to make sure they have the right datatypes and typmods.
485472
*/
486-
staticvoid
487-
merge_tlist_typmods(List*tlist,List*planlist)
473+
staticList*
474+
generate_append_tlist(List*colTypes,boolflag,
475+
List*input_plans,
476+
List*refnames_tlist)
488477
{
478+
List*tlist=NIL;
479+
intresno=1;
480+
List*curColType;
481+
intcolindex;
482+
Resdom*resdom;
483+
Node*expr;
489484
List*planl;
485+
int32*colTypmods;
486+
487+
/*
488+
* First extract typmods to use.
489+
*
490+
* If the inputs all agree on type and typmod of a particular column,
491+
* use that typmod; else use -1.
492+
*/
493+
colTypmods= (int32*)palloc(length(colTypes)*sizeof(int32));
490494

491-
foreach(planl,planlist)
495+
foreach(planl,input_plans)
492496
{
493497
Plan*subplan= (Plan*)lfirst(planl);
494-
List*subtlist=subplan->targetlist;
495-
List*restlist;
498+
List*subtlist;
496499

497-
foreach(restlist,tlist)
500+
curColType=colTypes;
501+
colindex=0;
502+
foreach(subtlist,subplan->targetlist)
498503
{
499-
TargetEntry*restle= (TargetEntry*)lfirst(restlist);
500-
TargetEntry*subtle;
504+
TargetEntry*subtle= (TargetEntry*)lfirst(subtlist);
501505

502-
if (restle->resdom->resjunk)
506+
if (subtle->resdom->resjunk)
503507
continue;
504-
Assert(subtlist!=NIL);
505-
subtle= (TargetEntry*)lfirst(subtlist);
506-
while (subtle->resdom->resjunk)
508+
Assert(curColType!=NIL);
509+
if (subtle->resdom->restype== (Oid)lfirsti(curColType))
507510
{
508-
subtlist=lnext(subtlist);
509-
Assert(subtlist!=NIL);
510-
subtle= (TargetEntry*)lfirst(subtlist);
511+
/* If first subplan, copy the typmod; else compare */
512+
if (planl==input_plans)
513+
colTypmods[colindex]=subtle->resdom->restypmod;
514+
elseif (subtle->resdom->restypmod!=colTypmods[colindex])
515+
colTypmods[colindex]=-1;
511516
}
512-
if (restle->resdom->restype!=subtle->resdom->restype||
513-
restle->resdom->restypmod!=subtle->resdom->restypmod)
514-
restle->resdom->restypmod=-1;
515-
subtlist=lnext(subtlist);
517+
else
518+
{
519+
/* types disagree, so force typmod to -1 */
520+
colTypmods[colindex]=-1;
521+
}
522+
curColType=lnext(curColType);
523+
colindex++;
516524
}
525+
Assert(curColType==NIL);
517526
}
527+
528+
/*
529+
* Now we can build the tlist for the Append.
530+
*/
531+
colindex=0;
532+
foreach(curColType,colTypes)
533+
{
534+
OidcolType= (Oid)lfirsti(curColType);
535+
int32colTypmod=colTypmods[colindex++];
536+
TargetEntry*reftle= (TargetEntry*)lfirst(refnames_tlist);
537+
538+
Assert(reftle->resdom->resno==resno);
539+
Assert(!reftle->resdom->resjunk);
540+
expr= (Node*)makeVar(0,
541+
resno,
542+
colType,
543+
colTypmod,
544+
0);
545+
resdom=makeResdom((AttrNumber)resno++,
546+
colType,
547+
colTypmod,
548+
pstrdup(reftle->resdom->resname),
549+
false);
550+
tlist=lappend(tlist,makeTargetEntry(resdom,expr));
551+
refnames_tlist=lnext(refnames_tlist);
552+
}
553+
554+
if (flag)
555+
{
556+
/* Add a resjunk flag column */
557+
resdom=makeResdom((AttrNumber)resno++,
558+
INT4OID,
559+
-1,
560+
pstrdup("flag"),
561+
true);
562+
/* flag value is shown as copied up from subplan */
563+
expr= (Node*)makeVar(0,
564+
resdom->resno,
565+
INT4OID,
566+
-1,
567+
0);
568+
tlist=lappend(tlist,makeTargetEntry(resdom,expr));
569+
}
570+
571+
pfree(colTypmods);
572+
573+
returntlist;
518574
}
519575

520576
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp