aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c719
1 files changed, 24 insertions, 695 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 9959f6910e9..6594a9aac70 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -466,12 +466,6 @@ static void get_coercion_expr(Node *arg, deparse_context *context,
Node *parentNode);
static void get_const_expr(Const *constval, deparse_context *context,
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 simple_quote_literal(StringInfo buf, const char *val);
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
@@ -505,10 +499,6 @@ static char *generate_qualified_type_name(Oid typid);
static text *string_to_text(char *str);
static char *flatten_reloptions(Oid relid);
static void get_reloptions(StringInfo buf, Datum reloptions);
-static void get_json_path_spec(Node *path_spec, deparse_context *context,
- bool showimplicit);
-static void get_json_table_columns(TableFunc *tf, JsonTableParent *node,
- deparse_context *context, bool showimplicit);
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
@@ -6338,8 +6328,7 @@ get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
bool need_paren = (PRETTY_PAREN(context)
|| IsA(expr, FuncExpr)
|| IsA(expr, Aggref)
- || IsA(expr, WindowFunc)
- || IsA(expr, JsonConstructorExpr));
+ || IsA(expr, WindowFunc));
if (need_paren)
appendStringInfoChar(context->buf, '(');
@@ -8198,8 +8187,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_GroupingFunc:
case T_WindowFunc:
case T_FuncExpr:
- case T_JsonConstructorExpr:
- case T_JsonExpr:
/* function-like: name(..) or name[..] */
return true;
@@ -8293,7 +8280,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_NullTest:
case T_BooleanTest:
case T_DistinctExpr:
- case T_JsonIsPredicate:
switch (nodeTag(parentNode))
{
case T_FuncExpr:
@@ -8318,7 +8304,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_GroupingFunc: /* own parentheses */
case T_WindowFunc: /* own parentheses */
case T_CaseExpr: /* other separators */
- case T_JsonExpr: /* own parentheses */
return true;
default:
return false;
@@ -8375,11 +8360,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
return false;
}
- case T_JsonValueExpr:
- /* maybe simple, check args */
- return isSimpleNode((Node *) ((JsonValueExpr *) node)->raw_expr,
- node, prettyFlags);
-
default:
break;
}
@@ -8486,122 +8466,6 @@ get_rule_expr_paren(Node *node, deparse_context *context,
}
-/*
- * get_json_path_spec - Parse back a JSON path specification
- */
-static void
-get_json_path_spec(Node *path_spec, deparse_context *context, bool showimplicit)
-{
- if (IsA(path_spec, Const))
- get_const_expr((Const *) path_spec, context, -1);
- else
- get_rule_expr(path_spec, context, showimplicit);
-}
-
-/*
- * get_json_format - Parse back a JsonFormat node
- */
-static void
-get_json_format(JsonFormat *format, StringInfo buf)
-{
- if (format->format_type == JS_FORMAT_DEFAULT)
- return;
-
- appendStringInfoString(buf,
- format->format_type == JS_FORMAT_JSONB ?
- " FORMAT JSONB" : " FORMAT JSON");
-
- if (format->encoding != JS_ENC_DEFAULT)
- {
- const char *encoding =
- format->encoding == JS_ENC_UTF16 ? "UTF16" :
- format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
-
- appendStringInfo(buf, " ENCODING %s", encoding);
- }
-}
-
-/*
- * get_json_returning - Parse back a JsonReturning structure
- */
-static void
-get_json_returning(JsonReturning *returning, StringInfo buf,
- bool json_format_by_default)
-{
- if (!OidIsValid(returning->typid))
- return;
-
- appendStringInfo(buf, " RETURNING %s",
- format_type_with_typemod(returning->typid,
- returning->typmod));
-
- if (!json_format_by_default ||
- returning->format->format_type !=
- (returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
- get_json_format(returning->format, buf);
-}
-
-static void
-get_json_behavior(JsonBehavior *behavior, deparse_context *context,
- const char *on)
-{
- /*
- * The order of array elements must correspond to the order of
- * JsonBehaviorType members.
- */
- const char *behavior_names[] =
- {
- " NULL",
- " ERROR",
- " EMPTY",
- " TRUE",
- " FALSE",
- " UNKNOWN",
- " EMPTY ARRAY",
- " EMPTY OBJECT",
- " DEFAULT "
- };
-
- if ((int) behavior->btype < 0 || behavior->btype >= lengthof(behavior_names))
- elog(ERROR, "invalid json behavior type: %d", behavior->btype);
-
- appendStringInfoString(context->buf, behavior_names[behavior->btype]);
-
- if (behavior->btype == JSON_BEHAVIOR_DEFAULT)
- get_rule_expr(behavior->default_expr, context, false);
-
- appendStringInfo(context->buf, " ON %s", on);
-}
-
-/*
- * get_json_expr_options
- *
- * Parse back common options for JSON_QUERY, JSON_VALUE, JSON_EXISTS and
- * JSON_TABLE columns.
- */
-static void
-get_json_expr_options(JsonExpr *jsexpr, deparse_context *context,
- JsonBehaviorType default_behavior)
-{
- if (jsexpr->op == JSON_QUERY_OP)
- {
- if (jsexpr->wrapper == JSW_CONDITIONAL)
- appendStringInfo(context->buf, " WITH CONDITIONAL WRAPPER");
- else if (jsexpr->wrapper == JSW_UNCONDITIONAL)
- appendStringInfo(context->buf, " WITH UNCONDITIONAL WRAPPER");
-
- if (jsexpr->omit_quotes)
- appendStringInfo(context->buf, " OMIT QUOTES");
- }
-
- if (jsexpr->op != JSON_EXISTS_OP &&
- jsexpr->on_empty->btype != default_behavior)
- get_json_behavior(jsexpr->on_empty, context, "EMPTY");
-
- if (jsexpr->on_error->btype != default_behavior)
- get_json_behavior(jsexpr->on_error, context, "ERROR");
-}
-
/* ----------
* get_rule_expr - Parse back an expression
*
@@ -9760,116 +9624,6 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
-
- case T_JsonValueExpr:
- {
- JsonValueExpr *jve = (JsonValueExpr *) node;
-
- get_rule_expr((Node *) jve->raw_expr, context, false);
- get_json_format(jve->format, context->buf);
- }
- break;
-
- case T_JsonConstructorExpr:
- get_json_constructor((JsonConstructorExpr *) node, context, false);
- break;
-
- case T_JsonIsPredicate:
- {
- JsonIsPredicate *pred = (JsonIsPredicate *) node;
-
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(context->buf, '(');
-
- get_rule_expr_paren(pred->expr, context, true, node);
-
- appendStringInfoString(context->buf, " IS JSON");
-
- /* TODO: handle FORMAT clause */
-
- switch (pred->item_type)
- {
- case JS_TYPE_SCALAR:
- appendStringInfoString(context->buf, " SCALAR");
- break;
- case JS_TYPE_ARRAY:
- appendStringInfoString(context->buf, " ARRAY");
- break;
- case JS_TYPE_OBJECT:
- appendStringInfoString(context->buf, " OBJECT");
- break;
- default:
- break;
- }
-
- if (pred->unique_keys)
- appendStringInfoString(context->buf, " WITH UNIQUE KEYS");
-
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(context->buf, ')');
- }
- break;
-
- case T_JsonExpr:
- {
- JsonExpr *jexpr = (JsonExpr *) node;
-
- switch (jexpr->op)
- {
- case JSON_QUERY_OP:
- appendStringInfoString(buf, "JSON_QUERY(");
- break;
- case JSON_VALUE_OP:
- appendStringInfoString(buf, "JSON_VALUE(");
- break;
- case JSON_EXISTS_OP:
- appendStringInfoString(buf, "JSON_EXISTS(");
- break;
- default:
- elog(ERROR, "unexpected JsonExpr type: %d", jexpr->op);
- break;
- }
-
- get_rule_expr(jexpr->formatted_expr, context, showimplicit);
-
- appendStringInfoString(buf, ", ");
-
- get_json_path_spec(jexpr->path_spec, context, showimplicit);
-
- if (jexpr->passing_values)
- {
- ListCell *lc1,
- *lc2;
- bool needcomma = false;
-
- appendStringInfoString(buf, " PASSING ");
-
- forboth(lc1, jexpr->passing_names,
- lc2, jexpr->passing_values)
- {
- if (needcomma)
- appendStringInfoString(buf, ", ");
- needcomma = true;
-
- get_rule_expr((Node *) lfirst(lc2), context, showimplicit);
- appendStringInfo(buf, " AS %s",
- ((String *) lfirst_node(String, lc1))->sval);
- }
- }
-
- if (jexpr->op != JSON_EXISTS_OP ||
- jexpr->returning->typid != BOOLOID)
- get_json_returning(jexpr->returning, context->buf,
- jexpr->op == JSON_QUERY_OP);
-
- get_json_expr_options(jexpr, context,
- jexpr->op == JSON_EXISTS_OP ?
- JSON_BEHAVIOR_FALSE : JSON_BEHAVIOR_NULL);
-
- appendStringInfoString(buf, ")");
- }
- break;
-
case T_List:
{
char *sep;
@@ -9993,7 +9747,6 @@ looks_like_function(Node *node)
case T_MinMaxExpr:
case T_SQLValueFunction:
case T_XmlExpr:
- case T_JsonExpr:
/* these are all accepted by func_expr_common_subexpr */
return true;
default:
@@ -10139,103 +9892,17 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
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");
-
- if (!((ctor->type == JSCTOR_JSON_PARSE ||
- ctor->type == JSCTOR_JSON_SCALAR) &&
- ctor->returning->typid == JSONOID))
- 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_PARSE:
- funcname = "JSON";
- break;
- case JSCTOR_JSON_SCALAR:
- funcname = "JSON_SCALAR";
- break;
- case JSCTOR_JSON_SERIALIZE:
- funcname = "JSON_SERIALIZE";
- break;
- 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_agg_expr_helper - Parse back an Aggref node
+ * get_agg_expr - Parse back an Aggref node
*/
static void
-get_agg_expr_helper(Aggref *aggref, deparse_context *context,
- Aggref *original_aggref, const char *funcname,
- const char *options, bool is_json_objectagg)
+get_agg_expr(Aggref *aggref, deparse_context *context,
+ Aggref *original_aggref)
{
StringInfo buf = context->buf;
Oid argtypes[FUNC_MAX_ARGS];
int nargs;
- bool use_variadic = false;
+ bool use_variadic;
/*
* For a combining aggregate, we look up and deparse the corresponding
@@ -10265,14 +9932,13 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
/* Extract the argument types as seen by the parser */
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 */
- appendStringInfo(buf, "%s(%s", funcname,
+ appendStringInfo(buf, "%s(%s",
+ generate_function_name(aggref->aggfnoid, nargs,
+ NIL, argtypes,
+ aggref->aggvariadic,
+ &use_variadic,
+ context->special_exprkind),
(aggref->aggdistinct != NIL) ? "DISTINCT " : "");
if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
@@ -10308,18 +9974,7 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
if (tle->resjunk)
continue;
if (i++ > 0)
- {
- if (is_json_objectagg)
- {
- if (i > 2)
- break; /* skip ABSENT ON NULL and WITH UNIQUE
- * args */
-
- appendStringInfoString(buf, " : ");
- }
- else
- appendStringInfoString(buf, ", ");
- }
+ appendStringInfoString(buf, ", ");
if (use_variadic && i == nargs)
appendStringInfoString(buf, "VARIADIC ");
get_rule_expr(arg, context, true);
@@ -10333,9 +9988,6 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
}
}
- if (options)
- appendStringInfoString(buf, options);
-
if (aggref->aggfilter != NULL)
{
appendStringInfoString(buf, ") FILTER (WHERE ");
@@ -10346,16 +9998,6 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
}
/*
- * 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
* a combining Aggref; resolve_special_varno locates the corresponding partial
* Aggref and then calls this.
@@ -10374,12 +10016,10 @@ get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
}
/*
- * get_windowfunc_expr_helper - Parse back a WindowFunc node
+ * get_windowfunc_expr - Parse back a WindowFunc node
*/
static void
-get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
- const char *funcname, const char *options,
- bool is_json_objectagg)
+get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
{
StringInfo buf = context->buf;
Oid argtypes[FUNC_MAX_ARGS];
@@ -10403,30 +10043,16 @@ get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
nargs++;
}
- if (!funcname)
- funcname = generate_function_name(wfunc->winfnoid, nargs, argnames,
- argtypes, false, NULL,
- context->special_exprkind);
-
- appendStringInfo(buf, "%s(", funcname);
-
+ appendStringInfo(buf, "%s(",
+ generate_function_name(wfunc->winfnoid, nargs,
+ argnames, argtypes,
+ false, NULL,
+ context->special_exprkind));
/* winstar can be set only in zero-argument aggregates */
if (wfunc->winstar)
appendStringInfoChar(buf, '*');
else
- {
- 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);
+ get_rule_expr((Node *) wfunc->args, context, true);
if (wfunc->aggfilter != NULL)
{
@@ -10464,15 +10090,6 @@ get_windowfunc_expr_helper(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
*
* Returns true if we successfully deparsed, false if we did not
@@ -10712,31 +10329,6 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
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
*
@@ -11106,14 +10698,16 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
/* ----------
- * get_xmltable - Parse back a XMLTABLE function
+ * get_tablefunc - Parse back a table function
* ----------
*/
static void
-get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit)
+get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
{
StringInfo buf = context->buf;
+ /* XMLTABLE is the only existing implementation. */
+
appendStringInfoString(buf, "XMLTABLE(");
if (tf->ns_uris != NIL)
@@ -11204,271 +10798,6 @@ get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit)
appendStringInfoChar(buf, ')');
}
-/*
- * get_json_nested_columns - Parse back nested JSON_TABLE columns
- */
-static void
-get_json_table_nested_columns(TableFunc *tf, Node *node,
- deparse_context *context, bool showimplicit,
- bool needcomma)
-{
- if (IsA(node, JsonTableSibling))
- {
- JsonTableSibling *n = (JsonTableSibling *) node;
-
- get_json_table_nested_columns(tf, n->larg, context, showimplicit,
- needcomma);
- get_json_table_nested_columns(tf, n->rarg, context, showimplicit, true);
- }
- else
- {
- JsonTableParent *n = castNode(JsonTableParent, node);
-
- if (needcomma)
- appendStringInfoChar(context->buf, ',');
-
- appendStringInfoChar(context->buf, ' ');
- appendContextKeyword(context, "NESTED PATH ", 0, 0, 0);
- get_const_expr(n->path, context, -1);
- appendStringInfo(context->buf, " AS %s", quote_identifier(n->name));
- get_json_table_columns(tf, n, context, showimplicit);
- }
-}
-
-/*
- * get_json_table_plan - Parse back a JSON_TABLE plan
- */
-static void
-get_json_table_plan(TableFunc *tf, Node *node, deparse_context *context,
- bool parenthesize)
-{
- if (parenthesize)
- appendStringInfoChar(context->buf, '(');
-
- if (IsA(node, JsonTableSibling))
- {
- JsonTableSibling *n = (JsonTableSibling *) node;
-
- get_json_table_plan(tf, n->larg, context,
- IsA(n->larg, JsonTableSibling) ||
- castNode(JsonTableParent, n->larg)->child);
-
- appendStringInfoString(context->buf, n->cross ? " CROSS " : " UNION ");
-
- get_json_table_plan(tf, n->rarg, context,
- IsA(n->rarg, JsonTableSibling) ||
- castNode(JsonTableParent, n->rarg)->child);
- }
- else
- {
- JsonTableParent *n = castNode(JsonTableParent, node);
-
- appendStringInfoString(context->buf, quote_identifier(n->name));
-
- if (n->child)
- {
- appendStringInfoString(context->buf,
- n->outerJoin ? " OUTER " : " INNER ");
- get_json_table_plan(tf, n->child, context,
- IsA(n->child, JsonTableSibling));
- }
- }
-
- if (parenthesize)
- appendStringInfoChar(context->buf, ')');
-}
-
-/*
- * get_json_table_columns - Parse back JSON_TABLE columns
- */
-static void
-get_json_table_columns(TableFunc *tf, JsonTableParent *node,
- deparse_context *context, bool showimplicit)
-{
- StringInfo buf = context->buf;
- JsonExpr *jexpr = castNode(JsonExpr, tf->docexpr);
- ListCell *lc_colname;
- ListCell *lc_coltype;
- ListCell *lc_coltypmod;
- ListCell *lc_colvarexpr;
- int colnum = 0;
-
- appendStringInfoChar(buf, ' ');
- appendContextKeyword(context, "COLUMNS (", 0, 0, 0);
-
- if (PRETTY_INDENT(context))
- context->indentLevel += PRETTYINDENT_VAR;
-
- forfour(lc_colname, tf->colnames,
- lc_coltype, tf->coltypes,
- lc_coltypmod, tf->coltypmods,
- lc_colvarexpr, tf->colvalexprs)
- {
- char *colname = strVal(lfirst(lc_colname));
- JsonExpr *colexpr;
- Oid typid;
- int32 typmod;
- bool ordinality;
- JsonBehaviorType default_behavior;
-
- typid = lfirst_oid(lc_coltype);
- typmod = lfirst_int(lc_coltypmod);
- colexpr = castNode(JsonExpr, lfirst(lc_colvarexpr));
-
- if (colnum < node->colMin)
- {
- colnum++;
- continue;
- }
-
- if (colnum > node->colMax)
- break;
-
- if (colnum > node->colMin)
- appendStringInfoString(buf, ", ");
-
- colnum++;
-
- ordinality = !colexpr;
-
- appendContextKeyword(context, "", 0, 0, 0);
-
- appendStringInfo(buf, "%s %s", quote_identifier(colname),
- ordinality ? "FOR ORDINALITY" :
- format_type_with_typemod(typid, typmod));
- if (ordinality)
- continue;
-
- if (colexpr->op == JSON_EXISTS_OP)
- {
- appendStringInfoString(buf, " EXISTS");
- default_behavior = JSON_BEHAVIOR_FALSE;
- }
- else
- {
- if (colexpr->op == JSON_QUERY_OP)
- {
- char typcategory;
- bool typispreferred;
-
- get_type_category_preferred(typid, &typcategory, &typispreferred);
-
- if (typcategory == TYPCATEGORY_STRING)
- appendStringInfoString(buf,
- colexpr->format->format_type == JS_FORMAT_JSONB ?
- " FORMAT JSONB" : " FORMAT JSON");
- }
-
- default_behavior = JSON_BEHAVIOR_NULL;
- }
-
- if (jexpr->on_error->btype == JSON_BEHAVIOR_ERROR)
- default_behavior = JSON_BEHAVIOR_ERROR;
-
- appendStringInfoString(buf, " PATH ");
-
- get_json_path_spec(colexpr->path_spec, context, showimplicit);
-
- get_json_expr_options(colexpr, context, default_behavior);
- }
-
- if (node->child)
- get_json_table_nested_columns(tf, node->child, context, showimplicit,
- node->colMax >= node->colMin);
-
- if (PRETTY_INDENT(context))
- context->indentLevel -= PRETTYINDENT_VAR;
-
- appendContextKeyword(context, ")", 0, 0, 0);
-}
-
-/* ----------
- * get_json_table - Parse back a JSON_TABLE function
- * ----------
- */
-static void
-get_json_table(TableFunc *tf, deparse_context *context, bool showimplicit)
-{
- StringInfo buf = context->buf;
- JsonExpr *jexpr = castNode(JsonExpr, tf->docexpr);
- JsonTableParent *root = castNode(JsonTableParent, tf->plan);
-
- appendStringInfoString(buf, "JSON_TABLE(");
-
- if (PRETTY_INDENT(context))
- context->indentLevel += PRETTYINDENT_VAR;
-
- appendContextKeyword(context, "", 0, 0, 0);
-
- get_rule_expr(jexpr->formatted_expr, context, showimplicit);
-
- appendStringInfoString(buf, ", ");
-
- get_const_expr(root->path, context, -1);
-
- appendStringInfo(buf, " AS %s", quote_identifier(root->name));
-
- if (jexpr->passing_values)
- {
- ListCell *lc1,
- *lc2;
- bool needcomma = false;
-
- appendStringInfoChar(buf, ' ');
- appendContextKeyword(context, "PASSING ", 0, 0, 0);
-
- if (PRETTY_INDENT(context))
- context->indentLevel += PRETTYINDENT_VAR;
-
- forboth(lc1, jexpr->passing_names,
- lc2, jexpr->passing_values)
- {
- if (needcomma)
- appendStringInfoString(buf, ", ");
- needcomma = true;
-
- appendContextKeyword(context, "", 0, 0, 0);
-
- get_rule_expr((Node *) lfirst(lc2), context, false);
- appendStringInfo(buf, " AS %s",
- quote_identifier((lfirst_node(String, lc1))->sval)
- );
- }
-
- if (PRETTY_INDENT(context))
- context->indentLevel -= PRETTYINDENT_VAR;
- }
-
- get_json_table_columns(tf, root, context, showimplicit);
-
- appendStringInfoChar(buf, ' ');
- appendContextKeyword(context, "PLAN ", 0, 0, 0);
- get_json_table_plan(tf, (Node *) root, context, true);
-
- if (jexpr->on_error->btype != JSON_BEHAVIOR_EMPTY)
- get_json_behavior(jexpr->on_error, context, "ERROR");
-
- if (PRETTY_INDENT(context))
- context->indentLevel -= PRETTYINDENT_VAR;
-
- appendContextKeyword(context, ")", 0, 0, 0);
-}
-
-/* ----------
- * get_tablefunc - Parse back a table function
- * ----------
- */
-static void
-get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
-{
- /* XMLTABLE and JSON_TABLE are the only existing implementations. */
-
- if (tf->functype == TFT_XMLTABLE)
- get_xmltable(tf, context, showimplicit);
- else if (tf->functype == TFT_JSON_TABLE)
- get_json_table(tf, context, showimplicit);
-}
-
/* ----------
* get_from_clause - Parse back a FROM clause
*