Skip to content

Commit e7877e0

Browse files
author
Nikita Glukhov
committed
Add JsonValueUnwrap(), JsonExtractScalar()
1 parent 63ba0ba commit e7877e0

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 JsonValue *key, bool last)
109155
{

src/backend/utils/adt/jsonb.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -934,15 +934,9 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
934934
? DatumGetJsont(val)
935935
: DatumGetJsonb(val);
936936
#endif
937-
JsonbIterator *it;
938-
939-
it = JsonbIteratorInit(&jsonb->root);
940-
941937
if (JB_ROOT_IS_SCALAR(jsonb))
942938
{
943-
(void) JsonbIteratorNext(&it, &jb, true);
944-
Assert(jb.type == jbvArray);
945-
(void) JsonbIteratorNext(&it, &jb, true);
939+
JsonExtractScalar(&jsonb->root, &jb);
946940
break;
947941
}
948942

@@ -954,6 +948,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
954948
else
955949
{
956950
JsonbIteratorToken type;
951+
JsonbIterator *it = JsonbIteratorInit(&jsonb->root);
957952

958953
while ((type = JsonbIteratorNext(&it, &jb, false))
959954
!= WJB_DONE)

src/backend/utils/adt/jsonb_util.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,16 @@ pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
693693
jbval->type != jbvBinary || !unpackBinary)
694694
{
695695
/* drop through */
696+
if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE))
697+
jbval = JsonValueUnwrap(jbval, &v);
698+
699+
return pushJsonbValueScalar(pstate, seq, jbval);
700+
}
701+
702+
if (*pstate && JsonContainerIsScalar(jbval->val.binary.data))
703+
{
704+
jbval = JsonExtractScalar(jbval->val.binary.data, &v);
705+
Assert(IsAJsonbScalar(jbval));
696706
return pushJsonbValueScalar(pstate, seq, jbval);
697707
}
698708

src/include/utils/json_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
346346
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
347347
extern JsonContainer *JsonValueToContainer(const JsonValue *val);
348348
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
349+
extern const JsonValue *JsonValueUnwrap(const JsonValue *val, JsonValue *buf);
349350
extern JsonContainer *JsonCopyFlat(JsonContainer *flatContainer);
351+
extern JsonValue *JsonExtractScalar(JsonContainer *jc, JsonValue *scalar);
350352

351353
extern int JsonCompareContainers(JsonContainer *a, JsonContainer *b);
352354

0 commit comments

Comments
 (0)