Skip to content

Commit ca218ec

Browse files
author
Nikita Glukhov
committed
Add JsonValueCopy(), JsonCopy()
1 parent 28bedd9 commit ca218ec

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy