Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9951a7b

Browse files
author
Nikita Glukhov
committed
Try to preserve formatting for text jsons
1 parent 4f5929c commit 9951a7b

File tree

6 files changed

+85
-54
lines changed

6 files changed

+85
-54
lines changed

src/backend/utils/adt/json_generic.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ jsonvContainerOps =
556556
jsonvFindValueInArray,
557557
jsonvGetArrayElement,
558558
jsonvGetArraySize,
559-
JsonbToCString,
559+
JsonbToCStringRaw,
560560
};
561561

562562
JsonValue *

src/backend/utils/adt/jsonb.c

+26-8
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,11 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
415415
break;
416416
}
417417

418-
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false);
418+
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false, true);
419419
}
420420

421421
/*
422-
* JsonbToCString
422+
* JsonbToCStringRaw
423423
* Converts jsonb value to a C-string.
424424
*
425425
* If 'out' argument is non-null, the resulting C-string is stored inside the
@@ -430,7 +430,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
430430
* if they are converting it to a text* object.
431431
*/
432432
char *
433-
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
433+
JsonbToCStringRaw(StringInfo out, JsonbContainer *in, int estimated_len)
434434
{
435435
return JsonbToCStringWorker(out, in, estimated_len, false);
436436
}
@@ -459,6 +459,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
459459

460460
/* If we are indenting, don't add a space after a comma */
461461
int ispaces = indent ? 1 : 2;
462+
bool skipNested = !indent;
462463

463464
/*
464465
* Don't indent the very first item. This gets set to the indent flag at
@@ -476,7 +477,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
476477
it = JsonbIteratorInit(in);
477478

478479
while (redo_switch ||
479-
((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
480+
((type = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE))
480481
{
481482
redo_switch = false;
482483
switch (type)
@@ -517,11 +518,14 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
517518
jsonb_put_escaped_value(out, &v);
518519
appendBinaryStringInfo(out, ": ", 2);
519520

520-
type = JsonbIteratorNext(&it, &v, false);
521+
type = JsonbIteratorNext(&it, &v, skipNested);
521522
if (type == WJB_VALUE)
522523
{
523524
first = false;
524-
jsonb_put_escaped_value(out, &v);
525+
if (v.type == jbvBinary)
526+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
527+
else
528+
jsonb_put_escaped_value(out, &v);
525529
}
526530
else
527531
{
@@ -542,7 +546,11 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
542546

543547
if (!raw_scalar)
544548
add_indent(out, use_indent, level);
545-
jsonb_put_escaped_value(out, &v);
549+
550+
if (v.type == jbvBinary)
551+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
552+
else
553+
jsonb_put_escaped_value(out, &v);
546554
break;
547555
case WJB_END_ARRAY:
548556
level--;
@@ -854,6 +862,15 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
854862
{
855863
JsonbIteratorToken type;
856864

865+
JsonToJsonValue(jsonb, &jb);
866+
867+
if (result->parseState)
868+
{
869+
pushScalarJsonbValue(&result->parseState, &jb,
870+
false, false);
871+
return;
872+
}
873+
857874
while ((type = JsonbIteratorNext(&it, &jb, false))
858875
!= WJB_DONE)
859876
{
@@ -885,7 +902,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
885902
return;
886903
}
887904

888-
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar);
905+
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar,
906+
true);
889907
}
890908

891909
/*

src/backend/utils/adt/jsonb_util.c

+24-17
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
105105
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys,
106106
bool skip_nulls);
107107
static JsonbValue *pushSingleScalarJsonbValue(JsonbParseState **pstate,
108-
const JsonbValue *jbval);
108+
const JsonbValue *jbval,
109+
bool unpackBinary);
109110
static void jsonbInitContainer(JsonContainerData *jc, JsonbContainer *jbc, int len);
110111

111112
JsonValue *
@@ -166,7 +167,7 @@ JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
166167
if (IsAJsonbScalar(val))
167168
{
168169
JsonbParseState *pstate = NULL;
169-
val = pushSingleScalarJsonbValue(&pstate, val);
170+
val = pushSingleScalarJsonbValue(&pstate, val, true);
170171
}
171172
else
172173
{
@@ -706,8 +707,8 @@ JsonbParseStateSetSkipNulls(JsonbParseState *state, bool skip_nulls)
706707
* are unpacked before being added to the result.
707708
*/
708709
JsonbValue *
709-
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
710-
const JsonbValue *jbval)
710+
pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
711+
const JsonbValue *jbval, bool unpackBinary)
711712
{
712713
JsonIterator *it;
713714
JsonbValue *res = NULL;
@@ -721,25 +722,29 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
721722
for (i = 0; i < jbval->val.object.nPairs; i++)
722723
{
723724
pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
724-
pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
725+
pushJsonbValueExt(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value, unpackBinary);
725726
}
726727

727728
return pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
728729
}
729730

730731
if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvArray)
731732
{
733+
if (jbval->val.array.rawScalar)
734+
return pushJsonbValue(pstate, seq, &jbval->val.array.elems[0]);
735+
732736
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
737+
733738
for (i = 0; i < jbval->val.array.nElems; i++)
734739
{
735-
pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
740+
pushJsonbValueExt(pstate, WJB_ELEM, &jbval->val.array.elems[i], unpackBinary);
736741
}
737742

738743
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
739744
}
740745

741746
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
742-
jbval->type != jbvBinary)
747+
jbval->type != jbvBinary || !unpackBinary)
743748
{
744749
/* drop through */
745750
return pushJsonbValueScalar(pstate, seq, jbval);
@@ -827,7 +832,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
827832
appendValue(*pstate, scalarVal);
828833
break;
829834
case WJB_ELEM:
830-
Assert(IsAJsonbScalar(scalarVal));
835+
/* Assert(IsAJsonbScalar(scalarVal)); */
831836
appendElement(*pstate, scalarVal);
832837
break;
833838
case WJB_END_OBJECT:
@@ -868,7 +873,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
868873
}
869874

870875
static JsonbValue *
871-
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
876+
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
877+
bool unpackBinary)
872878
{
873879
/* single root scalar */
874880
JsonbValue va;
@@ -878,20 +884,21 @@ pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
878884
va.val.array.nElems = 1;
879885

880886
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, &va);
881-
pushJsonbValue(pstate, WJB_ELEM, jbval);
887+
pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
882888
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
883889
}
884890

885891
static JsonbValue *
886892
pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
887-
bool isKey)
893+
bool isKey, bool unpackBinary)
888894
{
889895
switch ((*pstate)->contVal.type)
890896
{
891897
case jbvArray:
892-
return pushJsonbValue(pstate, WJB_ELEM, jbval);
898+
return pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
893899
case jbvObject:
894-
return pushJsonbValue(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval);
900+
return pushJsonbValueExt(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval,
901+
unpackBinary);
895902
default:
896903
elog(ERROR, "unexpected parent of nested structure");
897904
return NULL;
@@ -900,11 +907,11 @@ pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
900907

901908
JsonbValue *
902909
pushScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
903-
bool isKey)
910+
bool isKey, bool unpackBinary)
904911
{
905912
return *pstate == NULL
906-
? pushSingleScalarJsonbValue(pstate, jbval)
907-
: pushNestedScalarJsonbValue(pstate, jbval, isKey);
913+
? pushSingleScalarJsonbValue(pstate, jbval, unpackBinary)
914+
: pushNestedScalarJsonbValue(pstate, jbval, isKey, unpackBinary);
908915

909916
}
910917

@@ -2232,5 +2239,5 @@ jsonbContainerOps =
22322239
jsonbFindValueInArray,
22332240
jsonbGetArrayElement,
22342241
NULL,
2235-
JsonbToCString,
2242+
JsonbToCStringRaw,
22362243
};

0 commit comments

Comments
 (0)