mirror of https://github.com/citusdata/citus.git
Update ruleutils for join related changes of postgres
Postgres changed some join related fields and therefore they also changed ruleutils, this commit applies those changes to our copy of ruleutils. Related commit on postgres side: 9ce77d75c5ab094637cc4a446296dc3be6e3c221pull/3900/head
parent
38aaf1faba
commit
135af84859
|
@ -337,8 +337,6 @@ static char *make_colname_unique(char *colname, deparse_namespace *dpns,
|
|||
static void expand_colnames_array_to(deparse_columns *colinfo, int n);
|
||||
static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
|
||||
deparse_columns *colinfo);
|
||||
static void flatten_join_using_qual(Node *qual,
|
||||
List **leftvars, List **rightvars);
|
||||
static char *get_rtable_name(int rtindex, deparse_context *context);
|
||||
static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
|
||||
static void push_child_plan(deparse_namespace *dpns, Plan *plan,
|
||||
|
@ -775,13 +773,13 @@ has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode)
|
|||
* dangerous situation and must pick unique aliases.
|
||||
*/
|
||||
RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
|
||||
ListCell *lc;
|
||||
|
||||
foreach(lc, jrte->joinaliasvars)
|
||||
/* We need only examine the merged columns */
|
||||
for (int i = 0; i < jrte->joinmergedcols; i++)
|
||||
{
|
||||
Var *aliasvar = (Var *) lfirst(lc);
|
||||
Node *aliasvar = list_nth(jrte->joinaliasvars, i);
|
||||
|
||||
if (aliasvar != NULL && !IsA(aliasvar, Var))
|
||||
if (!IsA(aliasvar, Var))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1190,12 +1188,8 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
|
|||
char *colname = colinfo->colnames[i];
|
||||
char *real_colname;
|
||||
|
||||
/* Ignore dropped column (only possible for non-merged column) */
|
||||
if (colinfo->leftattnos[i] == 0 && colinfo->rightattnos[i] == 0)
|
||||
{
|
||||
Assert(colname == NULL);
|
||||
continue;
|
||||
}
|
||||
/* Join column must refer to at least one input column */
|
||||
Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
|
||||
|
||||
/* Get the child column name */
|
||||
if (colinfo->leftattnos[i] > 0)
|
||||
|
@ -1207,7 +1201,12 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
|
|||
/* We're joining system columns --- use eref name */
|
||||
real_colname = strVal(list_nth(rte->eref->colnames, i));
|
||||
}
|
||||
Assert(real_colname != NULL);
|
||||
/* If child col has been dropped, no need to assign a join colname */
|
||||
if (real_colname == NULL)
|
||||
{
|
||||
colinfo->colnames[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* In an unnamed join, just report child column names as-is */
|
||||
if (rte->alias == NULL)
|
||||
|
@ -1532,7 +1531,8 @@ identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
|
|||
deparse_columns *colinfo)
|
||||
{
|
||||
int numjoincols;
|
||||
int i;
|
||||
int jcolno;
|
||||
int rcolno;
|
||||
ListCell *lc;
|
||||
|
||||
/* Extract left/right child RT indexes */
|
||||
|
@ -1561,146 +1561,32 @@ identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
|
|||
colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
|
||||
colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
|
||||
|
||||
/* Scan the joinaliasvars list to identify simple column references */
|
||||
i = 0;
|
||||
foreach(lc, jrte->joinaliasvars)
|
||||
{
|
||||
Var *aliasvar = (Var *) lfirst(lc);
|
||||
|
||||
/* get rid of any implicit coercion above the Var */
|
||||
aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar);
|
||||
|
||||
if (aliasvar == NULL)
|
||||
{
|
||||
/* It's a dropped column; nothing to do here */
|
||||
}
|
||||
else if (IsA(aliasvar, Var))
|
||||
{
|
||||
Assert(aliasvar->varlevelsup == 0);
|
||||
Assert(aliasvar->varattno != 0);
|
||||
if (aliasvar->varno == colinfo->leftrti)
|
||||
colinfo->leftattnos[i] = aliasvar->varattno;
|
||||
else if (aliasvar->varno == colinfo->rightrti)
|
||||
colinfo->rightattnos[i] = aliasvar->varattno;
|
||||
else
|
||||
elog(ERROR, "unexpected varno %d in JOIN RTE",
|
||||
aliasvar->varno);
|
||||
}
|
||||
else if (IsA(aliasvar, CoalesceExpr))
|
||||
{
|
||||
/*
|
||||
* It's a merged column in FULL JOIN USING. Ignore it for now and
|
||||
* let the code below identify the merged columns.
|
||||
*/
|
||||
}
|
||||
else
|
||||
elog(ERROR, "unrecognized node type in join alias vars: %d",
|
||||
(int) nodeTag(aliasvar));
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's a USING clause, deconstruct the join quals to identify the
|
||||
* merged columns. This is a tad painful but if we cannot rely on the
|
||||
* column names, there is no other representation of which columns were
|
||||
* joined by USING. (Unless the join type is FULL, we can't tell from the
|
||||
* joinaliasvars list which columns are merged.) Note: we assume that the
|
||||
* merged columns are the first output column(s) of the join.
|
||||
/*
|
||||
* Deconstruct RTE's joinleftcols/joinrightcols into desired format.
|
||||
* Recall that the column(s) merged due to USING are the first column(s)
|
||||
* of the join output. We need not do anything special while scanning
|
||||
* joinleftcols, but while scanning joinrightcols we must distinguish
|
||||
* merged from unmerged columns.
|
||||
*/
|
||||
if (j->usingClause)
|
||||
jcolno = 0;
|
||||
foreach(lc, jrte->joinleftcols)
|
||||
{
|
||||
List *leftvars = NIL;
|
||||
List *rightvars = NIL;
|
||||
ListCell *lc2;
|
||||
int leftattno = lfirst_int(lc);
|
||||
|
||||
/* Extract left- and right-side Vars from the qual expression */
|
||||
flatten_join_using_qual(j->quals, &leftvars, &rightvars);
|
||||
Assert(list_length(leftvars) == list_length(j->usingClause));
|
||||
Assert(list_length(rightvars) == list_length(j->usingClause));
|
||||
|
||||
/* Mark the output columns accordingly */
|
||||
i = 0;
|
||||
forboth(lc, leftvars, lc2, rightvars)
|
||||
{
|
||||
Var *leftvar = (Var *) lfirst(lc);
|
||||
Var *rightvar = (Var *) lfirst(lc2);
|
||||
|
||||
Assert(leftvar->varlevelsup == 0);
|
||||
Assert(leftvar->varattno != 0);
|
||||
if (leftvar->varno != colinfo->leftrti)
|
||||
elog(ERROR, "unexpected varno %d in JOIN USING qual",
|
||||
leftvar->varno);
|
||||
colinfo->leftattnos[i] = leftvar->varattno;
|
||||
|
||||
Assert(rightvar->varlevelsup == 0);
|
||||
Assert(rightvar->varattno != 0);
|
||||
if (rightvar->varno != colinfo->rightrti)
|
||||
elog(ERROR, "unexpected varno %d in JOIN USING qual",
|
||||
rightvar->varno);
|
||||
colinfo->rightattnos[i] = rightvar->varattno;
|
||||
|
||||
i++;
|
||||
}
|
||||
colinfo->leftattnos[jcolno++] = leftattno;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* flatten_join_using_qual: extract Vars being joined from a JOIN/USING qual
|
||||
*
|
||||
* We assume that transformJoinUsingClause won't have produced anything except
|
||||
* AND nodes, equality operator nodes, and possibly implicit coercions, and
|
||||
* that the AND node inputs match left-to-right with the original USING list.
|
||||
*
|
||||
* Caller must initialize the result lists to NIL.
|
||||
*/
|
||||
static void
|
||||
flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
|
||||
{
|
||||
if (IsA(qual, BoolExpr))
|
||||
rcolno = 0;
|
||||
foreach(lc, jrte->joinrightcols)
|
||||
{
|
||||
/* Handle AND nodes by recursion */
|
||||
BoolExpr *b = (BoolExpr *) qual;
|
||||
ListCell *lc;
|
||||
int rightattno = lfirst_int(lc);
|
||||
|
||||
Assert(b->boolop == AND_EXPR);
|
||||
foreach(lc, b->args)
|
||||
{
|
||||
flatten_join_using_qual((Node *) lfirst(lc),
|
||||
leftvars, rightvars);
|
||||
}
|
||||
}
|
||||
else if (IsA(qual, OpExpr))
|
||||
{
|
||||
/* Otherwise we should have an equality operator */
|
||||
OpExpr *op = (OpExpr *) qual;
|
||||
Var *var;
|
||||
|
||||
if (list_length(op->args) != 2)
|
||||
elog(ERROR, "unexpected unary operator in JOIN/USING qual");
|
||||
/* Arguments should be Vars with perhaps implicit coercions */
|
||||
var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
|
||||
if (!IsA(var, Var))
|
||||
elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
|
||||
(int) nodeTag(var));
|
||||
*leftvars = lappend(*leftvars, var);
|
||||
var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
|
||||
if (!IsA(var, Var))
|
||||
elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
|
||||
(int) nodeTag(var));
|
||||
*rightvars = lappend(*rightvars, var);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perhaps we have an implicit coercion to boolean? */
|
||||
Node *q = strip_implicit_coercions(qual);
|
||||
|
||||
if (q != qual)
|
||||
flatten_join_using_qual(q, leftvars, rightvars);
|
||||
if (rcolno < jrte->joinmergedcols) /* merged column? */
|
||||
colinfo->rightattnos[rcolno] = rightattno;
|
||||
else
|
||||
elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
|
||||
(int) nodeTag(qual));
|
||||
colinfo->rightattnos[jcolno++] = rightattno;
|
||||
rcolno++;
|
||||
}
|
||||
Assert(jcolno == numjoincols);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3643,6 +3529,8 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
|
|||
StringInfo buf = context->buf;
|
||||
RangeTblEntry *rte;
|
||||
AttrNumber attnum;
|
||||
Index varno;
|
||||
AttrNumber varattno;
|
||||
int netlevelsup;
|
||||
deparse_namespace *dpns;
|
||||
deparse_columns *colinfo;
|
||||
|
@ -3656,6 +3544,24 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
|
|||
var->varlevelsup, levelsup);
|
||||
dpns = (deparse_namespace *) list_nth(context->namespaces,
|
||||
netlevelsup);
|
||||
/*
|
||||
* If we have a syntactic referent for the Var, and we're working from a
|
||||
* parse tree, prefer to use the syntactic referent. Otherwise, fall back
|
||||
* on the semantic referent. (Forcing use of the semantic referent when
|
||||
* printing plan trees is a design choice that's perhaps more motivated by
|
||||
* backwards compatibility than anything else. But it does have the
|
||||
* advantage of making plans more explicit.)
|
||||
*/
|
||||
if (var->varnosyn > 0 && dpns->plan == NULL)
|
||||
{
|
||||
varno = var->varnosyn;
|
||||
varattno = var->varattnosyn;
|
||||
}
|
||||
else
|
||||
{
|
||||
varno = var->varno;
|
||||
varattno = var->varattno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find the relevant RTE in this rtable. In a plan tree, it's
|
||||
|
@ -3663,10 +3569,9 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
|
|||
* down into the subplans, or INDEX_VAR, which is resolved similarly. Also
|
||||
* find the aliases previously assigned for this RTE.
|
||||
*/
|
||||
if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
|
||||
if (varno >= 1 && varno <= list_length(dpns->rtable))
|
||||
{
|
||||
Index varno = var->varno;
|
||||
AttrNumber varattno = var->varattno;
|
||||
|
||||
/*
|
||||
* We might have been asked to map child Vars to some parent relation.
|
||||
*/
|
||||
|
@ -3995,6 +3900,8 @@ get_name_for_var_field(Var *var, int fieldno,
|
|||
AttrNumber attnum;
|
||||
int netlevelsup;
|
||||
deparse_namespace *dpns;
|
||||
Index varno;
|
||||
AttrNumber varattno;
|
||||
TupleDesc tupleDesc;
|
||||
Node *expr;
|
||||
|
||||
|
@ -4053,26 +3960,40 @@ get_name_for_var_field(Var *var, int fieldno,
|
|||
var->varlevelsup, levelsup);
|
||||
dpns = (deparse_namespace *) list_nth(context->namespaces,
|
||||
netlevelsup);
|
||||
|
||||
/*
|
||||
* If we have a syntactic referent for the Var, and we're working from a
|
||||
* parse tree, prefer to use the syntactic referent. Otherwise, fall back
|
||||
* on the semantic referent. (See comments in get_variable().)
|
||||
*/
|
||||
if (var->varnosyn > 0 && dpns->plan == NULL)
|
||||
{
|
||||
varno = var->varnosyn;
|
||||
varattno = var->varattnosyn;
|
||||
}
|
||||
else
|
||||
{
|
||||
varno = var->varno;
|
||||
varattno = var->varattno;
|
||||
}
|
||||
/*
|
||||
* Try to find the relevant RTE in this rtable. In a plan tree, it's
|
||||
* likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
|
||||
* down into the subplans, or INDEX_VAR, which is resolved similarly.
|
||||
*/
|
||||
if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
|
||||
if (varno >= 1 && varno <= list_length(dpns->rtable))
|
||||
{
|
||||
rte = rt_fetch(var->varno, dpns->rtable);
|
||||
attnum = var->varattno;
|
||||
rte = rt_fetch(varno, dpns->rtable);
|
||||
attnum = varattno;
|
||||
}
|
||||
else if (var->varno == OUTER_VAR && dpns->outer_tlist)
|
||||
else if (varno == OUTER_VAR && dpns->outer_tlist)
|
||||
{
|
||||
TargetEntry *tle;
|
||||
deparse_namespace save_dpns;
|
||||
const char *result;
|
||||
|
||||
tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
|
||||
tle = get_tle_by_resno(dpns->outer_tlist, varattno);
|
||||
if (!tle)
|
||||
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
|
||||
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
|
||||
|
||||
Assert(netlevelsup == 0);
|
||||
push_child_plan(dpns, dpns->outer_plan, &save_dpns);
|
||||
|
@ -4083,15 +4004,15 @@ get_name_for_var_field(Var *var, int fieldno,
|
|||
pop_child_plan(dpns, &save_dpns);
|
||||
return result;
|
||||
}
|
||||
else if (var->varno == INNER_VAR && dpns->inner_tlist)
|
||||
else if (varno == INNER_VAR && dpns->inner_tlist)
|
||||
{
|
||||
TargetEntry *tle;
|
||||
deparse_namespace save_dpns;
|
||||
const char *result;
|
||||
|
||||
tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
|
||||
tle = get_tle_by_resno(dpns->inner_tlist, varattno);
|
||||
if (!tle)
|
||||
elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
|
||||
elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
|
||||
|
||||
Assert(netlevelsup == 0);
|
||||
push_child_plan(dpns, dpns->inner_plan, &save_dpns);
|
||||
|
@ -4102,14 +4023,14 @@ get_name_for_var_field(Var *var, int fieldno,
|
|||
pop_child_plan(dpns, &save_dpns);
|
||||
return result;
|
||||
}
|
||||
else if (var->varno == INDEX_VAR && dpns->index_tlist)
|
||||
else if (varno == INDEX_VAR && dpns->index_tlist)
|
||||
{
|
||||
TargetEntry *tle;
|
||||
const char *result;
|
||||
|
||||
tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
|
||||
tle = get_tle_by_resno(dpns->index_tlist, varattno);
|
||||
if (!tle)
|
||||
elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
|
||||
elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
|
||||
|
||||
Assert(netlevelsup == 0);
|
||||
|
||||
|
@ -4120,7 +4041,7 @@ get_name_for_var_field(Var *var, int fieldno,
|
|||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "bogus varno: %d", var->varno);
|
||||
elog(ERROR, "bogus varno: %d", varno);
|
||||
return NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue