aboutsummaryrefslogtreecommitdiff
path: root/src/backend/nodes/nodeFuncs.c
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2022-03-03 13:02:10 -0500
committerAndrew Dunstan <andrew@dunslane.net>2022-03-27 17:03:34 -0400
commitf4fb45d15c59d7add2e1b81a9d477d0119a9691a (patch)
tree9025afb61fd4409ae48cd21d47c7fd58647e2633 /src/backend/nodes/nodeFuncs.c
parentf79b803dcc98d707450e158db3638dc67ff8380b (diff)
downloadpostgresql-f4fb45d15c59d7add2e1b81a9d477d0119a9691a.tar.gz
postgresql-f4fb45d15c59d7add2e1b81a9d477d0119a9691a.zip
SQL/JSON constructors
This patch introduces the SQL/JSON standard constructors for JSON: JSON() JSON_ARRAY() JSON_ARRAYAGG() JSON_OBJECT() JSON_OBJECTAGG() For the most part these functions provide facilities that mimic existing json/jsonb functions. However, they also offer some useful additional functionality. In addition to text input, the JSON() function accepts bytea input, which it will decode and constuct a json value from. The other functions provide useful options for handling duplicate keys and null values. This series of patches will be followed by a consolidated documentation patch. Nikita Glukhov Reviewers have included (in no particular order) Andres Freund, Alexander Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu, Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby. Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru
Diffstat (limited to 'src/backend/nodes/nodeFuncs.c')
-rw-r--r--src/backend/nodes/nodeFuncs.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 0b242c76eca..25cf282aab2 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -257,6 +257,9 @@ exprType(const Node *expr)
type = exprType((Node *) (jve->formatted_expr ? jve->formatted_expr : jve->raw_expr));
}
break;
+ case T_JsonConstructorExpr:
+ type = ((const JsonConstructorExpr *) expr)->returning->typid;
+ break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
type = InvalidOid; /* keep compiler quiet */
@@ -491,6 +494,8 @@ exprTypmod(const Node *expr)
return exprTypmod((Node *) ((const PlaceHolderVar *) expr)->phexpr);
case T_JsonValueExpr:
return exprTypmod((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
+ case T_JsonConstructorExpr:
+ return -1; /* ((const JsonConstructorExpr *) expr)->returning->typmod; */
default:
break;
}
@@ -970,6 +975,16 @@ exprCollation(const Node *expr)
case T_JsonValueExpr:
coll = exprCollation((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
break;
+ case T_JsonConstructorExpr:
+ {
+ const JsonConstructorExpr *ctor = (const JsonConstructorExpr *) expr;
+
+ if (ctor->coercion)
+ coll = exprCollation((Node *) ctor->coercion);
+ else
+ coll = InvalidOid;
+ }
+ break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
coll = InvalidOid; /* keep compiler quiet */
@@ -1186,6 +1201,16 @@ exprSetCollation(Node *expr, Oid collation)
exprSetCollation((Node *) ((JsonValueExpr *) expr)->formatted_expr,
collation);
break;
+ case T_JsonConstructorExpr:
+ {
+ JsonConstructorExpr *ctor = (JsonConstructorExpr *) expr;
+
+ if (ctor->coercion)
+ exprSetCollation((Node *) ctor->coercion, collation);
+ else
+ Assert(!OidIsValid(collation)); /* result is always a json[b] type */
+ }
+ break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
break;
@@ -1635,6 +1660,9 @@ exprLocation(const Node *expr)
case T_JsonValueExpr:
loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->raw_expr);
break;
+ case T_JsonConstructorExpr:
+ loc = ((const JsonConstructorExpr *) expr)->location;
+ break;
default:
/* for any other node type it's just unknown... */
loc = -1;
@@ -2379,6 +2407,18 @@ expression_tree_walker(Node *node,
return true;
}
break;
+ case T_JsonConstructorExpr:
+ {
+ JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
+
+ if (walker(ctor->args, context))
+ return true;
+ if (walker(ctor->func, context))
+ return true;
+ if (walker(ctor->coercion, context))
+ return true;
+ }
+ break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));
@@ -3363,6 +3403,19 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
+ case T_JsonConstructorExpr:
+ {
+ JsonConstructorExpr *jve = (JsonConstructorExpr *) node;
+ JsonConstructorExpr *newnode;
+
+ FLATCOPY(newnode, jve, JsonConstructorExpr);
+ MUTATE(newnode->args, jve->args, List *);
+ MUTATE(newnode->func, jve->func, Expr *);
+ MUTATE(newnode->coercion, jve->coercion, Expr *);
+ MUTATE(newnode->returning, jve->returning, JsonReturning *);
+
+ return (Node *) newnode;
+ }
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));
@@ -3637,6 +3690,7 @@ raw_expression_tree_walker(Node *node,
case T_ParamRef:
case T_A_Const:
case T_A_Star:
+ case T_JsonFormat:
/* primitive node types with no subnodes */
break;
case T_Alias:
@@ -4085,6 +4139,104 @@ raw_expression_tree_walker(Node *node,
return true;
}
break;
+ case T_JsonConstructorExpr:
+ {
+ JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
+
+ if (walker(ctor->args, context))
+ return true;
+ if (walker(ctor->func, context))
+ return true;
+ if (walker(ctor->coercion, context))
+ return true;
+ if (walker(ctor->returning, context))
+ return true;
+ }
+ break;
+ case T_JsonOutput:
+ {
+ JsonOutput *out = (JsonOutput *) node;
+
+ if (walker(out->typeName, context))
+ return true;
+ if (walker(out->returning, context))
+ return true;
+ }
+ break;
+ case T_JsonKeyValue:
+ {
+ JsonKeyValue *jkv = (JsonKeyValue *) node;
+
+ if (walker(jkv->key, context))
+ return true;
+ if (walker(jkv->value, context))
+ return true;
+ }
+ break;
+ case T_JsonObjectConstructor:
+ {
+ JsonObjectConstructor *joc = (JsonObjectConstructor *) node;
+
+ if (walker(joc->output, context))
+ return true;
+ if (walker(joc->exprs, context))
+ return true;
+ }
+ break;
+ case T_JsonArrayConstructor:
+ {
+ JsonArrayConstructor *jac = (JsonArrayConstructor *) node;
+
+ if (walker(jac->output, context))
+ return true;
+ if (walker(jac->exprs, context))
+ return true;
+ }
+ break;
+ case T_JsonAggConstructor:
+ {
+ JsonAggConstructor *ctor = (JsonAggConstructor *) node;
+
+ if (walker(ctor->output, context))
+ return true;
+ if (walker(ctor->agg_order, context))
+ return true;
+ if (walker(ctor->agg_filter, context))
+ return true;
+ if (walker(ctor->over, context))
+ return true;
+ }
+ break;
+ case T_JsonObjectAgg:
+ {
+ JsonObjectAgg *joa = (JsonObjectAgg *) node;
+
+ if (walker(joa->constructor, context))
+ return true;
+ if (walker(joa->arg, context))
+ return true;
+ }
+ break;
+ case T_JsonArrayAgg:
+ {
+ JsonArrayAgg *jaa = (JsonArrayAgg *) node;
+
+ if (walker(jaa->constructor, context))
+ return true;
+ if (walker(jaa->arg, context))
+ return true;
+ }
+ break;
+ case T_JsonArrayQueryConstructor:
+ {
+ JsonArrayQueryConstructor *jaqc = (JsonArrayQueryConstructor *) node;
+
+ if (walker(jaqc->output, context))
+ return true;
+ if (walker(jaqc->query, context))
+ return true;
+ }
+ break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));