Skip to content

Commit f168b8b

Browse files
author
Nikita Glukhov
committed
Add JsonValueUnwrap(), JsonExtractScalar()
1 parent 611cdfe commit f168b8b

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

src/backend/utils/adt/json_generic.c

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

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

src/backend/utils/adt/jsonb.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -846,15 +846,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
846846
case JSONBTYPE_JSONB:
847847
{
848848
Jsonb *jsonb = DatumGetJsonbP(val);
849-
JsonbIterator *it;
850-
851-
it = JsonbIteratorInit(&jsonb->root);
852849

853850
if (JB_ROOT_IS_SCALAR(jsonb))
854851
{
855-
(void) JsonbIteratorNext(&it, &jb, true);
856-
Assert(jb.type == jbvArray);
857-
(void) JsonbIteratorNext(&it, &jb, true);
852+
JsonExtractScalar(&jsonb->root, &jb);
858853
break;
859854
}
860855

@@ -866,6 +861,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
866861
else
867862
{
868863
JsonbIteratorToken type;
864+
JsonbIterator *it = JsonbIteratorInit(&jsonb->root);
869865

870866
while ((type = JsonbIteratorNext(&it, &jb, false))
871867
!= WJB_DONE)

src/backend/utils/adt/jsonb_util.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,16 @@ pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
747747
jbval->type != jbvBinary || !unpackBinary)
748748
{
749749
/* drop through */
750+
if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE))
751+
jbval = JsonValueUnwrap(jbval, &v);
752+
753+
return pushJsonbValueScalar(pstate, seq, jbval);
754+
}
755+
756+
if (*pstate && JsonContainerIsScalar(jbval->val.binary.data))
757+
{
758+
jbval = JsonExtractScalar(jbval->val.binary.data, &v);
759+
Assert(IsAJsonbScalar(jbval));
750760
return pushJsonbValueScalar(pstate, seq, jbval);
751761
}
752762

src/include/utils/json_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@ extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
271271
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
272272
extern JsonContainer *JsonValueToContainer(const JsonValue *val);
273273
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
274+
extern const JsonValue *JsonValueUnwrap(const JsonValue *val, JsonValue *buf);
274275
extern JsonContainer *JsonCopyFlat(JsonContainer *flatContainer);
276+
extern JsonValue *JsonExtractScalar(JsonContainer *jc, JsonValue *scalar);
275277

276278
extern Jsonb *JsonbMakeEmptyArray(void);
277279
extern Jsonb *JsonbMakeEmptyObject(void);

0 commit comments

Comments
 (0)