mirror of https://github.com/citusdata/citus.git
Merge c507801c54
into 433e22e995
commit
6a53deff14
|
@ -113,6 +113,8 @@ static Var * PartitionColumnForPushedDownSubquery(Query *query);
|
||||||
static bool ContainsReferencesToRelids(Query *query, Relids relids, int *foundRelid);
|
static bool ContainsReferencesToRelids(Query *query, Relids relids, int *foundRelid);
|
||||||
static bool ContainsReferencesToRelidsWalker(Node *node,
|
static bool ContainsReferencesToRelidsWalker(Node *node,
|
||||||
RelidsReferenceWalkerContext *context);
|
RelidsReferenceWalkerContext *context);
|
||||||
|
static bool
|
||||||
|
ExprReferencesPartitionColumn(Node *node, Query *query);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1036,8 +1038,13 @@ DeferErrorIfCannotPushdownSubquery(Query *subqueryTree, bool outerMostQueryHasLi
|
||||||
errorDetail = "For Update/Share commands are currently unsupported";
|
errorDetail = "For Update/Share commands are currently unsupported";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* grouping sets are not allowed in subqueries*/
|
/* real GROUPING SETS / ROLLUP / CUBE are still disallowed;
|
||||||
if (subqueryTree->groupingSets)
|
* but PG 18 also fills groupingSets with a single simple item
|
||||||
|
* when the GROUP BY list contains un-projected columns. Allow that. */
|
||||||
|
if (subqueryTree->groupingSets &&
|
||||||
|
!(list_length(subqueryTree->groupingSets) == 1 &&
|
||||||
|
((GroupingSet *) linitial(subqueryTree->groupingSets))->kind
|
||||||
|
== GROUPING_SET_SIMPLE))
|
||||||
{
|
{
|
||||||
preconditionsSatisfied = false;
|
preconditionsSatisfied = false;
|
||||||
errorDetail = "could not run distributed query with GROUPING SETS, CUBE, "
|
errorDetail = "could not run distributed query with GROUPING SETS, CUBE, "
|
||||||
|
@ -1097,12 +1104,27 @@ DeferErrorIfSubqueryRequiresMerge(Query *subqueryTree, bool lateral,
|
||||||
/* group clause list must include partition column */
|
/* group clause list must include partition column */
|
||||||
if (subqueryTree->groupClause)
|
if (subqueryTree->groupClause)
|
||||||
{
|
{
|
||||||
List *groupClauseList = subqueryTree->groupClause;
|
bool groupOnPartitionColumn = false;
|
||||||
List *targetEntryList = subqueryTree->targetList;
|
|
||||||
List *groupTargetEntryList = GroupTargetEntryList(groupClauseList,
|
/* Walk every GROUP BY expression. */
|
||||||
targetEntryList);
|
ListCell *lc;
|
||||||
bool groupOnPartitionColumn =
|
foreach (lc, subqueryTree->groupClause)
|
||||||
TargetListOnPartitionColumn(subqueryTree, groupTargetEntryList);
|
{
|
||||||
|
Expr *expr = (Expr *)
|
||||||
|
get_sortgroupclause_expr(
|
||||||
|
(SortGroupClause *) lfirst(lc),
|
||||||
|
subqueryTree->targetList);
|
||||||
|
|
||||||
|
expr = (Expr *) strip_implicit_coercions((Node *) expr);
|
||||||
|
|
||||||
|
if (ExprReferencesPartitionColumn((Node *) expr, subqueryTree))
|
||||||
|
{
|
||||||
|
groupOnPartitionColumn = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!groupOnPartitionColumn)
|
if (!groupOnPartitionColumn)
|
||||||
{
|
{
|
||||||
preconditionsSatisfied = false;
|
preconditionsSatisfied = false;
|
||||||
|
@ -1171,6 +1193,70 @@ DeferErrorIfSubqueryRequiresMerge(Query *subqueryTree, bool lateral,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ExprReferencesPartitionColumn
|
||||||
|
*
|
||||||
|
* Recursively return true iff `node` ultimately refers to the partition
|
||||||
|
* (distribution) column of *any* distributed table in `query`.
|
||||||
|
*
|
||||||
|
* Handles:
|
||||||
|
* • plain Vars that point straight at RTE_RELATION
|
||||||
|
* • OUTER_VAR indirection (PG ≥ 18 resjunk columns)
|
||||||
|
* • Vars that point at an RTE_GROUP (PG ≥ 18); we descend into
|
||||||
|
* its groupexprs until we reach real relations.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ExprReferencesPartitionColumn(Node *node, Query *query)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* 1. Plain or OUTER_VAR Var ---------------------------------------- */
|
||||||
|
if (IsA(node, Var))
|
||||||
|
{
|
||||||
|
Var *v = (Var *) node;
|
||||||
|
|
||||||
|
/* Follow the OUTER_VAR → targetlist indirection exactly once */
|
||||||
|
if (v->varno == OUTER_VAR)
|
||||||
|
{
|
||||||
|
TargetEntry *tle = get_tle_by_resno(query->targetList, v->varattno);
|
||||||
|
return tle && ExprReferencesPartitionColumn((Node *) tle->expr, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity: varno must fit in rtable */
|
||||||
|
if (v->varno <= 0 || v->varno > list_length(query->rtable))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RangeTblEntry *rte = rt_fetch(v->varno, query->rtable);
|
||||||
|
|
||||||
|
/* 1a. Real relation: compare attnos ---------------------------- */
|
||||||
|
if (rte->rtekind == RTE_RELATION && HasDistributionKey(rte->relid))
|
||||||
|
{
|
||||||
|
Var *partcol = DistPartitionKey(rte->relid);
|
||||||
|
return partcol && partcol->varattno == v->varattno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1b. Synthetic GROUP entry: descend into its expressions ------- */
|
||||||
|
if (rte->rtekind == RTE_GROUP && rte->groupexprs)
|
||||||
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
foreach (lc, rte->groupexprs)
|
||||||
|
{
|
||||||
|
if (ExprReferencesPartitionColumn((Node *) lfirst(lc), query))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; /* other RTE kinds are irrelevant here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. Any other node type: walk its children ------------------------ */
|
||||||
|
return expression_tree_walker(node,
|
||||||
|
ExprReferencesPartitionColumn,
|
||||||
|
(void *) query);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DeferErrorIfUnsupportedTableCombination checks if the given query tree contains any
|
* DeferErrorIfUnsupportedTableCombination checks if the given query tree contains any
|
||||||
* unsupported range table combinations. For this, the function walks over all
|
* unsupported range table combinations. For this, the function walks over all
|
||||||
|
|
Loading…
Reference in New Issue