Skip to content

Commit 7d28bac

Browse files
author
Nikita Glukhov
committed
Add temporary stack-allocated expanded Jsons
1 parent af398f9 commit 7d28bac

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
@@ -304,7 +304,7 @@ jsonb_string_to_tsvector_byid(PG_FUNCTION_ARGS)
304304
TSVector result;
305305

306306
result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
307-
PG_FREE_IF_COPY(jb, 1);
307+
PG_FREE_IF_COPY_JSONB(jb, 1);
308308

309309
PG_RETURN_TSVECTOR(result);
310310
}
@@ -318,7 +318,7 @@ jsonb_string_to_tsvector(PG_FUNCTION_ARGS)
318318

319319
cfgId = getTSCurrentConfig(true);
320320
result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
321-
PG_FREE_IF_COPY(jb, 0);
321+
PG_FREE_IF_COPY_JSONB(jb, 0);
322322

323323
PG_RETURN_TSVECTOR(result);
324324
}
@@ -333,8 +333,8 @@ jsonb_to_tsvector_byid(PG_FUNCTION_ARGS)
333333
uint32 flags = parse_jsonb_index_flags(jbFlags);
334334

335335
result = jsonb_to_tsvector_worker(cfgId, jb, flags);
336-
PG_FREE_IF_COPY(jb, 1);
337-
PG_FREE_IF_COPY(jbFlags, 2);
336+
PG_FREE_IF_COPY_JSONB(jb, 1);
337+
PG_FREE_IF_COPY_JSONB(jbFlags, 2);
338338

339339
PG_RETURN_TSVECTOR(result);
340340
}
@@ -350,8 +350,8 @@ jsonb_to_tsvector(PG_FUNCTION_ARGS)
350350

351351
cfgId = getTSCurrentConfig(true);
352352
result = jsonb_to_tsvector_worker(cfgId, jb, flags);
353-
PG_FREE_IF_COPY(jb, 0);
354-
PG_FREE_IF_COPY(jbFlags, 1);
353+
PG_FREE_IF_COPY_JSONB(jb, 0);
354+
PG_FREE_IF_COPY_JSONB(jbFlags, 1);
355355

356356
PG_RETURN_TSVECTOR(result);
357357
}
@@ -397,7 +397,11 @@ json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
397397
TSVector result;
398398

399399
result = json_to_tsvector_worker(cfgId, json, jtiString);
400+
#ifndef JSON_GENERIC
400401
PG_FREE_IF_COPY(json, 1);
402+
#else
403+
PG_FREE_IF_COPY_JSONB(json, 1);
404+
#endif
401405

402406
PG_RETURN_TSVECTOR(result);
403407
}
@@ -415,7 +419,11 @@ json_string_to_tsvector(PG_FUNCTION_ARGS)
415419

416420
cfgId = getTSCurrentConfig(true);
417421
result = json_to_tsvector_worker(cfgId, json, jtiString);
422+
#ifndef JSON_GENERIC
418423
PG_FREE_IF_COPY(json, 0);
424+
#else
425+
PG_FREE_IF_COPY_JSONB(json, 0);
426+
#endif
419427

420428
PG_RETURN_TSVECTOR(result);
421429
}
@@ -434,8 +442,12 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS)
434442
uint32 flags = parse_jsonb_index_flags(jbFlags);
435443

436444
result = json_to_tsvector_worker(cfgId, json, flags);
445+
#ifndef JSON_GENERIC
437446
PG_FREE_IF_COPY(json, 1);
438-
PG_FREE_IF_COPY(jbFlags, 2);
447+
#else
448+
PG_FREE_IF_COPY_JSONB(json, 1);
449+
#endif
450+
PG_FREE_IF_COPY_JSONB(jbFlags, 2);
439451

440452
PG_RETURN_TSVECTOR(result);
441453
}
@@ -455,8 +467,12 @@ json_to_tsvector(PG_FUNCTION_ARGS)
455467

456468
cfgId = getTSCurrentConfig(true);
457469
result = json_to_tsvector_worker(cfgId, json, flags);
470+
#ifndef JSON_GENERIC
458471
PG_FREE_IF_COPY(json, 0);
459-
PG_FREE_IF_COPY(jbFlags, 1);
472+
#else
473+
PG_FREE_IF_COPY_JSONB(json, 0);
474+
#endif
475+
PG_FREE_IF_COPY_JSONB(jbFlags, 1);
460476

461477
PG_RETURN_TSVECTOR(result);
462478
}

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