mirror of https://github.com/citusdata/citus.git
Ruleutils_17 Add basic JSON_TABLE() functionality
Relevant PG commit:
de3600452b61d1bc3967e9e37e86db8956c8f577
de3600452b
m3hm3t/pg17_isolation_test_cmd_from
parent
6b4889f7b4
commit
662fc76ec9
|
@ -488,6 +488,8 @@ static char *generate_function_name(Oid funcid, int nargs,
|
||||||
static List *get_insert_column_names_list(List *targetList, StringInfo buf, deparse_context *context, RangeTblEntry *rte);
|
static List *get_insert_column_names_list(List *targetList, StringInfo buf, deparse_context *context, RangeTblEntry *rte);
|
||||||
static void get_json_path_spec(Node *path_spec, deparse_context *context,
|
static void get_json_path_spec(Node *path_spec, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
|
static void get_json_table_columns(TableFunc *tf, deparse_context *context,
|
||||||
|
bool showimplicit);
|
||||||
|
|
||||||
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
|
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
|
||||||
|
|
||||||
|
@ -5553,7 +5555,8 @@ get_json_behavior(JsonBehavior *behavior, deparse_context *context,
|
||||||
/*
|
/*
|
||||||
* get_json_expr_options
|
* get_json_expr_options
|
||||||
*
|
*
|
||||||
* Parse back common options for JSON_QUERY, JSON_VALUE, JSON_EXISTS.
|
* Parse back common options for JSON_QUERY, JSON_VALUE, JSON_EXISTS and
|
||||||
|
* JSON_TABLE columns.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_json_expr_options(JsonExpr *jsexpr, deparse_context *context,
|
get_json_expr_options(JsonExpr *jsexpr, deparse_context *context,
|
||||||
|
@ -8284,16 +8287,14 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* get_tablefunc - Parse back a table function
|
* get_xmltable - Parse back a XMLTABLE function
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
|
get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit)
|
||||||
{
|
{
|
||||||
StringInfo buf = context->buf;
|
StringInfo buf = context->buf;
|
||||||
|
|
||||||
/* XMLTABLE is the only existing implementation. */
|
|
||||||
|
|
||||||
appendStringInfoString(buf, "XMLTABLE(");
|
appendStringInfoString(buf, "XMLTABLE(");
|
||||||
|
|
||||||
if (tf->ns_uris != NIL)
|
if (tf->ns_uris != NIL)
|
||||||
|
@ -8384,6 +8385,180 @@ get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_json_table_columns - Parse back JSON_TABLE columns
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_json_table_columns(TableFunc *tf, 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_colvalexpr;
|
||||||
|
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_colvalexpr, 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_colvalexpr));
|
||||||
|
|
||||||
|
if (colnum > 0)
|
||||||
|
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 (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);
|
||||||
|
JsonTablePathScan *root = castNode(JsonTablePathScan, 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->value, context, -1);
|
||||||
|
|
||||||
|
appendStringInfo(buf, " AS %s", quote_identifier(root->path->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, context, showimplicit);
|
||||||
|
|
||||||
|
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
|
* get_from_clause - Parse back a FROM clause
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue