Adds SQL syntax function calls related changes to ruleutils_14.c

Relevant PG commit:
40c24bfef92530bd846e111c1742c2a54441c62c
pull/5209/head
Halil Ozan Akgul 2021-08-16 14:54:43 +03:00 committed by Sait Talha Nisanci
parent b4f76303c6
commit 1cb865deb8
1 changed files with 234 additions and 1 deletions

View File

@ -413,6 +413,7 @@ static void get_agg_expr(Aggref *aggref, deparse_context *context,
static void get_agg_combine_expr(Node *node, deparse_context *context,
void *callback_arg);
static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context);
static void get_coercion_expr(Node *arg, deparse_context *context,
Oid resulttype, int32 resulttypmod,
Node *parentNode);
@ -6132,7 +6133,8 @@ looks_like_function(Node *node)
{
case T_FuncExpr:
/* OK, unless it's going to deparse as a cast */
return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL);
return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL ||
((FuncExpr *) node)->funcformat == COERCE_SQL_SYNTAX);
case T_NullIfExpr:
case T_CoalesceExpr:
case T_MinMaxExpr:
@ -6234,6 +6236,18 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
return;
}
/*
* If the function was called using one of the SQL spec's random special
* syntaxes, try to reproduce that. If we don't recognize the function,
* fall through.
*/
if (expr->funcformat == COERCE_SQL_SYNTAX)
{
if (get_func_sql_syntax(expr, context))
return;
}
/*
* Normal function: display as proname(args). First we need to extract
* the argument datatypes.
@ -6470,6 +6484,225 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
}
}
/*
* get_func_sql_syntax - Parse back a SQL-syntax function call
*
* Returns true if we successfully deparsed, false if we did not
* recognize the function.
*/
static bool
get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
{
StringInfo buf = context->buf;
Oid funcoid = expr->funcid;
switch (funcoid)
{
case F_TIMEZONE_INTERVAL_TIMESTAMP:
case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
case F_TIMEZONE_INTERVAL_TIMETZ:
case F_TIMEZONE_TEXT_TIMESTAMP:
case F_TIMEZONE_TEXT_TIMESTAMPTZ:
case F_TIMEZONE_TEXT_TIMETZ:
/* AT TIME ZONE ... note reversed argument order */
appendStringInfoChar(buf, '(');
get_rule_expr((Node *) lsecond(expr->args), context, false);
appendStringInfoString(buf, " AT TIME ZONE ");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoChar(buf, ')');
return true;
case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
case F_OVERLAPS_TIME_TIME_TIME_TIME:
/* (x1, x2) OVERLAPS (y1, y2) */
appendStringInfoString(buf, "((");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, ", ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
appendStringInfoString(buf, ") OVERLAPS (");
get_rule_expr((Node *) lthird(expr->args), context, false);
appendStringInfoString(buf, ", ");
get_rule_expr((Node *) lfourth(expr->args), context, false);
appendStringInfoString(buf, "))");
return true;
case F_IS_NORMALIZED:
/* IS xxx NORMALIZED */
appendStringInfoString(buf, "((");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, ") IS");
if (list_length(expr->args) == 2)
{
Const *con = (Const *) lsecond(expr->args);
Assert(IsA(con, Const) &&
con->consttype == TEXTOID &&
!con->constisnull);
appendStringInfo(buf, " %s",
TextDatumGetCString(con->constvalue));
}
appendStringInfoString(buf, " NORMALIZED)");
return true;
case F_PG_COLLATION_FOR:
/* COLLATION FOR */
appendStringInfoString(buf, "COLLATION FOR (");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoChar(buf, ')');
return true;
/*
* XXX EXTRACT, a/k/a date_part(), is intentionally not covered
* yet. Add it after we change the return type to numeric.
*/
case F_NORMALIZE:
/* NORMALIZE() */
appendStringInfoString(buf, "NORMALIZE(");
get_rule_expr((Node *) linitial(expr->args), context, false);
if (list_length(expr->args) == 2)
{
Const *con = (Const *) lsecond(expr->args);
Assert(IsA(con, Const) &&
con->consttype == TEXTOID &&
!con->constisnull);
appendStringInfo(buf, ", %s",
TextDatumGetCString(con->constvalue));
}
appendStringInfoChar(buf, ')');
return true;
case F_OVERLAY_BIT_BIT_INT4:
case F_OVERLAY_BIT_BIT_INT4_INT4:
case F_OVERLAY_BYTEA_BYTEA_INT4:
case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
case F_OVERLAY_TEXT_TEXT_INT4:
case F_OVERLAY_TEXT_TEXT_INT4_INT4:
/* OVERLAY() */
appendStringInfoString(buf, "OVERLAY(");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, " PLACING ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) lthird(expr->args), context, false);
if (list_length(expr->args) == 4)
{
appendStringInfoString(buf, " FOR ");
get_rule_expr((Node *) lfourth(expr->args), context, false);
}
appendStringInfoChar(buf, ')');
return true;
case F_POSITION_BIT_BIT:
case F_POSITION_BYTEA_BYTEA:
case F_POSITION_TEXT_TEXT:
/* POSITION() ... extra parens since args are b_expr not a_expr */
appendStringInfoString(buf, "POSITION((");
get_rule_expr((Node *) lsecond(expr->args), context, false);
appendStringInfoString(buf, ") IN (");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, "))");
return true;
case F_SUBSTRING_BIT_INT4:
case F_SUBSTRING_BIT_INT4_INT4:
case F_SUBSTRING_BYTEA_INT4:
case F_SUBSTRING_BYTEA_INT4_INT4:
case F_SUBSTRING_TEXT_INT4:
case F_SUBSTRING_TEXT_INT4_INT4:
/* SUBSTRING FROM/FOR (i.e., integer-position variants) */
appendStringInfoString(buf, "SUBSTRING(");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
if (list_length(expr->args) == 3)
{
appendStringInfoString(buf, " FOR ");
get_rule_expr((Node *) lthird(expr->args), context, false);
}
appendStringInfoChar(buf, ')');
return true;
case F_SUBSTRING_TEXT_TEXT_TEXT:
/* SUBSTRING SIMILAR/ESCAPE */
appendStringInfoString(buf, "SUBSTRING(");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, " SIMILAR ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
appendStringInfoString(buf, " ESCAPE ");
get_rule_expr((Node *) lthird(expr->args), context, false);
appendStringInfoChar(buf, ')');
return true;
case F_BTRIM_BYTEA_BYTEA:
case F_BTRIM_TEXT:
case F_BTRIM_TEXT_TEXT:
/* TRIM() */
appendStringInfoString(buf, "TRIM(BOTH");
if (list_length(expr->args) == 2)
{
appendStringInfoChar(buf, ' ');
get_rule_expr((Node *) lsecond(expr->args), context, false);
}
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoChar(buf, ')');
return true;
case F_LTRIM_TEXT:
case F_LTRIM_TEXT_TEXT:
/* TRIM() */
appendStringInfoString(buf, "TRIM(LEADING");
if (list_length(expr->args) == 2)
{
appendStringInfoChar(buf, ' ');
get_rule_expr((Node *) lsecond(expr->args), context, false);
}
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoChar(buf, ')');
return true;
case F_RTRIM_TEXT:
case F_RTRIM_TEXT_TEXT:
/* TRIM() */
appendStringInfoString(buf, "TRIM(TRAILING");
if (list_length(expr->args) == 2)
{
appendStringInfoChar(buf, ' ');
get_rule_expr((Node *) lsecond(expr->args), context, false);
}
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoChar(buf, ')');
return true;
case F_XMLEXISTS:
/* XMLEXISTS ... extra parens because args are c_expr */
appendStringInfoString(buf, "XMLEXISTS((");
get_rule_expr((Node *) linitial(expr->args), context, false);
appendStringInfoString(buf, ") PASSING (");
get_rule_expr((Node *) lsecond(expr->args), context, false);
appendStringInfoString(buf, "))");
return true;
}
return false;
}
/* ----------
* get_coercion_expr
*