mirror of https://github.com/citusdata/citus.git
Adds SQL syntax function calls related changes to ruleutils_14.c
Relevant PG commit: 40c24bfef92530bd846e111c1742c2a54441c62cpull/5209/head
parent
b4f76303c6
commit
1cb865deb8
|
@ -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,
|
static void get_agg_combine_expr(Node *node, deparse_context *context,
|
||||||
void *callback_arg);
|
void *callback_arg);
|
||||||
static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
|
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,
|
static void get_coercion_expr(Node *arg, deparse_context *context,
|
||||||
Oid resulttype, int32 resulttypmod,
|
Oid resulttype, int32 resulttypmod,
|
||||||
Node *parentNode);
|
Node *parentNode);
|
||||||
|
@ -6132,7 +6133,8 @@ looks_like_function(Node *node)
|
||||||
{
|
{
|
||||||
case T_FuncExpr:
|
case T_FuncExpr:
|
||||||
/* OK, unless it's going to deparse as a cast */
|
/* 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_NullIfExpr:
|
||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
case T_MinMaxExpr:
|
case T_MinMaxExpr:
|
||||||
|
@ -6234,6 +6236,18 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||||
return;
|
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
|
* Normal function: display as proname(args). First we need to extract
|
||||||
* the argument datatypes.
|
* 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
|
* get_coercion_expr
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue