Skip to content

Commit 113e5ce

Browse files
author
Nikita Glukhov
committed
Add support of json object/arrays with unknown size
1 parent 95898b4 commit 113e5ce

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

src/backend/utils/adt/jsonb_gin.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ gin_extract_jsonb(PG_FUNCTION_ARGS)
8383
PG_RETURN_POINTER(NULL);
8484
}
8585

86+
if (total < 0)
87+
total = 8;
88+
8689
/* Otherwise, use 2 * root count as initial estimate of result size */
8790
entries = (Datum *) palloc(sizeof(Datum) * total);
8891

@@ -348,6 +351,9 @@ gin_extract_jsonb_path(PG_FUNCTION_ARGS)
348351
PG_RETURN_POINTER(NULL);
349352
}
350353

354+
if (total < 0)
355+
total = 8;
356+
351357
/* Otherwise, use 2 * root count as initial estimate of result size */
352358
entries = (Datum *) palloc(sizeof(Datum) * total);
353359

src/backend/utils/adt/jsonfuncs.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
513513
state = palloc(sizeof(OkeysState));
514514

515515
state->result_size = JB_ROOT_COUNT(jb);
516+
if (state->result_size < 0)
517+
state->result_size = 8;
516518
state->result_count = 0;
517519
state->sent_count = 0;
518520
state->result = palloc(state->result_size * sizeof(char *));
@@ -530,6 +532,12 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
530532
cstr = palloc(v.val.string.len + 1 * sizeof(char));
531533
memcpy(cstr, v.val.string.val, v.val.string.len);
532534
cstr[v.val.string.len] = '\0';
535+
if (state->result_count >= state->result_size)
536+
{
537+
state->result_size *= 2;
538+
state->result = repalloc(state->result, state->result_size *
539+
sizeof(char *));
540+
}
533541
state->result[state->result_count++] = cstr;
534542
}
535543
}
@@ -806,7 +814,9 @@ jsonb_array_element(PG_FUNCTION_ARGS)
806814
/* Handle negative subscript */
807815
if (element < 0)
808816
{
809-
uint32 nelements = JB_ROOT_COUNT(jb);
817+
int nelements = JB_ROOT_COUNT(jb);
818+
if (nelements < 0)
819+
nelements = JsonGetArraySize(JsonRoot(jb));
810820

811821
if (-element > nelements)
812822
PG_RETURN_NULL();
@@ -850,6 +860,8 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
850860
if (element < 0)
851861
{
852862
uint32 nelements = JB_ROOT_COUNT(jb);
863+
if (nelements < 0)
864+
nelements = JsonGetArraySize(JsonRoot(jb));
853865

854866
if (-element > nelements)
855867
PG_RETURN_NULL();
@@ -1576,7 +1588,8 @@ jsonb_array_length(PG_FUNCTION_ARGS)
15761588
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
15771589
errmsg("cannot get array length of a non-array")));
15781590

1579-
PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1591+
PG_RETURN_INT32(JB_ROOT_COUNT(jb) >= 0 ? JB_ROOT_COUNT(jb)
1592+
: JsonGetArraySize(JsonRoot(jb)));
15801593
}
15811594

15821595
/*
@@ -4211,16 +4224,19 @@ jsonb_delete_idx(PG_FUNCTION_ARGS)
42114224
Assert(r == WJB_BEGIN_ARRAY);
42124225
n = v.val.array.nElems;
42134226

4214-
if (idx < 0)
4227+
if (v.val.array.nElems >= 0)
42154228
{
4216-
if (-idx > n)
4217-
idx = n;
4218-
else
4219-
idx = n + idx;
4220-
}
4229+
if (idx < 0)
4230+
{
4231+
if (-idx > n)
4232+
idx = n;
4233+
else
4234+
idx = n + idx;
4235+
}
42214236

4222-
if (idx >= n)
4223-
PG_RETURN_JSONB(in);
4237+
if (idx >= n)
4238+
PG_RETURN_JSONB(in);
4239+
}
42244240

42254241
pushJsonbValue(&state, r, NULL);
42264242

@@ -4237,6 +4253,15 @@ jsonb_delete_idx(PG_FUNCTION_ARGS)
42374253

42384254
Assert(res != NULL);
42394255

4256+
if (idx < 0 && -idx <= res->val.array.nElems)
4257+
{
4258+
idx = res->val.array.nElems + idx;
4259+
res->val.array.nElems--;
4260+
memmove(&res->val.array.elems[idx],
4261+
&res->val.array.elems[idx + 1],
4262+
sizeof(JsonValue) * (res->val.array.nElems - idx));
4263+
}
4264+
42404265
PG_RETURN_JSONB(JsonbValueToJsonb(res));
42414266
}
42424267

@@ -4525,7 +4550,8 @@ setPath(JsonbIterator **it, Datum *path_elems,
45254550
case WJB_BEGIN_ARRAY:
45264551
(void) pushJsonbValue(st, r, NULL);
45274552
setPathArray(it, path_elems, path_nulls, path_len, st, level,
4528-
newval, v.val.array.nElems, op_type);
4553+
newval, v.val.array.nElems >= 0 ? v.val.array.nElems :
4554+
JsonGetArraySize((*it)->container), op_type);
45294555
r = JsonbIteratorNext(it, &v, false);
45304556
Assert(r == WJB_END_ARRAY);
45314557
res = pushJsonbValue(st, r, NULL);

0 commit comments

Comments
 (0)