Skip to content

Commit f9bed84

Browse files
author
Nikita Glukhov
committed
Add JsonValueCopy(), JsonCopy()
1 parent d71f262 commit f9bed84

File tree

3 files changed

+112
-8
lines changed

3 files changed

+112
-8
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 105 additions & 8 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"
@@ -19,16 +20,88 @@ static JsonContainerOps jsonvContainerOps;
1920
static Json *JsonExpand(Json *tmp, Datum value, bool freeValue,
2021
JsonContainerOps *ops);
2122

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

33106
static inline JsonValue *
34107
jsonFindKeyInObjectInternal(JsonContainer *obj, const char *key, int len,
@@ -549,6 +622,17 @@ jsonvGetArraySize(JsonContainer *arrc)
549622
}
550623
}
551624

625+
static JsonContainer *
626+
jsonvCopy(JsonContainer *jc)
627+
{
628+
JsonContainerData *res = JsonContainerAlloc();
629+
630+
*res = *jc;
631+
res->data = JsonValueCopy(NULL, (JsonValue *) jc->data);
632+
633+
return res;
634+
}
635+
552636
static JsonContainerOps
553637
jsonvContainerOps =
554638
{
@@ -559,6 +643,7 @@ jsonvContainerOps =
559643
jsonvGetArrayElement,
560644
jsonvGetArraySize,
561645
JsonbToCStringRaw,
646+
jsonvCopy,
562647
};
563648

564649
JsonValue *
@@ -679,6 +764,18 @@ JsonValueToJson(JsonValue *val)
679764
}
680765
}
681766

767+
JsonContainer *
768+
JsonCopyFlat(JsonContainer *jc)
769+
{
770+
JsonContainerData *res = JsonContainerAlloc();
771+
772+
*res = *jc;
773+
res->data = palloc(jc->len);
774+
memcpy(res->data, jc->data, jc->len);
775+
776+
return res;
777+
}
778+
682779
JsonValue *
683780
JsonContainerExtractKeys(JsonContainer *jsc)
684781
{

src/backend/utils/adt/jsonb_util.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,4 +2240,5 @@ jsonbContainerOps =
22402240
jsonbGetArrayElement,
22412241
NULL,
22422242
JsonbToCStringRaw,
2243+
JsonCopyFlat,
22432244
};

src/include/utils/json_generic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct JsonContainerOps
6262
uint32 (*getArraySize)(JsonContainer *array);
6363
char *(*toString)(StringInfo out, JsonContainer *jc,
6464
int estimated_len);
65+
JsonContainer *(*copy)(JsonContainer *jc);
6566
};
6667

6768
typedef struct CompressedObject
@@ -195,6 +196,9 @@ typedef struct Json
195196
#define JsonGetArraySize(json) \
196197
JsonOp0(getArraySize, json)
197198

199+
#define JsonCopy(jscontainer) \
200+
JsonOp0(copy, jscontainer)
201+
198202
static inline JsonIteratorToken
199203
JsonIteratorNext(JsonIterator **it, JsonValue *val, bool skipNested)
200204
{
@@ -263,6 +267,8 @@ extern Json *JsonValueToJson(JsonValue *val);
263267
extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
264268
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
265269
extern JsonContainer *JsonValueToContainer(const JsonValue *val);
270+
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
271+
extern JsonContainer *JsonCopyFlat(JsonContainer *flatContainer);
266272

267273
extern Jsonb *JsonbMakeEmptyArray(void);
268274
extern Jsonb *JsonbMakeEmptyObject(void);

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