Skip to content

Commit cc253f9

Browse files
author
Nikita Glukhov
committed
Add JsonValueUnwrap(), JsonExtractScalar()
1 parent ca218ec commit cc253f9

File tree

4 files changed

+60
-7
lines changed

4 files changed

+60
-7
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,52 @@ JsonValueCopy(JsonValue *res, const JsonValue *val)
104104
return res;
105105
}
106106

107+
JsonValue *
108+
JsonExtractScalar(JsonContainer *jc, JsonValue *scalar)
109+
{
110+
JsonIterator *it;
111+
JsonValue val;
112+
113+
Assert(JsonContainerIsScalar(jc));
114+
115+
it = JsonIteratorInit(jc);
116+
117+
if (JsonIteratorNext(&it, &val, false) != WJB_BEGIN_ARRAY ||
118+
JsonIteratorNext(&it, scalar, false) != WJB_ELEM ||
119+
JsonIteratorNext(&it, &val, false) != WJB_END_ARRAY)
120+
elog(ERROR, "unexpected structure of scalar json container");
121+
122+
return scalar;
123+
}
124+
125+
const JsonValue *
126+
JsonValueUnwrap(const JsonValue *val, JsonValue *valbuf)
127+
{
128+
if (val->type == jbvBinary)
129+
{
130+
JsonContainer *jc = val->val.binary.data;
131+
132+
if (jc->ops == &jsonvContainerOps)
133+
{
134+
val = (JsonbValue *) jc->data;
135+
Assert(val->type != jbvBinary);
136+
}
137+
else if (JsonContainerIsScalar(jc))
138+
{
139+
val = JsonExtractScalar(jc, valbuf);
140+
Assert(IsAJsonbScalar(val));
141+
}
142+
}
143+
144+
if (val->type == jbvArray && val->val.array.rawScalar)
145+
{
146+
val = &val->val.array.elems[0];
147+
Assert(IsAJsonbScalar(val));
148+
}
149+
150+
return val;
151+
}
152+
107153
static inline JsonValue *
108154
jsonFindKeyInObjectInternal(JsonContainer *obj, const char *key, int len,
109155
bool last)

src/backend/utils/adt/jsonb.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -943,15 +943,9 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
943943
? DatumGetJsontP(val)
944944
: DatumGetJsonbP(val);
945945
#endif
946-
JsonbIterator *it;
947-
948-
it = JsonbIteratorInit(&jsonb->root);
949-
950946
if (JB_ROOT_IS_SCALAR(jsonb))
951947
{
952-
(void) JsonbIteratorNext(&it, &jb, true);
953-
Assert(jb.type == jbvArray);
954-
(void) JsonbIteratorNext(&it, &jb, true);
948+
JsonExtractScalar(&jsonb->root, &jb);
955949
break;
956950
}
957951

@@ -963,6 +957,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
963957
else
964958
{
965959
JsonbIteratorToken type;
960+
JsonbIterator *it = JsonbIteratorInit(&jsonb->root);
966961

967962
while ((type = JsonbIteratorNext(&it, &jb, false))
968963
!= WJB_DONE)

src/backend/utils/adt/jsonb_util.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,16 @@ pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
724724
jbval->type != jbvBinary || !unpackBinary)
725725
{
726726
/* drop through */
727+
if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE))
728+
jbval = JsonValueUnwrap(jbval, &v);
729+
730+
return pushJsonbValueScalar(pstate, seq, jbval);
731+
}
732+
733+
if (*pstate && JsonContainerIsScalar(jbval->val.binary.data))
734+
{
735+
jbval = JsonExtractScalar(jbval->val.binary.data, &v);
736+
Assert(IsAJsonbScalar(jbval));
727737
return pushJsonbValueScalar(pstate, seq, jbval);
728738
}
729739

src/include/utils/json_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,9 @@ extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
360360
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
361361
extern JsonContainer *JsonValueToContainer(const JsonValue *val);
362362
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
363+
extern const JsonValue *JsonValueUnwrap(const JsonValue *val, JsonValue *buf);
363364
extern JsonContainer *JsonCopyFlat(JsonContainer *flatContainer);
365+
extern JsonValue *JsonExtractScalar(JsonContainer *jc, JsonValue *scalar);
364366

365367
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
366368
extern const char *JsonbTypeName(JsonbValue *jb);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy