mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
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
This commit is contained in:
@@ -2344,6 +2344,152 @@ _copyJsonValueExpr(const JsonValueExpr *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonConstructorExpr
|
||||
*/
|
||||
static JsonConstructorExpr *
|
||||
_copyJsonConstructorExpr(const JsonConstructorExpr *from)
|
||||
{
|
||||
JsonConstructorExpr *newnode = makeNode(JsonConstructorExpr);
|
||||
|
||||
COPY_SCALAR_FIELD(type);
|
||||
COPY_NODE_FIELD(args);
|
||||
COPY_NODE_FIELD(func);
|
||||
COPY_NODE_FIELD(coercion);
|
||||
COPY_NODE_FIELD(returning);
|
||||
COPY_SCALAR_FIELD(absent_on_null);
|
||||
COPY_SCALAR_FIELD(unique);
|
||||
COPY_LOCATION_FIELD(location);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonKeyValue
|
||||
*/
|
||||
static JsonKeyValue *
|
||||
_copyJsonKeyValue(const JsonKeyValue *from)
|
||||
{
|
||||
JsonKeyValue *newnode = makeNode(JsonKeyValue);
|
||||
|
||||
COPY_NODE_FIELD(key);
|
||||
COPY_NODE_FIELD(value);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonObjectConstructor
|
||||
*/
|
||||
static JsonObjectConstructor *
|
||||
_copyJsonObjectConstructor(const JsonObjectConstructor *from)
|
||||
{
|
||||
JsonObjectConstructor *newnode = makeNode(JsonObjectConstructor);
|
||||
|
||||
COPY_NODE_FIELD(exprs);
|
||||
COPY_NODE_FIELD(output);
|
||||
COPY_SCALAR_FIELD(absent_on_null);
|
||||
COPY_SCALAR_FIELD(unique);
|
||||
COPY_LOCATION_FIELD(location);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonAggConstructor
|
||||
*/
|
||||
static JsonAggConstructor *
|
||||
_copyJsonAggConstructor(const JsonAggConstructor *from)
|
||||
{
|
||||
JsonAggConstructor *newnode = makeNode(JsonAggConstructor);
|
||||
|
||||
COPY_NODE_FIELD(output);
|
||||
COPY_NODE_FIELD(agg_filter);
|
||||
COPY_NODE_FIELD(agg_order);
|
||||
COPY_NODE_FIELD(over);
|
||||
COPY_LOCATION_FIELD(location);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonObjectAgg
|
||||
*/
|
||||
static JsonObjectAgg *
|
||||
_copyJsonObjectAgg(const JsonObjectAgg *from)
|
||||
{
|
||||
JsonObjectAgg *newnode = makeNode(JsonObjectAgg);
|
||||
|
||||
COPY_NODE_FIELD(constructor);
|
||||
COPY_NODE_FIELD(arg);
|
||||
COPY_SCALAR_FIELD(absent_on_null);
|
||||
COPY_SCALAR_FIELD(unique);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonOutput
|
||||
*/
|
||||
static JsonOutput *
|
||||
_copyJsonOutput(const JsonOutput *from)
|
||||
{
|
||||
JsonOutput *newnode = makeNode(JsonOutput);
|
||||
|
||||
COPY_NODE_FIELD(typeName);
|
||||
COPY_NODE_FIELD(returning);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonArrayConstructor
|
||||
*/
|
||||
static JsonArrayConstructor *
|
||||
_copyJsonArrayConstructor(const JsonArrayConstructor *from)
|
||||
{
|
||||
JsonArrayConstructor *newnode = makeNode(JsonArrayConstructor);
|
||||
|
||||
COPY_NODE_FIELD(exprs);
|
||||
COPY_NODE_FIELD(output);
|
||||
COPY_SCALAR_FIELD(absent_on_null);
|
||||
COPY_LOCATION_FIELD(location);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonArrayAgg
|
||||
*/
|
||||
static JsonArrayAgg *
|
||||
_copyJsonArrayAgg(const JsonArrayAgg *from)
|
||||
{
|
||||
JsonArrayAgg *newnode = makeNode(JsonArrayAgg);
|
||||
|
||||
COPY_NODE_FIELD(constructor);
|
||||
COPY_NODE_FIELD(arg);
|
||||
COPY_SCALAR_FIELD(absent_on_null);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyJsonArrayQueryConstructor
|
||||
*/
|
||||
static JsonArrayQueryConstructor *
|
||||
_copyJsonArrayQueryConstructor(const JsonArrayQueryConstructor *from)
|
||||
{
|
||||
JsonArrayQueryConstructor *newnode = makeNode(JsonArrayQueryConstructor);
|
||||
|
||||
COPY_NODE_FIELD(query);
|
||||
COPY_NODE_FIELD(output);
|
||||
COPY_NODE_FIELD(format);
|
||||
COPY_SCALAR_FIELD(absent_on_null);
|
||||
COPY_LOCATION_FIELD(location);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* pathnodes.h copy functions
|
||||
*
|
||||
@@ -5406,6 +5552,33 @@ copyObjectImpl(const void *from)
|
||||
case T_JsonValueExpr:
|
||||
retval = _copyJsonValueExpr(from);
|
||||
break;
|
||||
case T_JsonKeyValue:
|
||||
retval = _copyJsonKeyValue(from);
|
||||
break;
|
||||
case T_JsonConstructorExpr:
|
||||
retval = _copyJsonConstructorExpr(from);
|
||||
break;
|
||||
case T_JsonObjectConstructor:
|
||||
retval = _copyJsonObjectConstructor(from);
|
||||
break;
|
||||
case T_JsonAggConstructor:
|
||||
retval = _copyJsonAggConstructor(from);
|
||||
break;
|
||||
case T_JsonObjectAgg:
|
||||
retval = _copyJsonObjectAgg(from);
|
||||
break;
|
||||
case T_JsonOutput:
|
||||
retval = _copyJsonOutput(from);
|
||||
break;
|
||||
case T_JsonArrayConstructor:
|
||||
retval = _copyJsonArrayConstructor(from);
|
||||
break;
|
||||
case T_JsonArrayQueryConstructor:
|
||||
retval = _copyJsonArrayQueryConstructor(from);
|
||||
break;
|
||||
case T_JsonArrayAgg:
|
||||
retval = _copyJsonArrayAgg(from);
|
||||
break;
|
||||
|
||||
/*
|
||||
* RELATION NODES
|
||||
|
||||
@@ -871,6 +871,111 @@ _equalJsonValueExpr(const JsonValueExpr *a, const JsonValueExpr *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonConstructorExpr(const JsonConstructorExpr *a, const JsonConstructorExpr *b)
|
||||
{
|
||||
COMPARE_SCALAR_FIELD(type);
|
||||
COMPARE_NODE_FIELD(args);
|
||||
COMPARE_NODE_FIELD(func);
|
||||
COMPARE_NODE_FIELD(coercion);
|
||||
COMPARE_NODE_FIELD(returning);
|
||||
COMPARE_SCALAR_FIELD(absent_on_null);
|
||||
COMPARE_SCALAR_FIELD(unique);
|
||||
COMPARE_LOCATION_FIELD(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonKeyValue(const JsonKeyValue *a, const JsonKeyValue *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(key);
|
||||
COMPARE_NODE_FIELD(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonObjectConstructor(const JsonObjectConstructor *a,
|
||||
const JsonObjectConstructor *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(exprs);
|
||||
COMPARE_NODE_FIELD(output);
|
||||
COMPARE_SCALAR_FIELD(absent_on_null);
|
||||
COMPARE_SCALAR_FIELD(unique);
|
||||
COMPARE_LOCATION_FIELD(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonAggConstructor(const JsonAggConstructor *a,
|
||||
const JsonAggConstructor *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(output);
|
||||
COMPARE_NODE_FIELD(agg_filter);
|
||||
COMPARE_NODE_FIELD(agg_order);
|
||||
COMPARE_NODE_FIELD(over);
|
||||
COMPARE_LOCATION_FIELD(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonObjectAgg(const JsonObjectAgg *a, const JsonObjectAgg *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(constructor);
|
||||
COMPARE_NODE_FIELD(arg);
|
||||
COMPARE_SCALAR_FIELD(absent_on_null);
|
||||
COMPARE_SCALAR_FIELD(unique);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonOutput(const JsonOutput *a, const JsonOutput *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(typeName);
|
||||
COMPARE_NODE_FIELD(returning);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonArrayConstructor(const JsonArrayConstructor *a,
|
||||
const JsonArrayConstructor *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(exprs);
|
||||
COMPARE_NODE_FIELD(output);
|
||||
COMPARE_SCALAR_FIELD(absent_on_null);
|
||||
COMPARE_LOCATION_FIELD(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonArrayAgg(const JsonArrayAgg *a, const JsonArrayAgg *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(constructor);
|
||||
COMPARE_NODE_FIELD(arg);
|
||||
COMPARE_SCALAR_FIELD(absent_on_null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJsonArrayQueryConstructor(const JsonArrayQueryConstructor *a,
|
||||
const JsonArrayQueryConstructor *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(query);
|
||||
COMPARE_NODE_FIELD(output);
|
||||
COMPARE_NODE_FIELD(format);
|
||||
COMPARE_SCALAR_FIELD(absent_on_null);
|
||||
COMPARE_LOCATION_FIELD(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff from pathnodes.h
|
||||
*/
|
||||
@@ -3398,6 +3503,9 @@ equal(const void *a, const void *b)
|
||||
case T_JsonValueExpr:
|
||||
retval = _equalJsonValueExpr(a, b);
|
||||
break;
|
||||
case T_JsonConstructorExpr:
|
||||
retval = _equalJsonConstructorExpr(a, b);
|
||||
break;
|
||||
|
||||
/*
|
||||
* RELATION NODES
|
||||
@@ -3978,6 +4086,30 @@ equal(const void *a, const void *b)
|
||||
case T_PublicationTable:
|
||||
retval = _equalPublicationTable(a, b);
|
||||
break;
|
||||
case T_JsonKeyValue:
|
||||
retval = _equalJsonKeyValue(a, b);
|
||||
break;
|
||||
case T_JsonObjectConstructor:
|
||||
retval = _equalJsonObjectConstructor(a, b);
|
||||
break;
|
||||
case T_JsonAggConstructor:
|
||||
retval = _equalJsonAggConstructor(a, b);
|
||||
break;
|
||||
case T_JsonObjectAgg:
|
||||
retval = _equalJsonObjectAgg(a, b);
|
||||
break;
|
||||
case T_JsonOutput:
|
||||
retval = _equalJsonOutput(a, b);
|
||||
break;
|
||||
case T_JsonArrayConstructor:
|
||||
retval = _equalJsonArrayConstructor(a, b);
|
||||
break;
|
||||
case T_JsonArrayQueryConstructor:
|
||||
retval = _equalJsonArrayQueryConstructor(a, b);
|
||||
break;
|
||||
case T_JsonArrayAgg:
|
||||
retval = _equalJsonArrayAgg(a, b);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
|
||||
@@ -872,3 +872,18 @@ makeJsonEncoding(char *name)
|
||||
|
||||
return JS_ENC_DEFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* makeJsonKeyValue -
|
||||
* creates a JsonKeyValue node
|
||||
*/
|
||||
Node *
|
||||
makeJsonKeyValue(Node *key, Node *value)
|
||||
{
|
||||
JsonKeyValue *n = makeNode(JsonKeyValue);
|
||||
|
||||
n->key = (Expr *) key;
|
||||
n->value = castNode(JsonValueExpr, value);
|
||||
|
||||
return (Node *) n;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
@@ -3361,6 +3401,19 @@ expression_tree_mutator(Node *node,
|
||||
MUTATE(newnode->formatted_expr, jve->formatted_expr, Expr *);
|
||||
MUTATE(newnode->format, jve->format, JsonFormat *);
|
||||
|
||||
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:
|
||||
@@ -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));
|
||||
|
||||
@@ -1781,6 +1781,21 @@ _outJsonValueExpr(StringInfo str, const JsonValueExpr *node)
|
||||
WRITE_NODE_FIELD(format);
|
||||
}
|
||||
|
||||
static void
|
||||
_outJsonConstructorExpr(StringInfo str, const JsonConstructorExpr *node)
|
||||
{
|
||||
WRITE_NODE_TYPE("JSONCTOREXPR");
|
||||
|
||||
WRITE_NODE_FIELD(args);
|
||||
WRITE_NODE_FIELD(func);
|
||||
WRITE_NODE_FIELD(coercion);
|
||||
WRITE_INT_FIELD(type);
|
||||
WRITE_NODE_FIELD(returning);
|
||||
WRITE_BOOL_FIELD(unique);
|
||||
WRITE_BOOL_FIELD(absent_on_null);
|
||||
WRITE_LOCATION_FIELD(location);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Stuff from pathnodes.h.
|
||||
@@ -4576,6 +4591,9 @@ outNode(StringInfo str, const void *obj)
|
||||
case T_JsonValueExpr:
|
||||
_outJsonValueExpr(str, obj);
|
||||
break;
|
||||
case T_JsonConstructorExpr:
|
||||
_outJsonConstructorExpr(str, obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
|
||||
@@ -1434,6 +1434,26 @@ _readJsonValueExpr(void)
|
||||
READ_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* _readJsonConstructorExpr
|
||||
*/
|
||||
static JsonConstructorExpr *
|
||||
_readJsonConstructorExpr(void)
|
||||
{
|
||||
READ_LOCALS(JsonConstructorExpr);
|
||||
|
||||
READ_NODE_FIELD(args);
|
||||
READ_NODE_FIELD(func);
|
||||
READ_NODE_FIELD(coercion);
|
||||
READ_INT_FIELD(type);
|
||||
READ_NODE_FIELD(returning);
|
||||
READ_BOOL_FIELD(unique);
|
||||
READ_BOOL_FIELD(absent_on_null);
|
||||
READ_LOCATION_FIELD(location);
|
||||
|
||||
READ_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff from pathnodes.h.
|
||||
*
|
||||
@@ -3025,6 +3045,8 @@ parseNodeString(void)
|
||||
return_value = _readJsonReturning();
|
||||
else if (MATCH("JSONVALUEEXPR", 13))
|
||||
return_value = _readJsonValueExpr();
|
||||
else if (MATCH("JSONCTOREXPR", 12))
|
||||
return_value = _readJsonConstructorExpr();
|
||||
else
|
||||
{
|
||||
elog(ERROR, "badly formatted node string \"%.32s\"...", token);
|
||||
|
||||
Reference in New Issue
Block a user