Ruleutils_17 Add SQL/JSON query functions

Relevant PG commit:
6185c9737cf48c9540782d88f12bd2912d6ca1cc
6185c9737c
m3hm3t/pg17_isolation_test_cmd_from
naisila 2024-07-25 16:16:37 +02:00
parent 68893674e0
commit d2648f4988
No known key found for this signature in database
GPG Key ID: A824BA9862D73E6D
1 changed files with 139 additions and 0 deletions

View File

@ -445,6 +445,8 @@ static void get_const_expr(Const *constval, deparse_context *context,
int showtype); int showtype);
static void get_const_collation(Const *constval, deparse_context *context); static void get_const_collation(Const *constval, deparse_context *context);
static void get_json_format(JsonFormat *format, StringInfo buf); static void get_json_format(JsonFormat *format, StringInfo buf);
static void get_json_returning(JsonReturning *returning, StringInfo buf,
bool json_format_by_default);
static void get_json_constructor(JsonConstructorExpr *ctor, static void get_json_constructor(JsonConstructorExpr *ctor,
deparse_context *context, bool showimplicit); deparse_context *context, bool showimplicit);
static void get_json_constructor_options(JsonConstructorExpr *ctor, static void get_json_constructor_options(JsonConstructorExpr *ctor,
@ -484,6 +486,8 @@ static char *generate_function_name(Oid funcid, int nargs,
bool has_variadic, bool *use_variadic_p, bool has_variadic, bool *use_variadic_p,
ParseExprKind special_exprkind); ParseExprKind special_exprkind);
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,
bool showimplicit);
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ") #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
@ -5191,6 +5195,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_MergeSupportFunc: case T_MergeSupportFunc:
case T_FuncExpr: case T_FuncExpr:
case T_JsonConstructorExpr: case T_JsonConstructorExpr:
case T_JsonExpr:
/* function-like: name(..) or name[..] */ /* function-like: name(..) or name[..] */
return true; return true;
@ -5362,6 +5367,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_GroupingFunc: /* own parentheses */ case T_GroupingFunc: /* own parentheses */
case T_WindowFunc: /* own parentheses */ case T_WindowFunc: /* own parentheses */
case T_CaseExpr: /* other separators */ case T_CaseExpr: /* other separators */
case T_JsonExpr: /* own parentheses */
return true; return true;
default: default:
return false; return false;
@ -5475,6 +5481,65 @@ get_rule_expr_paren(Node *node, deparse_context *context,
appendStringInfoChar(context->buf, ')'); appendStringInfoChar(context->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->expr, context, false);
appendStringInfo(context->buf, " ON %s", on);
}
/*
* get_json_expr_options
*
* Parse back common options for JSON_QUERY, JSON_VALUE, JSON_EXISTS.
*/
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->on_empty && jsexpr->on_empty->btype != default_behavior)
get_json_behavior(jsexpr->on_empty, context, "EMPTY");
if (jsexpr->on_error && jsexpr->on_error->btype != default_behavior)
get_json_behavior(jsexpr->on_error, context, "ERROR");
}
/* ---------- /* ----------
* get_rule_expr - Parse back an expression * get_rule_expr - Parse back an expression
* *
@ -6753,6 +6818,67 @@ get_rule_expr(Node *node, deparse_context *context,
} }
break; break;
case T_JsonExpr:
{
JsonExpr *jexpr = (JsonExpr *) node;
switch (jexpr->op)
{
case JSON_EXISTS_OP:
appendStringInfoString(buf, "JSON_EXISTS(");
break;
case JSON_QUERY_OP:
appendStringInfoString(buf, "JSON_QUERY(");
break;
case JSON_VALUE_OP:
appendStringInfoString(buf, "JSON_VALUE(");
break;
default:
elog(ERROR, "unrecognized JsonExpr op: %d",
(int) jexpr->op);
}
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_NULL :
JSON_BEHAVIOR_FALSE);
appendStringInfoString(buf, ")");
}
break;
case T_List: case T_List:
{ {
char *sep; char *sep;
@ -6880,6 +7006,7 @@ looks_like_function(Node *node)
case T_MinMaxExpr: case T_MinMaxExpr:
case T_SQLValueFunction: case T_SQLValueFunction:
case T_XmlExpr: case T_XmlExpr:
case T_JsonExpr:
/* these are all accepted by func_expr_common_subexpr */ /* these are all accepted by func_expr_common_subexpr */
return true; return true;
default: default:
@ -7792,6 +7919,18 @@ get_const_collation(Const *constval, 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 * get_json_format - Parse back a JsonFormat node
*/ */