mirror of https://github.com/citusdata/citus.git
Update ruleutils_96 with latest PostgreSQL changes
See: postgres/postgres@41ada83774 postgres/postgres@3b0c2dbed0 postgres/postgres@ff2d537223pull/1632/head
parent
0e134a9178
commit
ebecde8f6e
|
@ -386,6 +386,9 @@ static void get_rule_expr(Node *node, deparse_context *context,
|
|||
bool showimplicit);
|
||||
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
|
||||
bool showimplicit);
|
||||
static void get_rule_expr_funccall(Node *node, deparse_context *context,
|
||||
bool showimplicit);
|
||||
static bool looks_like_function(Node *node);
|
||||
static void get_oper_expr(OpExpr *expr, deparse_context *context);
|
||||
static void get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||
bool showimplicit);
|
||||
|
@ -3282,8 +3285,11 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
|||
/*
|
||||
* We must dig down into the expr to see if it's a PARAM_MULTIEXPR
|
||||
* Param. That could be buried under FieldStores and ArrayRefs
|
||||
* (cf processIndirection()), and underneath those there could be
|
||||
* an implicit type coercion.
|
||||
* and CoerceToDomains (cf processIndirection()), and underneath
|
||||
* those there could be an implicit type coercion. Because we
|
||||
* would ignore implicit type coercions anyway, we don't need to
|
||||
* be as careful as processIndirection() is about descending past
|
||||
* implicit CoerceToDomains.
|
||||
*/
|
||||
expr = (Node *) tle->expr;
|
||||
while (expr)
|
||||
|
@ -3302,6 +3308,14 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
|||
break;
|
||||
expr = (Node *) aref->refassgnexpr;
|
||||
}
|
||||
else if (IsA(expr, CoerceToDomain))
|
||||
{
|
||||
CoerceToDomain *cdomain = (CoerceToDomain *) expr;
|
||||
|
||||
if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
|
||||
break;
|
||||
expr = (Node *) cdomain->arg;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
@ -5763,6 +5777,63 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
|
|||
get_rule_expr(node, context, showimplicit);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_rule_expr_funccall - Parse back a function-call expression
|
||||
*
|
||||
* Same as get_rule_expr(), except that we guarantee that the output will
|
||||
* look like a function call, or like one of the things the grammar treats as
|
||||
* equivalent to a function call (see the func_expr_windowless production).
|
||||
* This is needed in places where the grammar uses func_expr_windowless and
|
||||
* you can't substitute a parenthesized a_expr. If what we have isn't going
|
||||
* to look like a function call, wrap it in a dummy CAST() expression, which
|
||||
* will satisfy the grammar --- and, indeed, is likely what the user wrote to
|
||||
* produce such a thing.
|
||||
*/
|
||||
static void
|
||||
get_rule_expr_funccall(Node *node, deparse_context *context,
|
||||
bool showimplicit)
|
||||
{
|
||||
if (looks_like_function(node))
|
||||
get_rule_expr(node, context, showimplicit);
|
||||
else
|
||||
{
|
||||
StringInfo buf = context->buf;
|
||||
|
||||
appendStringInfoString(buf, "CAST(");
|
||||
/* no point in showing any top-level implicit cast */
|
||||
get_rule_expr(node, context, false);
|
||||
appendStringInfo(buf, " AS %s)",
|
||||
format_type_with_typemod(exprType(node),
|
||||
exprTypmod(node)));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to identify node types that satisfy func_expr_windowless.
|
||||
* If in doubt, "false" is always a safe answer.
|
||||
*/
|
||||
static bool
|
||||
looks_like_function(Node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
return false; /* probably shouldn't happen */
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_FuncExpr:
|
||||
/* OK, unless it's going to deparse as a cast */
|
||||
return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL);
|
||||
case T_NullIfExpr:
|
||||
case T_CoalesceExpr:
|
||||
case T_MinMaxExpr:
|
||||
case T_XmlExpr:
|
||||
/* these are all accepted by func_expr_common_subexpr */
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_oper_expr - Parse back an OpExpr node
|
||||
|
@ -6641,7 +6712,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
|||
if (list_length(rte->functions) == 1 &&
|
||||
(rtfunc1->funccolnames == NIL || !rte->funcordinality))
|
||||
{
|
||||
get_rule_expr(rtfunc1->funcexpr, context, true);
|
||||
get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
|
||||
/* we'll print the coldeflist below, if it has one */
|
||||
}
|
||||
else
|
||||
|
@ -6704,7 +6775,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
|||
|
||||
if (funcno > 0)
|
||||
appendStringInfoString(buf, ", ");
|
||||
get_rule_expr(rtfunc->funcexpr, context, true);
|
||||
get_rule_expr_funccall(rtfunc->funcexpr, context, true);
|
||||
if (rtfunc->funccolnames != NIL)
|
||||
{
|
||||
/* Reconstruct the column definition list */
|
||||
|
@ -6894,6 +6965,11 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
|||
if (!PRETTY_PAREN(context))
|
||||
appendStringInfoChar(buf, ')');
|
||||
}
|
||||
else if (j->jointype != JOIN_INNER)
|
||||
{
|
||||
/* If we didn't say CROSS JOIN above, we must provide an ON */
|
||||
appendStringInfoString(buf, " ON TRUE");
|
||||
}
|
||||
|
||||
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
||||
appendStringInfoChar(buf, ')');
|
||||
|
@ -7090,13 +7166,17 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
|
|||
*
|
||||
* We strip any top-level FieldStore or assignment ArrayRef nodes that
|
||||
* appear in the input, printing them as decoration for the base column
|
||||
* name (which we assume the caller just printed). Return the subexpression
|
||||
* that's to be assigned.
|
||||
* name (which we assume the caller just printed). We might also need to
|
||||
* strip CoerceToDomain nodes, but only ones that appear above assignment
|
||||
* nodes.
|
||||
*
|
||||
* Returns the subexpression that's to be assigned.
|
||||
*/
|
||||
static Node *
|
||||
processIndirection(Node *node, deparse_context *context)
|
||||
{
|
||||
StringInfo buf = context->buf;
|
||||
CoerceToDomain *cdomain = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -7144,10 +7224,28 @@ processIndirection(Node *node, deparse_context *context)
|
|||
*/
|
||||
node = (Node *) aref->refassgnexpr;
|
||||
}
|
||||
else if (IsA(node, CoerceToDomain))
|
||||
{
|
||||
cdomain = (CoerceToDomain *) node;
|
||||
/* If it's an explicit domain coercion, we're done */
|
||||
if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
|
||||
break;
|
||||
/* Tentatively descend past the CoerceToDomain */
|
||||
node = (Node *) cdomain->arg;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we descended past a CoerceToDomain whose argument turned out not to
|
||||
* be a FieldStore or array assignment, back up to the CoerceToDomain.
|
||||
* (This is not enough to be fully correct if there are nested implicit
|
||||
* CoerceToDomains, but such cases shouldn't ever occur.)
|
||||
*/
|
||||
if (cdomain && node == (Node *) cdomain->arg)
|
||||
node = (Node *) cdomain;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue