Skip to content

Commit 9b8181e

Browse files
author
Nikita Glukhov
committed
Add temporary stack-allocated expanded Jsons
1 parent d1f2f5a commit 9b8181e

File tree

9 files changed

+196
-79
lines changed

9 files changed

+196
-79
lines changed

src/backend/tsearch/to_tsany.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ jsonb_string_to_tsvector_byid(PG_FUNCTION_ARGS)
294294
TSVector result;
295295

296296
result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
297-
PG_FREE_IF_COPY(jb, 1);
297+
PG_FREE_IF_COPY_JSONB(jb, 1);
298298

299299
PG_RETURN_TSVECTOR(result);
300300
}
@@ -308,7 +308,7 @@ jsonb_string_to_tsvector(PG_FUNCTION_ARGS)
308308

309309
cfgId = getTSCurrentConfig(true);
310310
result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
311-
PG_FREE_IF_COPY(jb, 0);
311+
PG_FREE_IF_COPY_JSONB(jb, 0);
312312

313313
PG_RETURN_TSVECTOR(result);
314314
}
@@ -323,8 +323,8 @@ jsonb_to_tsvector_byid(PG_FUNCTION_ARGS)
323323
uint32 flags = parse_jsonb_index_flags(jbFlags);
324324

325325
result = jsonb_to_tsvector_worker(cfgId, jb, flags);
326-
PG_FREE_IF_COPY(jb, 1);
327-
PG_FREE_IF_COPY(jbFlags, 2);
326+
PG_FREE_IF_COPY_JSONB(jb, 1);
327+
PG_FREE_IF_COPY_JSONB(jbFlags, 2);
328328

329329
PG_RETURN_TSVECTOR(result);
330330
}
@@ -340,8 +340,8 @@ jsonb_to_tsvector(PG_FUNCTION_ARGS)
340340

341341
cfgId = getTSCurrentConfig(true);
342342
result = jsonb_to_tsvector_worker(cfgId, jb, flags);
343-
PG_FREE_IF_COPY(jb, 0);
344-
PG_FREE_IF_COPY(jbFlags, 1);
343+
PG_FREE_IF_COPY_JSONB(jb, 0);
344+
PG_FREE_IF_COPY_JSONB(jbFlags, 1);
345345

346346
PG_RETURN_TSVECTOR(result);
347347
}
@@ -387,7 +387,11 @@ json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
387387
TSVector result;
388388

389389
result = json_to_tsvector_worker(cfgId, json, jtiString);
390+
#ifndef JSON_GENERIC
390391
PG_FREE_IF_COPY(json, 1);
392+
#else
393+
PG_FREE_IF_COPY_JSONB(json, 1);
394+
#endif
391395

392396
PG_RETURN_TSVECTOR(result);
393397
}
@@ -405,7 +409,11 @@ json_string_to_tsvector(PG_FUNCTION_ARGS)
405409

406410
cfgId = getTSCurrentConfig(true);
407411
result = json_to_tsvector_worker(cfgId, json, jtiString);
412+
#ifndef JSON_GENERIC
408413
PG_FREE_IF_COPY(json, 0);
414+
#else
415+
PG_FREE_IF_COPY_JSONB(json, 0);
416+
#endif
409417

410418
PG_RETURN_TSVECTOR(result);
411419
}
@@ -424,8 +432,12 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS)
424432
uint32 flags = parse_jsonb_index_flags(jbFlags);
425433

426434
result = json_to_tsvector_worker(cfgId, json, flags);
435+
#ifndef JSON_GENERIC
427436
PG_FREE_IF_COPY(json, 1);
428-
PG_FREE_IF_COPY(jbFlags, 2);
437+
#else
438+
PG_FREE_IF_COPY_JSONB(json, 1);
439+
#endif
440+
PG_FREE_IF_COPY_JSONB(jbFlags, 2);
429441

430442
PG_RETURN_TSVECTOR(result);
431443
}
@@ -445,8 +457,12 @@ json_to_tsvector(PG_FUNCTION_ARGS)
445457

446458
cfgId = getTSCurrentConfig(true);
447459
result = json_to_tsvector_worker(cfgId, json, flags);
460+
#ifndef JSON_GENERIC
448461
PG_FREE_IF_COPY(json, 0);
449-
PG_FREE_IF_COPY(jbFlags, 1);
462+
#else
463+
PG_FREE_IF_COPY_JSONB(json, 0);
464+
#endif
465+
PG_FREE_IF_COPY_JSONB(jbFlags, 1);
450466

451467
PG_RETURN_TSVECTOR(result);
452468
}

src/backend/tsearch/wparser.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
407407
/* flatten result to jsonb before jb freeing */
408408
res = JsonFlattenToJsonbDatum(out);
409409

410-
PG_FREE_IF_COPY(jb, 1);
410+
PG_FREE_IF_COPY_JSONB(jb, 1);
411411
PG_FREE_IF_COPY(query, 2);
412412
if (opt)
413413
PG_FREE_IF_COPY(opt, 3);
@@ -488,6 +488,7 @@ ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
488488

489489
#ifndef JSON_GENERIC
490490
out = transform_json_string_values(json, state, action);
491+
PG_FREE_IF_COPY(json, 1);
491492
#else
492493
{
493494
Jsonb *jsonb = transform_jsonb_string_values(json, state, action);
@@ -496,10 +497,11 @@ ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
496497
out = cstring_to_text(str);
497498

498499
pfree(str);
500+
501+
PG_FREE_IF_COPY_JSONB(json, 1);
499502
}
500503
#endif
501504

502-
PG_FREE_IF_COPY(json, 1);
503505
PG_FREE_IF_COPY(query, 2);
504506
if (opt)
505507
PG_FREE_IF_COPY(opt, 3);

src/backend/utils/adt/expandeddatum.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515
#include "postgres.h"
1616

17+
#include "utils/datum.h"
1718
#include "utils/expandeddatum.h"
1819
#include "utils/memutils.h"
1920

@@ -122,6 +123,9 @@ TransferExpandedObject(Datum d, MemoryContext new_parent)
122123
/* Assert caller gave a R/W pointer */
123124
Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)));
124125

126+
if (!eohptr->eoh_context)
127+
return datumCopy(d, false, -1);
128+
125129
/* Transfer ownership */
126130
MemoryContextSetParent(eohptr->eoh_context, new_parent);
127131

@@ -141,5 +145,8 @@ DeleteExpandedObject(Datum d)
141145
Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)));
142146

143147
/* Kill it */
144-
MemoryContextDelete(eohptr->eoh_context);
148+
if (eohptr->eoh_context)
149+
MemoryContextDelete(eohptr->eoh_context);
150+
else
151+
pfree(eohptr);
145152
}

src/backend/utils/adt/json_generic.c

Lines changed: 89 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
static JsonContainerOps jsonvContainerOps;
1818

19-
static Json *JsonExpand(Datum value, JsonContainerOps *ops);
19+
static Json *JsonExpand(Json *tmp, Datum value, bool freeValue,
20+
JsonContainerOps *ops);
21+
2022

2123
#if 0
2224
static JsonValue *
@@ -608,8 +610,7 @@ jsonWriteExtended(JsonContainer *jc, void *ptr, Size allocated_size)
608610
}
609611

610612
static Json *
611-
JsonInitExtended(const struct varlena *toasted,
612-
const struct varlena *detoasted)
613+
JsonInitExtended(Json *tmp, struct varlena *extvalue, bool freeValue)
613614
{
614615
JsonContainerOps *ops;
615616
CompressionMethodRoutine *cmr;
@@ -619,10 +620,12 @@ JsonInitExtended(const struct varlena *toasted,
619620
int len;
620621
Datum value;
621622

622-
Assert(VARATT_IS_EXTERNAL_EXTENDED(detoasted));
623+
Assert(VARATT_IS_EXTERNAL_EXTENDED(extvalue));
624+
625+
pextjs = (varatt_extended_json *) VARDATA_EXTERNAL(extvalue);
626+
memcpy(&extjs, pextjs, offsetof(varatt_extended_json, data));
623627

624-
pextjs = (varatt_extended_json *) VARDATA_EXTERNAL(detoasted);
625-
memcpy(&extjs, pextjs, offsetof(varatt_extended_json, params));
628+
totalSize = extjs.vaext.size - offsetof(varatt_extended_json, data);
626629

627630
ops = JsonContainerGetOpsByType(extjs.type);
628631

@@ -642,8 +645,11 @@ JsonInitExtended(const struct varlena *toasted,
642645
SET_VARSIZE(val, VARHDRSZ + len);
643646
memcpy(VARDATA(val), &pextjs->params, len);
644647

648+
if (freeValue)
649+
pfree(extvalue);
650+
645651
if (ops)
646-
return JsonExpand(PointerGetDatum(val), ops);
652+
return JsonExpand(tmp, value, true, ops);
647653

648654
value = cmr->decompress(PointerGetDatum(val), NULL);
649655

@@ -656,19 +662,19 @@ JsonInitExtended(const struct varlena *toasted,
656662
static void
657663
JsonInit(Json *json)
658664
{
659-
const void *data = DatumGetPointer(json->obj.compressed);
665+
const void *data = DatumGetPointer(json->obj.value);
666+
const void *detoasted_data;
660667

661668
Assert(json->root.data || data);
662669

663670
if (json->root.data || !data)
664671
return;
665672

666-
data = PG_DETOAST_DATUM(json->obj.compressed);
667-
668-
/* Assert(!VARATT_IS_EXTERNAL_EXTENDED(data)); */
669-
json->obj.compressed = PointerGetDatum(data);
673+
detoasted_data = PG_DETOAST_DATUM(json->obj.value);
674+
json->obj.value = PointerGetDatum(detoasted_data);
675+
json->obj.freeValue |= data != detoasted_data;
670676

671-
(*json->root.ops->init)(&json->root, json->obj.compressed);
677+
json->root.ops->init(&json->root, json->obj.value);
672678
}
673679

674680
static Size
@@ -824,27 +830,41 @@ jsonExpandedObjectMethods =
824830
};
825831

826832
static Json *
827-
JsonExpand(Datum value, JsonContainerOps *ops)
833+
JsonExpand(Json *tmp, Datum value, bool freeValue, JsonContainerOps *ops)
828834
{
829835
MemoryContext objcxt;
830836
Json *json;
831837

832-
/*
833-
* Allocate private context for expanded object. We start by assuming
834-
* that the json won't be very large; but if it does grow a lot, don't
835-
* constrain aset.c's large-context behavior.
836-
*/
837-
objcxt = AllocSetContextCreate(CurrentMemoryContext,
838-
"expanded json",
839-
ALLOCSET_SMALL_MINSIZE,
840-
ALLOCSET_SMALL_INITSIZE,
841-
ALLOCSET_DEFAULT_MAXSIZE);
842-
843-
json = (Json *) MemoryContextAlloc(objcxt, sizeof(Json));
838+
if (tmp)
839+
{
840+
json = tmp;
841+
json->obj.eoh.vl_len_ = 0;
842+
}
843+
else
844+
{
845+
#ifndef JSON_EXPANDED_OBJECT_MCXT
846+
json = (Json *) palloc(sizeof(Json));
847+
objcxt = NULL;
848+
#else
849+
/*
850+
* Allocate private context for expanded object. We start by assuming
851+
* that the json won't be very large; but if it does grow a lot, don't
852+
* constrain aset.c's large-context behavior.
853+
*/
854+
objcxt = AllocSetContextCreate(CurrentMemoryContext,
855+
"expanded json",
856+
ALLOCSET_SMALL_MINSIZE,
857+
ALLOCSET_SMALL_INITSIZE,
858+
ALLOCSET_DEFAULT_MAXSIZE);
859+
860+
json = (Json *) MemoryContextAlloc(objcxt, sizeof(Json));
861+
#endif
844862

845-
EOH_init_header(&json->obj.eoh, &jsonExpandedObjectMethods, objcxt);
863+
EOH_init_header(&json->obj.eoh, &jsonExpandedObjectMethods, objcxt);
864+
}
846865

847-
json->obj.compressed = value;
866+
json->obj.value = value;
867+
json->obj.freeValue = freeValue;
848868
json->root.data = NULL;
849869
json->root.len = 0;
850870
json->root.ops = ops;
@@ -855,8 +875,8 @@ JsonExpand(Datum value, JsonContainerOps *ops)
855875
return json;
856876
}
857877

858-
Json *
859-
DatumGetJson(Datum value, JsonContainerOps *ops)
878+
static Json *
879+
JsonExpandDatum(Datum value, JsonContainerOps *ops, Json *tmp)
860880
{
861881
struct varlena *toasted = (struct varlena *) DatumGetPointer(value);
862882
Json *json;
@@ -870,32 +890,66 @@ DatumGetJson(Datum value, JsonContainerOps *ops)
870890
/*
871891
if (VARATT_IS_EXTERNAL_EXTENDED(detoasted))
872892
#ifdef JSON_FLATTEN_INTO_JSONEXT
873-
return JsonInitExtended(toasted, detoasted);
893+
return JsonInitExtended(tmp, detoasted, toasted != detoasted);
874894
#else
875895
elog(ERROR, "unexpected extended json");
876896
#endif
877897
*/
878898

879-
json = JsonExpand(PointerGetDatum(detoasted), ops);
899+
json = JsonExpand(tmp, PointerGetDatum(detoasted), toasted != detoasted,
900+
ops);
880901
}
881902

903+
return json;
904+
}
905+
906+
Json *
907+
DatumGetJson(Datum value, JsonContainerOps *ops, Json *tmp)
908+
{
909+
Json *json = JsonExpandDatum(value, ops, tmp);
882910
JsonInit(json);
883911

884912
return json;
885913
}
886914

915+
void
916+
JsonFree(Json *json)
917+
{
918+
if (json->obj.freeValue)
919+
pfree(DatumGetPointer(json->obj.value));
920+
921+
if (!JsonIsTemporary(json))
922+
pfree(json);
923+
}
924+
925+
Json *
926+
JsonCopyTemporary(Json *tmp)
927+
{
928+
Json *json = (Json *) palloc(sizeof(Json));
929+
930+
memcpy(json, tmp, sizeof(Json));
931+
tmp->obj.freeValue = false;
932+
933+
EOH_init_header(&json->obj.eoh, &jsonExpandedObjectMethods, NULL);
934+
935+
return json;
936+
}
937+
887938
Json *
888939
JsonValueToJson(JsonValue *val)
889940
{
890941
if (val->type == jbvBinary)
891942
{
892-
Json *json = JsonExpand(PointerGetDatum(NULL), NULL);
893-
json->root = *val->val.binary.data;
943+
JsonContainer *jc = val->val.binary.data;
944+
Json *json = JsonExpand(NULL, PointerGetDatum(NULL), false,
945+
jc->ops);
946+
json->root = *jc;
894947
return json;
895948
}
896949
else
897950
{
898-
Json *json = JsonExpand(PointerGetDatum(NULL), &jsonvContainerOps);
951+
Json *json = JsonExpand(NULL, PointerGetDatum(NULL), false,
952+
&jsonvContainerOps);
899953
jsonvInitContainer(&json->root, val);
900954
return json;
901955
}

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