Skip to content

Commit 6f2db95

Browse files
author
Nikita Glukhov
committed
Add custom toaster encoders to jsonb
1 parent f649da1 commit 6f2db95

File tree

4 files changed

+64
-27
lines changed

4 files changed

+64
-27
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ JsonExpand(Json *tmp, Datum value, bool freeValue, JsonContainerOps *ops)
8181
json->root.ops = ops;
8282
json->root.size = -1;
8383
json->root.type = jbvBinary;
84+
json->root.toasterid = InvalidOid;
8485
json->is_json = false;
8586

8687
memset(json->root._data, 0, ops->data_size);
@@ -159,6 +160,21 @@ JsonValueToJson(JsonValue *val)
159160
}
160161
}
161162

163+
Datum
164+
JsonbValueToOrigJsonbDatum(JsonValue *val, Json *orig_json)
165+
{
166+
if (val->type != jbvBinary &&
167+
JsonRoot(orig_json)->ops->encode)
168+
{
169+
void *res = JsonRoot(orig_json)->ops->encode(val, &jsonbContainerOps);
170+
171+
if (res)
172+
return PointerGetDatum(res);
173+
}
174+
175+
return JsonValueToJsonbDatum(val);
176+
}
177+
162178
JsonContainer *
163179
JsonCopyFlat(JsonContainer *jc)
164180
{

src/backend/utils/adt/jsonb_util.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ static void fillJsonbValue(const JsonbContainerHeader *container, int index,
8484
char *base_addr, uint32 offset,
8585
JsonbValue *result);
8686
static int compareJsonbScalarValue(const JsonbValue *a, const JsonbValue *b);
87-
static void *convertToJsonb(const JsonbValue *val, JsonValueEncoder encoder);
8887
static void convertJsonbValue(StringInfo buffer, JEntry *header, const JsonbValue *val, int level);
8988
static void convertJsonbArray(StringInfo buffer, JEntry *header, const JsonbValue *val, int level);
9089
static void convertJsonbObject(StringInfo buffer, JEntry *header, const JsonbValue *val, int level);
@@ -121,6 +120,18 @@ JsonContainerFlatten(JsonContainer *jc, JsonValueEncoder encoder,
121120
{
122121
JsonbValue jbv;
123122

123+
if (jc->ops->encode)
124+
{
125+
JsonbValue bin;
126+
void *res;
127+
128+
JsonValueInitBinary(&bin, jc);
129+
res = jc->ops->encode(&bin, ops);
130+
131+
if (res)
132+
return res;
133+
}
134+
124135
if (jc->ops == ops)
125136
{
126137
int size = jc->len;
@@ -137,7 +148,7 @@ JsonContainerFlatten(JsonContainer *jc, JsonValueEncoder encoder,
137148
else
138149
binary = JsonValueInitBinary(&jbv, jc);
139150

140-
return convertToJsonb(binary, encoder);
151+
return JsonEncode(binary, encoder, NULL);
141152
}
142153

143154
/*
@@ -169,7 +180,7 @@ JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
169180
Assert(val->type == jbvObject || val->type == jbvArray);
170181
}
171182

172-
return convertToJsonb(val, encoder);
183+
return JsonEncode(val, encoder, NULL);
173184
}
174185

175186
/*
@@ -1714,41 +1725,36 @@ padBufferToInt(StringInfo buffer)
17141725
}
17151726

17161727
void
1717-
JsonbEncode(StringInfoData *buffer, const JsonbValue *val)
1728+
JsonbEncode(StringInfoData *buffer, const JsonbValue *val, void *cxt)
17181729
{
17191730
JEntry jentry;
17201731

1732+
/* Make room for the varlena header */
1733+
reserveFromBuffer(buffer, VARHDRSZ);
17211734
convertJsonbValue(buffer, &jentry, val, 0);
1735+
SET_VARSIZE(buffer->data, buffer->len);
17221736
}
17231737

17241738
/*
17251739
* Given a JsonbValue, convert to Jsonb. The result is palloc'd.
17261740
*/
1727-
static void *
1728-
convertToJsonb(const JsonbValue *val, JsonValueEncoder encoder)
1741+
void *
1742+
JsonEncode(const JsonbValue *val, JsonValueEncoder encoder, void *cxt)
17291743
{
17301744
StringInfoData buffer;
1731-
void *res;
17321745

17331746
/* Allocate an output buffer. It will be enlarged as needed */
17341747
initStringInfo(&buffer);
17351748

1736-
/* Make room for the varlena header */
1737-
reserveFromBuffer(&buffer, VARHDRSZ);
1738-
1739-
(*encoder)(&buffer, val);
1749+
(*encoder)(&buffer, val, cxt);
17401750

17411751
/*
17421752
* Note: the JEntry of the root is discarded. Therefore the root
17431753
* JsonbContainer struct must contain enough information to tell what kind
17441754
* of value it is.
17451755
*/
17461756

1747-
res = (void *) buffer.data;
1748-
1749-
SET_VARSIZE(res, buffer.len);
1750-
1751-
return res;
1757+
return buffer.data;
17521758
}
17531759

17541760
/*
@@ -2204,6 +2210,7 @@ jsonbInitContainer(JsonContainerData *jc, JsonbContainerHeader *jbc, int len)
22042210
jc->ops = &jsonbContainerOps;
22052211
JsonContainerDataPtr(jc) = jbc;
22062212
jc->len = len;
2213+
jc->toasterid = InvalidOid;
22072214
jc->size = jbc->header & JBC_CMASK;
22082215
jc->type = jbc->header & JBC_FOBJECT ? jbvObject :
22092216
jbc->header & JBC_FSCALAR ? jbvArray | jbvScalar :
@@ -2230,4 +2237,5 @@ jsonbContainerOps =
22302237
JsonbToCStringRaw,
22312238
JsonCopyFlat,
22322239
NULL,
2240+
NULL
22332241
};

src/backend/utils/adt/jsonfuncs.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,7 +1631,7 @@ jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
16311631

16321632
pfree(path_nulls);
16331633

1634-
PG_RETURN_JSONB_VALUE_P(res);
1634+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, jb));
16351635
}
16361636

16371637
static void
@@ -4209,7 +4209,7 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS)
42094209

42104210
Assert(res != NULL);
42114211

4212-
PG_RETURN_JSONB_VALUE_P(res);
4212+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, jb));
42134213
}
42144214

42154215
/*
@@ -4264,7 +4264,7 @@ jsonb_concat(PG_FUNCTION_ARGS)
42644264

42654265
Assert(res != NULL);
42664266

4267-
PG_RETURN_JSONB_VALUE_P(res);
4267+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, jb1));
42684268
}
42694269

42704270

@@ -4318,7 +4318,7 @@ jsonb_delete(PG_FUNCTION_ARGS)
43184318

43194319
Assert(res != NULL);
43204320

4321-
PG_RETURN_JSONB_VALUE_P(res);
4321+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, in));
43224322
}
43234323

43244324
/*
@@ -4403,7 +4403,7 @@ jsonb_delete_array(PG_FUNCTION_ARGS)
44034403

44044404
Assert(res != NULL);
44054405

4406-
PG_RETURN_JSONB_VALUE_P(res);
4406+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, in));
44074407
}
44084408

44094409
/*
@@ -4471,7 +4471,16 @@ jsonb_delete_idx(PG_FUNCTION_ARGS)
44714471

44724472
Assert(res != NULL);
44734473

4474-
PG_RETURN_JSONB_VALUE_P(res);
4474+
if (idx < 0 && -idx <= res->val.array.nElems)
4475+
{
4476+
idx = res->val.array.nElems + idx;
4477+
res->val.array.nElems--;
4478+
memmove(&res->val.array.elems[idx],
4479+
&res->val.array.elems[idx + 1],
4480+
sizeof(JsonValue) * (res->val.array.nElems - idx));
4481+
}
4482+
4483+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, in));
44754484
}
44764485

44774486
/*
@@ -4519,7 +4528,7 @@ jsonb_set(PG_FUNCTION_ARGS)
45194528

45204529
Assert(res != NULL);
45214530

4522-
PG_RETURN_JSONB_VALUE_P(res);
4531+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, in));
45234532
}
45244533

45254534

@@ -4630,7 +4639,7 @@ jsonb_delete_path(PG_FUNCTION_ARGS)
46304639

46314640
Assert(res != NULL);
46324641

4633-
PG_RETURN_JSONB_VALUE_P(res);
4642+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, in));
46344643
}
46354644

46364645
/*
@@ -4675,7 +4684,7 @@ jsonb_insert(PG_FUNCTION_ARGS)
46754684

46764685
Assert(res != NULL);
46774686

4678-
PG_RETURN_JSONB_VALUE_P(res);
4687+
PG_RETURN_DATUM(JsonbValueToOrigJsonbDatum(res, in));
46794688
}
46804689

46814690
/*

src/include/utils/json_generic.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef struct JsonContainerData
2929
int len;
3030
int size;
3131
JsonbValueType type;
32+
Oid toasterid;
3233
void *_data[FLEXIBLE_ARRAY_MEMBER];
3334
} JsonContainerData;
3435

@@ -63,6 +64,7 @@ struct JsonContainerOps
6364
int estimated_len);
6465
JsonContainer *(*copy)(JsonContainer *jc);
6566
void (*free)(JsonContainer *jc);
67+
void *(*encode)(JsonValue *jc, JsonContainerOps *ops);
6668
};
6769

6870
typedef struct CompressedObject
@@ -248,6 +250,7 @@ JsonValueInitBinary(JsonValue *val, JsonContainer *cont)
248250
}
249251

250252
extern Json *JsonValueToJson(JsonValue *val);
253+
extern Datum JsonbValueToOrigJsonbDatum(JsonValue *val, Json *origjs);
251254
extern JsonValue *JsonToJsonValue(Json *json, JsonValue *jv);
252255
extern JsonValue *JsonValueUnpackBinary(const JsonValue *jbv);
253256
extern JsonValue *JsonValueCopy(JsonValue *res, const JsonValue *val);
@@ -285,21 +288,22 @@ extern char *JsonbToCStringIndent(StringInfo out, JsonContainer *in,
285288
extern bool JsonValueScalarEquals(const JsonValue *aScalar,
286289
const JsonValue *bScalar);
287290

288-
typedef void (*JsonValueEncoder)(StringInfo, const JsonValue *);
291+
typedef void (*JsonValueEncoder)(StringInfo, const JsonValue *, void *cxt);
289292

290293
extern void *JsonContainerFlatten(JsonContainer *jc, JsonValueEncoder encoder,
291294
JsonContainerOps *ops, const JsonValue *binary);
292295

293296
extern void *JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
294297
JsonContainerOps *ops);
298+
extern void *JsonEncode(const JsonbValue *val, JsonValueEncoder encoder, void *cxt);
295299

296300
static inline void *
297301
JsonFlatten(Json *json, JsonValueEncoder encoder, JsonContainerOps *ops)
298302
{
299303
return JsonContainerFlatten(JsonRoot(json), encoder, ops, NULL);
300304
}
301305

302-
extern void JsonbEncode(StringInfo, const JsonValue *);
306+
extern void JsonbEncode(StringInfo, const JsonValue *, void *cxt);
303307

304308
#define JsonValueToJsonb(val) \
305309
JsonValueFlatten(val, JsonbEncode, &jsonbContainerOps)

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