Skip to content

Commit a9185e5

Browse files
author
Nikita Glukhov
committed
Add JsonValueCopy(), JsonCopy()
1 parent eff4c3a commit a9185e5

File tree

4 files changed

+113
-7
lines changed

4 files changed

+113
-7
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 105 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "postgres.h"
1212

13+
#include "miscadmin.h"
1314
#include "utils/builtins.h"
1415
#include "utils/json_generic.h"
1516
#include "utils/memutils.h"
@@ -20,15 +21,88 @@ JsonContainerOps jsonvContainerOps;
2021
static Json *JsonExpand(Json *tmp, Datum value, bool freeValue,
2122
JsonContainerOps *ops);
2223

23-
#if 0
24-
static JsonValue *
25-
JsonValueCopy(JsonValue *val)
24+
JsonValue *
25+
JsonValueCopy(JsonValue *res, const JsonValue *val)
2626
{
27-
JsonValue *copy = palloc(sizeof(JsonValue));
28-
memcpy(copy, val, sizeof(JsonValue));
29-
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;
30105
}
31-
#endif
32106

33107
static inline JsonValue *
34108
jsonFindKeyInObjectInternal(JsonContainer *obj, const char *key, int len,
@@ -560,6 +634,17 @@ jsonvGetArraySize(JsonContainer *arrc)
560634
}
561635
}
562636

637+
static JsonContainer *
638+
jsonvCopy(JsonContainer *jc)
639+
{
640+
JsonContainerData *res = JsonContainerAlloc();
641+
642+
*res = *jc;
643+
res->data = JsonValueCopy(NULL, (JsonValue *) jc->data);
644+
645+
return res;
646+
}
647+
563648
JsonContainerOps
564649
jsonvContainerOps =
565650
{
@@ -571,6 +656,7 @@ jsonvContainerOps =
571656
jsonvGetArrayElement,
572657
jsonvGetArraySize,
573658
JsonbToCStringRaw,
659+
jsonvCopy,
574660
};
575661

576662
JsonValue *
@@ -1011,6 +1097,18 @@ JsonValueToJson(JsonValue *val)
10111097
}
10121098
}
10131099

1100+
JsonContainer *
1101+
JsonCopyFlat(JsonContainer *jc)
1102+
{
1103+
JsonContainerData *res = JsonContainerAlloc();
1104+
1105+
*res = *jc;
1106+
res->data = palloc(jc->len);
1107+
memcpy(res->data, jc->data, jc->len);
1108+
1109+
return res;
1110+
}
1111+
10141112
JsonValue *
10151113
JsonContainerExtractKeys(JsonContainer *jsc)
10161114
{

src/backend/utils/adt/jsonb_util.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,4 +2202,5 @@ jsonbContainerOps =
22022202
jsonbGetArrayElement,
22032203
NULL,
22042204
JsonbToCStringRaw,
2205+
JsonCopyFlat,
22052206
};

src/common/jsonapi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,7 @@ jsontContainerOps =
16081608
jsonGetArrayElement,
16091609
jsontGetArraySize,
16101610
jsontToString,
1611+
JsonCopyFlat,
16111612
};
16121613

16131614
#endif

src/include/utils/json_generic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct JsonContainerOps
7474
uint32 (*getArraySize)(JsonContainer *array);
7575
char *(*toString)(StringInfo out, JsonContainer *jc,
7676
int estimated_len);
77+
JsonContainer *(*copy)(JsonContainer *jc);
7778
};
7879

7980
typedef struct CompressedObject
@@ -245,6 +246,9 @@ JsontPGetDatum(Json *json)
245246
#define JsonGetArraySize(json) \
246247
JsonOp0(getArraySize, json)
247248

249+
#define JsonCopy(jscontainer) \
250+
JsonOp0(copy, jscontainer)
251+
248252
static inline JsonIteratorToken
249253
JsonIteratorNext(JsonIterator **it, JsonValue *val, bool skipNested)
250254
{
@@ -355,6 +359,8 @@ extern Json *JsonValueToJson(JsonValue *val);
355359
extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
356360
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
357361
extern JsonContainer *JsonValueToContainer(const JsonValue *val);
362+
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
363+
extern JsonContainer *JsonCopyFlat(JsonContainer *flatContainer);
358364

359365
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
360366
extern const char *JsonbTypeName(JsonbValue *jb);

0 commit comments

Comments
 (0)