Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+105-8
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

+1
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

+6
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)