Skip to content

Commit 63ba0ba

Browse files
author
Nikita Glukhov
committed
Add JsonValueCopy(), JsonCopy()
1 parent 0cdfaaf commit 63ba0ba

File tree

4 files changed

+118
-7
lines changed

4 files changed

+118
-7
lines changed

src/backend/utils/adt/json.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3033,4 +3033,5 @@ jsontContainerOps =
30333033
jsonGetArrayElement,
30343034
jsontGetArraySize,
30353035
jsontToString,
3036+
JsonCopyFlat,
30363037
};

src/backend/utils/adt/json_generic.c

Lines changed: 109 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
*
99
*/
1010

11+
#include "postgres.h"
12+
#include "miscadmin.h"
1113
#include "access/compression.h"
1214
#include "utils/builtins.h"
1315
#include "utils/json_generic.h"
@@ -19,15 +21,88 @@ static Json *JsonExpand(Json *tmp, Datum value, bool freeValue,
1921

2022
JsonContainerOps jsonvContainerOps;
2123

22-
#if 0
23-
static JsonValue *
24-
JsonValueCopy(JsonValue *val)
24+
JsonValue *
25+
JsonValueCopy(JsonValue *res, const JsonValue *val)
2526
{
26-
JsonValue *copy = palloc(sizeof(JsonValue));
27-
memcpy(copy, val, sizeof(JsonValue));
28-
return copy;
27+
check_stack_depth();
28+
29+
if (!res)
30+
res = (JsonValue *) palloc(sizeof(JsonValue));
31+
32+
res->type = val->type;
33+
34+
switch (val->type)
35+
{
36+
case jbvNull:
37+
break;
38+
39+
case jbvBool:
40+
res->val.boolean = val->val.boolean;
41+
break;
42+
43+
case jbvString:
44+
{ /* copy string values in the current context */
45+
char *buf = palloc(val->val.string.len + 1);
46+
memcpy(buf, val->val.string.val, val->val.string.len);
47+
buf[val->val.string.len] = 0;
48+
res->val.string.val = buf;
49+
res->val.string.len = val->val.string.len;
50+
break;
51+
}
52+
53+
case jbvNumeric:
54+
/* same for numeric */
55+
res->val.numeric =
56+
DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
57+
NumericGetDatum(val->val.numeric)));
58+
break;
59+
60+
case jbvArray:
61+
{
62+
int i;
63+
64+
res->val.array = val->val.array;
65+
res->val.array.elems = (JsonValue *)
66+
palloc(sizeof(JsonValue) * val->val.array.nElems);
67+
68+
for (i = 0; i < val->val.array.nElems; i++)
69+
JsonValueCopy(&res->val.array.elems[i],
70+
&val->val.array.elems[i]);
71+
72+
break;
73+
}
74+
75+
case jbvObject:
76+
{
77+
int i;
78+
79+
res->val.object = val->val.object;
80+
res->val.object.pairs = (JsonPair *)
81+
palloc(sizeof(JsonPair) * val->val.object.nPairs);
82+
83+
for (i = 0; i < val->val.object.nPairs; i++)
84+
{
85+
res->val.object.pairs[i].order = val->val.object.pairs[i].order;
86+
JsonValueCopy(&res->val.object.pairs[i].key,
87+
&val->val.object.pairs[i].key);
88+
JsonValueCopy(&res->val.object.pairs[i].value,
89+
&val->val.object.pairs[i].value);
90+
}
91+
92+
break;
93+
}
94+
95+
case jbvBinary:
96+
res->val.binary = val->val.binary;
97+
res->val.binary.data = JsonCopy(val->val.binary.data);
98+
break;
99+
100+
default:
101+
elog(ERROR, "unknown json value type %d", val->type);
102+
}
103+
104+
return res;
29105
}
30-
#endif
31106

32107
static inline JsonValue *
33108
jsonFindKeyInObjectInternal(JsonContainer *obj, const JsonValue *key, bool last)
@@ -550,6 +625,17 @@ jsonvGetArraySize(JsonContainer *arrc)
550625
}
551626
}
552627

628+
static JsonContainer *
629+
jsonvCopy(JsonContainer *jc)
630+
{
631+
JsonContainerData *res = JsonContainerAlloc();
632+
633+
*res = *jc;
634+
res->data = JsonValueCopy(NULL, (JsonValue *) jc->data);
635+
636+
return res;
637+
}
638+
553639
JsonContainerOps
554640
jsonvContainerOps =
555641
{
@@ -562,6 +648,7 @@ jsonvContainerOps =
562648
jsonvGetArrayElement,
563649
jsonvGetArraySize,
564650
JsonbToCStringRaw,
651+
jsonvCopy,
565652
};
566653

567654
JsonValue *
@@ -1031,6 +1118,21 @@ JsonValueToJson(JsonValue *val)
10311118
}
10321119
}
10331120

1121+
JsonContainer *
1122+
JsonCopyFlat(JsonContainer *jc)
1123+
{
1124+
JsonContainerData *res = JsonContainerAlloc();
1125+
1126+
*res = *jc;
1127+
res->data = palloc(jc->len);
1128+
memcpy(res->data, jc->data, jc->len);
1129+
1130+
if (jc->ops->compressionOps && jc->ops->compressionOps->copyOptions)
1131+
res->options = jc->ops->compressionOps->copyOptions(jc->options);
1132+
1133+
return res;
1134+
}
1135+
10341136
JsonValue *
10351137
JsonContainerExtractKeys(JsonContainer *jsc)
10361138
{

src/backend/utils/adt/jsonb_util.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,4 +2108,5 @@ jsonbContainerOps =
21082108
jsonbGetArrayElement,
21092109
NULL,
21102110
JsonbToCStringRaw,
2111+
JsonCopyFlat,
21112112
};

src/include/utils/json_generic.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ typedef struct JsonCompressionOptionsOps
5858
Size (*encodeOptions)(JsonContainer *, void *buf);
5959
Size (*decodeOptions)(const void *buf, CompressionOptions *);
6060
bool (*optionsAreEqual)(JsonContainer *, CompressionOptions);
61+
void *(*copyOptions)(void *options);
6162
} JsonCompressionOptionsOps;
6263

6364
typedef enum JsonContainerTypes
@@ -86,6 +87,7 @@ struct JsonContainerOps
8687
uint32 (*getArraySize)(JsonContainer *array);
8788
char *(*toString)(StringInfo out, JsonContainer *jc,
8889
int estimated_len);
90+
JsonContainer *(*copy)(JsonContainer *jc);
8991
};
9092

9193
typedef struct CompressedObject
@@ -230,6 +232,9 @@ typedef struct Json
230232
#define JsonGetArraySize(json) \
231233
JsonOp0(getArraySize, json)
232234

235+
#define JsonCopy(jscontainer) \
236+
JsonOp0(copy, jscontainer)
237+
233238
static inline JsonIteratorToken
234239
JsonIteratorNext(JsonIterator **it, JsonValue *val, bool skipNested)
235240
{
@@ -340,6 +345,8 @@ extern Json *JsonValueToJson(JsonValue *val);
340345
extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
341346
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
342347
extern JsonContainer *JsonValueToContainer(const JsonValue *val);
348+
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
349+
extern JsonContainer *JsonCopyFlat(JsonContainer *flatContainer);
343350

344351
extern int JsonCompareContainers(JsonContainer *a, JsonContainer *b);
345352

0 commit comments

Comments
 (0)