Skip to content

Commit 5db9367

Browse files
committed
Fix UNION planner datatype issue
66c0185 gave the planner the ability to have union child queries provide the union planner with pre-sorted input so that UNION queries could be more efficiently implemented using Merge Append. That commit overlooked checking that the UNION target list and the union child target list's types all match. In some corner cases, this could result in the planner producing sorts using the sort operator of the top-level UNION's target list type rather than of the union child's target list's type. The implications of this range from silently working correctly, despite using the wrong sort operator all the way up to a segmentation fault. Here we fix by adjusting the planner so it makes no attempt to have the subquery produce pre-sorted results when the data type of the UNION target list and the types from the subquery target list don't match exactly. Backpatch to 17, where 66c0185 was introduced. Reported-by: Jason Smith <dqetool@126.com> Diagnosed-by: Tom Lane <tgl@sss.pgh.pa.us> Bug: 18764 Discussion: https://postgr.es/m/18764-63ad667ea26e877a%40postgresql.org Backpatch-through: 17
1 parent c559f61 commit 5db9367

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/backend/optimizer/plan/planner.c

+22-2
Original file line numberDiff line numberDiff line change
@@ -8086,33 +8086,53 @@ group_by_has_partkey(RelOptInfo *input_rel,
80868086
* child query's targetlist entries may already have a tleSortGroupRef
80878087
* assigned for other purposes, such as GROUP BYs. Here we keep the
80888088
* SortGroupClause list in the same order as 'op' groupClauses and just adjust
8089-
* the tleSortGroupRef to reference the TargetEntry's 'ressortgroupref'.
8089+
* the tleSortGroupRef to reference the TargetEntry's 'ressortgroupref'. If
8090+
* any of the columns in the targetlist don't match to the setop's colTypes
8091+
* then we return an empty list. This may leave some TLEs with unreferenced
8092+
* ressortgroupref markings, but that's harmless.
80908093
*/
80918094
static List *
80928095
generate_setop_child_grouplist(SetOperationStmt *op, List *targetlist)
80938096
{
80948097
List *grouplist = copyObject(op->groupClauses);
80958098
ListCell *lg;
80968099
ListCell *lt;
8100+
ListCell *ct;
80978101

80988102
lg = list_head(grouplist);
8103+
ct = list_head(op->colTypes);
80998104
foreach(lt, targetlist)
81008105
{
81018106
TargetEntry *tle = (TargetEntry *) lfirst(lt);
81028107
SortGroupClause *sgc;
8108+
Oid coltype;
81038109

81048110
/* resjunk columns could have sortgrouprefs. Leave these alone */
81058111
if (tle->resjunk)
81068112
continue;
81078113

8108-
/* we expect every non-resjunk target to have a SortGroupClause */
8114+
/*
8115+
* We expect every non-resjunk target to have a SortGroupClause and
8116+
* colTypes.
8117+
*/
81098118
Assert(lg != NULL);
8119+
Assert(ct != NULL);
81108120
sgc = (SortGroupClause *) lfirst(lg);
8121+
coltype = lfirst_oid(ct);
8122+
8123+
/* reject if target type isn't the same as the setop target type */
8124+
if (coltype != exprType((Node *) tle->expr))
8125+
return NIL;
8126+
81118127
lg = lnext(grouplist, lg);
8128+
ct = lnext(op->colTypes, ct);
81128129

81138130
/* assign a tleSortGroupRef, or reuse the existing one */
81148131
sgc->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
81158132
}
8133+
81168134
Assert(lg == NULL);
8135+
Assert(ct == NULL);
8136+
81178137
return grouplist;
81188138
}

0 commit comments

Comments
 (0)