Skip to content

Commit c30f001

Browse files
author
Nikita Glukhov
committed
Add variable-length JsonContainer data
1 parent 3874abf commit c30f001

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ JsonInit(Json *json)
7777
const void *data = DatumGetPointer(json->obj.value);
7878
struct varlena *detoasted_data;
7979

80-
Assert(json->root.data || data);
80+
Assert(JsonContainerDataPtr(&json->root) || data);
8181

82-
if (json->root.data || !data)
82+
if (JsonContainerDataPtr(&json->root) || !data) /* FIXME */
8383
return;
8484

8585
detoasted_data = PG_DETOAST_DATUM(json->obj.value);
@@ -92,18 +92,19 @@ JsonInit(Json *json)
9292
static Json *
9393
JsonExpand(Json *tmp, Datum value, bool freeValue, JsonContainerOps *ops)
9494
{
95-
Json *json = tmp ? tmp : (Json *) palloc(sizeof(Json));
95+
Json *json = tmp ? tmp : (Json *) palloc(JsonAllocSize(ops->data_size));
9696

9797
json->obj.value = value;
9898
json->obj.freeValue = freeValue;
9999
json->obj.isTemporary = tmp != NULL;
100-
json->root.data = NULL;
101100
json->root.len = 0;
102101
json->root.ops = ops;
103102
json->root.size = -1;
104103
json->root.type = jbvBinary;
105104
json->is_json = false;
106105

106+
memset(json->root._data, 0, ops->data_size);
107+
107108
return json;
108109
}
109110

@@ -148,6 +149,8 @@ JsonValueToJson(JsonValue *val)
148149
jc->ops);
149150

150151
json->root = *jc;
152+
memcpy(json->root._data, jc->_data, jc->ops->data_size);
153+
151154
return json;
152155
}
153156
else
@@ -161,11 +164,11 @@ JsonValueToJson(JsonValue *val)
161164
JsonContainer *
162165
JsonCopyFlat(JsonContainer *jc)
163166
{
164-
JsonContainerData *res = JsonContainerAlloc();
167+
JsonContainerData *res = JsonContainerAlloc(jc->ops);
165168

166169
*res = *jc;
167-
res->data = palloc(jc->len);
168-
memcpy(res->data, jc->data, jc->len);
170+
JsonContainerDataPtr(res) = palloc(jc->len);
171+
memcpy(JsonContainerDataPtr(res), JsonContainerDataPtr(jc), jc->len);
169172

170173
return res;
171174
}

src/backend/utils/adt/jsonb_util.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,12 @@ JsonContainerFlatten(JsonContainer *jc, JsonValueEncoder encoder,
123123

124124
if (jc->ops == ops)
125125
{
126-
int size = jc->len;
127-
void *out = palloc(VARHDRSZ + size);
126+
int size = jc->len;
127+
void *out = palloc(VARHDRSZ + size);
128+
128129
SET_VARSIZE(out, VARHDRSZ + size);
129-
memcpy(VARDATA(out), jc->data, size);
130+
memcpy(VARDATA(out), JsonContainerDataPtr(jc), size);
131+
130132
return out;
131133
}
132134

@@ -429,7 +431,7 @@ JsonbArrayIteratorGetIth(JsonbArrayIterator *it, uint32 i)
429431
static JsonbValue *
430432
jsonbFindValueInArray(JsonContainer *jsc, const JsonbValue *key)
431433
{
432-
const JsonbContainerHeader *container = jsc->data;
434+
const JsonbContainerHeader *container = JsonContainerDataPtr(jsc);
433435
JsonbArrayIterator it;
434436
JsonbValue *result = palloc(sizeof(JsonbValue));
435437

@@ -508,7 +510,7 @@ static JsonbValue *
508510
jsonbFindKeyInObject(JsonContainer *jsc, const char *keyVal, int keyLen,
509511
JsonValue *res)
510512
{
511-
const JsonbContainerHeader *container = jsc->data;
513+
const JsonbContainerHeader *container = JsonContainerDataPtr(jsc);
512514
const JEntry *children = container->children;
513515
int count = JsonContainerSize(jsc);
514516
char *baseAddr;
@@ -583,7 +585,7 @@ jsonbGetArrayElement(JsonContainer *jsc, uint32 i)
583585
if (!JsonContainerIsArray(jsc))
584586
elog(ERROR, "not a jsonb array");
585587

586-
JsonbArrayIteratorInit(&it, jsc->data);
588+
JsonbArrayIteratorInit(&it, JsonContainerDataPtr(jsc));
587589

588590
return JsonbArrayIteratorGetIth(&it, i);
589591
}
@@ -637,7 +639,7 @@ fillJsonbValue(const JsonbContainerHeader *container, int index,
637639
{
638640
Assert(JBE_ISCONTAINER(entry));
639641
result->type = jbvBinary;
640-
result->val.binary.data = JsonContainerAlloc();
642+
result->val.binary.data = JsonContainerAlloc(&jsonbContainerOps);
641643
jsonbInitContainer((JsonContainerData *) result->val.binary.data,
642644
/* Remove alignment padding from data pointer and length */
643645
(JsonbContainerHeader *)(base_addr + INTALIGN(offset)),
@@ -1199,7 +1201,7 @@ iteratorFromContainer(JsonContainer *container, jsonbIterator *parent)
11991201
static JsonIterator *
12001202
jsonbIteratorInit(JsonContainer *cont)
12011203
{
1202-
const JsonbContainerHeader *container = cont->data;
1204+
const JsonbContainerHeader *container = JsonContainerDataPtr(cont);
12031205
jsonbIterator *it;
12041206

12051207
it = palloc0(sizeof(jsonbIterator));
@@ -2069,7 +2071,7 @@ convertJsonbBinary(StringInfo buffer, JEntry *pheader, const JsonbValue *val,
20692071
{
20702072
int base_offset = buffer->len;
20712073
padBufferToInt(buffer);
2072-
appendToBuffer(buffer, jc->data, jc->len);
2074+
appendToBuffer(buffer, JsonContainerDataPtr(jc), jc->len);
20732075
*pheader = JENTRY_ISCONTAINER | (buffer->len - base_offset);
20742076
}
20752077
else
@@ -2201,12 +2203,11 @@ uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
22012203
}
22022204
}
22032205

2204-
22052206
static void
22062207
jsonbInitContainer(JsonContainerData *jc, JsonbContainerHeader *jbc, int len)
22072208
{
22082209
jc->ops = &jsonbContainerOps;
2209-
jc->data = jbc;
2210+
JsonContainerDataPtr(jc) = jbc;
22102211
jc->len = len;
22112212
jc->size = jbc->header & JBC_CMASK;
22122213
jc->type = jbc->header & JBC_FOBJECT ? jbvObject :
@@ -2224,6 +2225,7 @@ jsonbInit(JsonContainerData *jc, Datum value)
22242225
JsonContainerOps
22252226
jsonbContainerOps =
22262227
{
2228+
sizeof(JsonbContainerHeader *),
22272229
jsonbInit,
22282230
jsonbIteratorInit,
22292231
jsonbFindKeyInObject,

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2049,7 +2049,8 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
20492049

20502050
/* construct object id from its base object and offset inside that */
20512051
id = jb->type != jbvBinary ? 0 :
2052-
(int64) ((char *) jbc->data - (char *) cxt->baseObject.jbc->data); /* FIXME */
2052+
(int64) ((char *) JsonContainerDataPtr(jbc) -
2053+
(char *) JsonContainerDataPtr(cxt->baseObject.jbc)); /* FIXME */
20532054
id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
20542055

20552056
idval.type = jbvNumeric;

src/include/utils/json_generic.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ typedef struct JsonContainerOps JsonContainerOps;
2626
typedef struct JsonContainerData
2727
{
2828
JsonContainerOps *ops;
29-
void *data;
3029
int len;
3130
int size;
3231
JsonbValueType type;
32+
void *_data[FLEXIBLE_ARRAY_MEMBER];
3333
} JsonContainerData;
3434

3535
typedef const JsonContainerData JsonContainer;
@@ -49,6 +49,7 @@ struct JsonIteratorData
4949

5050
struct JsonContainerOps
5151
{
52+
int data_size;
5253
void (*init)(JsonContainerData *jc, Datum value);
5354
JsonIterator *(*iteratorInit)(JsonContainer *jc);
5455
JsonValue *(*findKeyInObject)(JsonContainer *object,
@@ -73,13 +74,14 @@ typedef struct CompressedObject
7374
typedef struct Json
7475
{
7576
CompressedObject obj;
76-
JsonContainerData root;
7777
bool is_json; /* json or jsonb */
78+
JsonContainerData root;
7879
} Json;
7980

8081
typedef Json Jsonb;
8182
typedef JsonContainer JsonbContainer;
8283

84+
#define JsonContainerDataPtr(jc) ((jc)->_data[0])
8385

8486
#define JsonIsTemporary(json) ((json)->obj.isTemporary)
8587

@@ -189,8 +191,14 @@ extern Json *DatumGetJson(Datum val, JsonContainerOps *ops, Json *tmp);
189191
extern void JsonFree(Json *json);
190192
extern Json *JsonCopyTemporary(Json *tmp);
191193

192-
#define JsonContainerAlloc() \
193-
((JsonContainerData *) palloc(sizeof(JsonContainerData)))
194+
#define JsonAllocSize(data_size) \
195+
(offsetof(Json, root._data) + (data_size))
196+
197+
#define JsonContainerAllocSize(data_size) \
198+
(offsetof(JsonContainerData, _data) + (data_size))
199+
200+
#define JsonContainerAlloc(ops) \
201+
((JsonContainerData *) palloc(JsonContainerAllocSize((ops)->data_size)))
194202

195203
extern JsonValue *JsonFindValueInContainer(JsonContainer *json, uint32 flags,
196204
JsonValue *key);

0 commit comments

Comments
 (0)