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);
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
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
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 */
'foo'::text = ANY ((( SELECT ARRAY['abc'::text, 'def'::text, 'foo'::text] AS "array"))::text[]) AS c2;
(1 row)
+-- check display of assorted RTE_FUNCTION expressions
+create view tt20v as
+select * from
+ coalesce(1,2) as c,
+ collation for ('x'::text) col,
+ current_date as d,
+ cast(1+2 as int4) as i4,
+ cast(1+2 as int8) as i8;
+select pg_get_viewdef('tt20v', true);
+ pg_get_viewdef
+---------------------------------------------
+ SELECT c.c, +
+ col.col, +
+ d.d, +
+ i4.i4, +
+ i8.i8 +
+ FROM COALESCE(1, 2) c(c), +
+ pg_collation_for('x'::text) col(col), +
+ CAST('now'::text::date AS date) d(d), +
+ CAST(1 + 2 AS integer) i4(i4), +
+ CAST((1 + 2)::bigint AS bigint) i8(i8);
+(1 row)
+
-- clean up all the random objects we made above
set client_min_messages = warning;
DROP SCHEMA temp_view_test CASCADE;
'foo'::text = any((select array['abc','def','foo']::text[])::text[]) c2;
select pg_get_viewdef('tt19v', true);
+-- check display of assorted RTE_FUNCTION expressions
+
+create view tt20v as
+select * from
+ coalesce(1,2) as c,
+ collation for ('x'::text) col,
+ current_date as d,
+ cast(1+2 as int4) as i4,
+ cast(1+2 as int8) as i8;
+select pg_get_viewdef('tt20v', true);
+
-- clean up all the random objects we made above
set client_min_messages = warning;
DROP SCHEMA temp_view_test CASCADE;