mirror of https://github.com/citusdata/citus.git
Adds SQL/JSON constructors to ruleutils_15.c
Relevant PG commits: f4fb45d15c59d7add2e1b81a9d477d0119a9691a cc7401d5ca498a84d9b47fd2e01cebd8e830e558boolean_node
parent
ddbca4ed42
commit
5fb34a2994
|
@ -425,6 +425,12 @@ static void get_coercion_expr(Node *arg, deparse_context *context,
|
||||||
Node *parentNode);
|
Node *parentNode);
|
||||||
static void get_const_expr(Const *constval, deparse_context *context,
|
static void get_const_expr(Const *constval, deparse_context *context,
|
||||||
int showtype);
|
int showtype);
|
||||||
|
static void get_json_constructor(JsonConstructorExpr *ctor,
|
||||||
|
deparse_context *context, bool showimplicit);
|
||||||
|
static void get_json_agg_constructor(JsonConstructorExpr *ctor,
|
||||||
|
deparse_context *context,
|
||||||
|
const char *funcname,
|
||||||
|
bool is_json_objectagg);
|
||||||
static void get_const_collation(Const *constval, deparse_context *context);
|
static void get_const_collation(Const *constval, deparse_context *context);
|
||||||
static void simple_quote_literal(StringInfo buf, const char *val);
|
static void simple_quote_literal(StringInfo buf, const char *val);
|
||||||
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
|
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
|
||||||
|
@ -2885,7 +2891,8 @@ get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
|
||||||
bool need_paren = (PRETTY_PAREN(context)
|
bool need_paren = (PRETTY_PAREN(context)
|
||||||
|| IsA(expr, FuncExpr)
|
|| IsA(expr, FuncExpr)
|
||||||
|| IsA(expr, Aggref)
|
|| IsA(expr, Aggref)
|
||||||
|| IsA(expr, WindowFunc));
|
|| IsA(expr, WindowFunc)
|
||||||
|
|| IsA(expr, JsonConstructorExpr));
|
||||||
|
|
||||||
if (need_paren)
|
if (need_paren)
|
||||||
appendStringInfoChar(context->buf, '(');
|
appendStringInfoChar(context->buf, '(');
|
||||||
|
@ -4846,6 +4853,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||||
case T_GroupingFunc:
|
case T_GroupingFunc:
|
||||||
case T_WindowFunc:
|
case T_WindowFunc:
|
||||||
case T_FuncExpr:
|
case T_FuncExpr:
|
||||||
|
case T_JsonConstructorExpr:
|
||||||
/* function-like: name(..) or name[..] */
|
/* function-like: name(..) or name[..] */
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -5133,12 +5141,12 @@ get_rule_expr_paren(Node *node, deparse_context *context,
|
||||||
* get_json_format - Parse back a JsonFormat node
|
* get_json_format - Parse back a JsonFormat node
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_json_format(JsonFormat *format, deparse_context *context)
|
get_json_format(JsonFormat *format, StringInfo buf)
|
||||||
{
|
{
|
||||||
if (format->format_type == JS_FORMAT_DEFAULT)
|
if (format->format_type == JS_FORMAT_DEFAULT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
appendStringInfoString(context->buf,
|
appendStringInfoString(buf,
|
||||||
format->format_type == JS_FORMAT_JSONB ?
|
format->format_type == JS_FORMAT_JSONB ?
|
||||||
" FORMAT JSONB" : " FORMAT JSON");
|
" FORMAT JSONB" : " FORMAT JSON");
|
||||||
|
|
||||||
|
@ -5148,7 +5156,7 @@ get_json_format(JsonFormat *format, deparse_context *context)
|
||||||
format->encoding == JS_ENC_UTF16 ? "UTF16" :
|
format->encoding == JS_ENC_UTF16 ? "UTF16" :
|
||||||
format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
|
format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
|
||||||
|
|
||||||
appendStringInfo(context->buf, " ENCODING %s", encoding);
|
appendStringInfo(buf, " ENCODING %s", encoding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5156,20 +5164,20 @@ get_json_format(JsonFormat *format, deparse_context *context)
|
||||||
* get_json_returning - Parse back a JsonReturning structure
|
* get_json_returning - Parse back a JsonReturning structure
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_json_returning(JsonReturning *returning, deparse_context *context,
|
get_json_returning(JsonReturning *returning, StringInfo buf,
|
||||||
bool json_format_by_default)
|
bool json_format_by_default)
|
||||||
{
|
{
|
||||||
if (!OidIsValid(returning->typid))
|
if (!OidIsValid(returning->typid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
appendStringInfo(context->buf, " RETURNING %s",
|
appendStringInfo(buf, " RETURNING %s",
|
||||||
format_type_with_typemod(returning->typid,
|
format_type_with_typemod(returning->typid,
|
||||||
returning->typmod));
|
returning->typmod));
|
||||||
|
|
||||||
if (!json_format_by_default ||
|
if (!json_format_by_default ||
|
||||||
returning->format->format_type !=
|
returning->format->format_type !=
|
||||||
(returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
|
(returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
|
||||||
get_json_format(returning->format, context);
|
get_json_format(returning->format, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
|
@ -6358,10 +6366,14 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
JsonValueExpr *jve = (JsonValueExpr *) node;
|
JsonValueExpr *jve = (JsonValueExpr *) node;
|
||||||
|
|
||||||
get_rule_expr((Node *) jve->raw_expr, context, false);
|
get_rule_expr((Node *) jve->raw_expr, context, false);
|
||||||
get_json_format(jve->format, context);
|
get_json_format(jve->format, context->buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_JsonConstructorExpr:
|
||||||
|
get_json_constructor((JsonConstructorExpr *) node, context, false);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_List:
|
case T_List:
|
||||||
{
|
{
|
||||||
char *sep;
|
char *sep;
|
||||||
|
@ -6636,6 +6648,77 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_json_constructor_options(JsonConstructorExpr *ctor, StringInfo buf)
|
||||||
|
{
|
||||||
|
if (ctor->absent_on_null)
|
||||||
|
{
|
||||||
|
if (ctor->type == JSCTOR_JSON_OBJECT ||
|
||||||
|
ctor->type == JSCTOR_JSON_OBJECTAGG)
|
||||||
|
appendStringInfoString(buf, " ABSENT ON NULL");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctor->type == JSCTOR_JSON_ARRAY ||
|
||||||
|
ctor->type == JSCTOR_JSON_ARRAYAGG)
|
||||||
|
appendStringInfoString(buf, " NULL ON NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctor->unique)
|
||||||
|
appendStringInfoString(buf, " WITH UNIQUE KEYS");
|
||||||
|
|
||||||
|
get_json_returning(ctor->returning, buf, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_json_constructor(JsonConstructorExpr *ctor, deparse_context *context,
|
||||||
|
bool showimplicit)
|
||||||
|
{
|
||||||
|
StringInfo buf = context->buf;
|
||||||
|
const char *funcname;
|
||||||
|
int nargs;
|
||||||
|
ListCell *lc;
|
||||||
|
|
||||||
|
switch (ctor->type)
|
||||||
|
{
|
||||||
|
case JSCTOR_JSON_OBJECT:
|
||||||
|
funcname = "JSON_OBJECT";
|
||||||
|
break;
|
||||||
|
case JSCTOR_JSON_ARRAY:
|
||||||
|
funcname = "JSON_ARRAY";
|
||||||
|
break;
|
||||||
|
case JSCTOR_JSON_OBJECTAGG:
|
||||||
|
get_json_agg_constructor(ctor, context, "JSON_OBJECTAGG", true);
|
||||||
|
return;
|
||||||
|
case JSCTOR_JSON_ARRAYAGG:
|
||||||
|
get_json_agg_constructor(ctor, context, "JSON_ARRAYAGG", false);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
elog(ERROR, "invalid JsonConstructorExprType %d", ctor->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
appendStringInfo(buf, "%s(", funcname);
|
||||||
|
|
||||||
|
nargs = 0;
|
||||||
|
foreach(lc, ctor->args)
|
||||||
|
{
|
||||||
|
if (nargs > 0)
|
||||||
|
{
|
||||||
|
const char *sep = ctor->type == JSCTOR_JSON_OBJECT &&
|
||||||
|
(nargs % 2) != 0 ? " : " : ", ";
|
||||||
|
|
||||||
|
appendStringInfoString(buf, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_rule_expr((Node *) lfirst(lc), context, true);
|
||||||
|
|
||||||
|
nargs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_json_constructor_options(ctor, buf);
|
||||||
|
|
||||||
|
appendStringInfo(buf, ")");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_proc_expr - Parse back a CallStmt node
|
* get_proc_expr - Parse back a CallStmt node
|
||||||
|
@ -6682,16 +6765,17 @@ get_proc_expr(CallStmt *stmt, deparse_context *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_agg_expr - Parse back an Aggref node
|
* get_agg_expr_helper - Parse back an Aggref node
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_agg_expr(Aggref *aggref, deparse_context *context,
|
get_agg_expr_helper(Aggref *aggref, deparse_context *context,
|
||||||
Aggref *original_aggref)
|
Aggref *original_aggref, const char *funcname,
|
||||||
|
const char *options, bool is_json_objectagg)
|
||||||
{
|
{
|
||||||
StringInfo buf = context->buf;
|
StringInfo buf = context->buf;
|
||||||
Oid argtypes[FUNC_MAX_ARGS];
|
Oid argtypes[FUNC_MAX_ARGS];
|
||||||
int nargs;
|
int nargs;
|
||||||
bool use_variadic;
|
bool use_variadic = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For a combining aggregate, we look up and deparse the corresponding
|
* For a combining aggregate, we look up and deparse the corresponding
|
||||||
|
@ -6722,13 +6806,14 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
|
||||||
/* Extract the argument types as seen by the parser */
|
/* Extract the argument types as seen by the parser */
|
||||||
nargs = get_aggregate_argtypes(aggref, argtypes);
|
nargs = get_aggregate_argtypes(aggref, argtypes);
|
||||||
|
|
||||||
|
if (!funcname)
|
||||||
|
funcname = generate_function_name(aggref->aggfnoid, nargs, NIL,
|
||||||
|
argtypes, aggref->aggvariadic,
|
||||||
|
&use_variadic,
|
||||||
|
context->special_exprkind);
|
||||||
|
|
||||||
/* Print the aggregate name, schema-qualified if needed */
|
/* Print the aggregate name, schema-qualified if needed */
|
||||||
appendStringInfo(buf, "%s(%s",
|
appendStringInfo(buf, "%s(%s", funcname,
|
||||||
generate_function_name(aggref->aggfnoid, nargs,
|
|
||||||
NIL, argtypes,
|
|
||||||
aggref->aggvariadic,
|
|
||||||
&use_variadic,
|
|
||||||
context->special_exprkind),
|
|
||||||
(aggref->aggdistinct != NIL) ? "DISTINCT " : "");
|
(aggref->aggdistinct != NIL) ? "DISTINCT " : "");
|
||||||
|
|
||||||
if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
|
if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
|
||||||
|
@ -6764,7 +6849,17 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
|
||||||
if (tle->resjunk)
|
if (tle->resjunk)
|
||||||
continue;
|
continue;
|
||||||
if (i++ > 0)
|
if (i++ > 0)
|
||||||
appendStringInfoString(buf, ", ");
|
{
|
||||||
|
if (is_json_objectagg)
|
||||||
|
{
|
||||||
|
if (i > 2)
|
||||||
|
break; /* skip ABSENT ON NULL and WITH UNIQUE args */
|
||||||
|
|
||||||
|
appendStringInfoString(buf, " : ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
appendStringInfoString(buf, ", ");
|
||||||
|
}
|
||||||
if (use_variadic && i == nargs)
|
if (use_variadic && i == nargs)
|
||||||
appendStringInfoString(buf, "VARIADIC ");
|
appendStringInfoString(buf, "VARIADIC ");
|
||||||
get_rule_expr(arg, context, true);
|
get_rule_expr(arg, context, true);
|
||||||
|
@ -6778,6 +6873,9 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options)
|
||||||
|
appendStringInfoString(buf, options);
|
||||||
|
|
||||||
if (aggref->aggfilter != NULL)
|
if (aggref->aggfilter != NULL)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, ") FILTER (WHERE ");
|
appendStringInfoString(buf, ") FILTER (WHERE ");
|
||||||
|
@ -6787,6 +6885,16 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_agg_expr - Parse back an Aggref node
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
|
||||||
|
{
|
||||||
|
get_agg_expr_helper(aggref, context, original_aggref, NULL, NULL,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a helper function for get_agg_expr(). It's used when we deparse
|
* This is a helper function for get_agg_expr(). It's used when we deparse
|
||||||
* a combining Aggref; resolve_special_varno locates the corresponding partial
|
* a combining Aggref; resolve_special_varno locates the corresponding partial
|
||||||
|
@ -6806,10 +6914,12 @@ get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_windowfunc_expr - Parse back a WindowFunc node
|
* get_windowfunc_expr_helper - Parse back a WindowFunc node
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
|
get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
|
||||||
|
const char *funcname, const char *options,
|
||||||
|
bool is_json_objectagg)
|
||||||
{
|
{
|
||||||
StringInfo buf = context->buf;
|
StringInfo buf = context->buf;
|
||||||
Oid argtypes[FUNC_MAX_ARGS];
|
Oid argtypes[FUNC_MAX_ARGS];
|
||||||
|
@ -6833,16 +6943,30 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
|
||||||
nargs++;
|
nargs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
appendStringInfo(buf, "%s(",
|
if (!funcname)
|
||||||
generate_function_name(wfunc->winfnoid, nargs,
|
funcname = generate_function_name(wfunc->winfnoid, nargs, argnames,
|
||||||
argnames, argtypes,
|
argtypes, false, NULL,
|
||||||
false, NULL,
|
context->special_exprkind);
|
||||||
context->special_exprkind));
|
|
||||||
|
appendStringInfo(buf, "%s(", funcname);
|
||||||
|
|
||||||
/* winstar can be set only in zero-argument aggregates */
|
/* winstar can be set only in zero-argument aggregates */
|
||||||
if (wfunc->winstar)
|
if (wfunc->winstar)
|
||||||
appendStringInfoChar(buf, '*');
|
appendStringInfoChar(buf, '*');
|
||||||
else
|
else
|
||||||
get_rule_expr((Node *) wfunc->args, context, true);
|
{
|
||||||
|
if (is_json_objectagg)
|
||||||
|
{
|
||||||
|
get_rule_expr((Node *) linitial(wfunc->args), context, false);
|
||||||
|
appendStringInfoString(buf, " : ");
|
||||||
|
get_rule_expr((Node *) lsecond(wfunc->args), context, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
get_rule_expr((Node *) wfunc->args, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options)
|
||||||
|
appendStringInfoString(buf, options);
|
||||||
|
|
||||||
if (wfunc->aggfilter != NULL)
|
if (wfunc->aggfilter != NULL)
|
||||||
{
|
{
|
||||||
|
@ -6879,6 +7003,14 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_windowfunc_expr - Parse back a WindowFunc node
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
|
||||||
|
{
|
||||||
|
get_windowfunc_expr_helper(wfunc, context, NULL, NULL, false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_func_sql_syntax - Parse back a SQL-syntax function call
|
* get_func_sql_syntax - Parse back a SQL-syntax function call
|
||||||
|
@ -7120,6 +7252,30 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_json_agg_constructor - Parse back an aggregate JsonConstructorExpr node
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_json_agg_constructor(JsonConstructorExpr *ctor, deparse_context *context,
|
||||||
|
const char *funcname, bool is_json_objectagg)
|
||||||
|
{
|
||||||
|
StringInfoData options;
|
||||||
|
|
||||||
|
initStringInfo(&options);
|
||||||
|
get_json_constructor_options(ctor, &options);
|
||||||
|
|
||||||
|
if (IsA(ctor->func, Aggref))
|
||||||
|
get_agg_expr_helper((Aggref *) ctor->func, context,
|
||||||
|
(Aggref *) ctor->func,
|
||||||
|
funcname, options.data, is_json_objectagg);
|
||||||
|
else if (IsA(ctor->func, WindowFunc))
|
||||||
|
get_windowfunc_expr_helper((WindowFunc *) ctor->func, context,
|
||||||
|
funcname, options.data,
|
||||||
|
is_json_objectagg);
|
||||||
|
else
|
||||||
|
elog(ERROR, "invalid JsonConstructorExpr underlying node type: %d",
|
||||||
|
nodeTag(ctor->func));
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* get_coercion_expr
|
* get_coercion_expr
|
||||||
|
|
Loading…
Reference in New Issue