Skip to content

Commit 9f166b6

Browse files
author
Nikita Glukhov
committed
Add JsonValueUnwrap(), JsonExtractScalar()
1 parent a9185e5 commit 9f166b6

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)