Skip to content

Commit 1e2c673

Browse files
author
Nikita Glukhov
committed
Add support of json object/arrays with unknown size
1 parent ccbcdbb commit 1e2c673

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

src/backend/utils/adt/jsonb_gin.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ gin_extract_jsonb(PG_FUNCTION_ARGS)
244244
PG_RETURN_POINTER(NULL);
245245
}
246246

247+
if (total < 0)
248+
total = 8;
249+
247250
/* Otherwise, use 2 * root count as initial estimate of result size */
248251
init_gin_entries(&entries, 2 * total);
249252

@@ -1108,6 +1111,9 @@ gin_extract_jsonb_path(PG_FUNCTION_ARGS)
11081111
PG_RETURN_POINTER(NULL);
11091112
}
11101113

1114+
if (total < 0)
1115+
total = 8;
1116+
11111117
/* Otherwise, use 2 * root count as initial estimate of result size */
11121118
init_gin_entries(&entries, 2 * total);
11131119

src/backend/utils/adt/jsonfuncs.c

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

569569
state->result_size = JB_ROOT_COUNT(jb);
570+
if (state->result_size < 0)
571+
state->result_size = 8;
570572
state->result_count = 0;
571573
state->sent_count = 0;
572574
state->result = palloc(state->result_size * sizeof(char *));
@@ -584,6 +586,12 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
584586
cstr = palloc(v.val.string.len + 1 * sizeof(char));
585587
memcpy(cstr, v.val.string.val, v.val.string.len);
586588
cstr[v.val.string.len] = '\0';
589+
if (state->result_count >= state->result_size)
590+
{
591+
state->result_size *= 2;
592+
state->result = repalloc(state->result, state->result_size *
593+
sizeof(char *));
594+
}
587595
state->result[state->result_count++] = cstr;
588596
}
589597
}
@@ -900,7 +908,9 @@ jsonb_array_element(PG_FUNCTION_ARGS)
900908
/* Handle negative subscript */
901909
if (element < 0)
902910
{
903-
uint32 nelements = JB_ROOT_COUNT(jb);
911+
int nelements = JB_ROOT_COUNT(jb);
912+
if (nelements < 0)
913+
nelements = JsonGetArraySize(JsonRoot(jb));
904914

905915
if (-element > nelements)
906916
PG_RETURN_NULL();
@@ -944,6 +954,8 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
944954
if (element < 0)
945955
{
946956
uint32 nelements = JB_ROOT_COUNT(jb);
957+
if (nelements < 0)
958+
nelements = JsonGetArraySize(JsonRoot(jb));
947959

948960
if (-element > nelements)
949961
PG_RETURN_NULL();
@@ -1827,7 +1839,8 @@ jsonb_array_length(PG_FUNCTION_ARGS)
18271839
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
18281840
errmsg("cannot get array length of a non-array")));
18291841

1830-
PG_RETURN_INT32(JB_ROOT_COUNT(jb));
1842+
PG_RETURN_INT32(JB_ROOT_COUNT(jb) >= 0 ? JB_ROOT_COUNT(jb)
1843+
: JsonGetArraySize(JsonRoot(jb)));
18311844
}
18321845

18331846
/*
@@ -4536,16 +4549,19 @@ jsonb_delete_idx(PG_FUNCTION_ARGS)
45364549
Assert(r == WJB_BEGIN_ARRAY);
45374550
n = v.val.array.nElems;
45384551

4539-
if (idx < 0)
4552+
if (v.val.array.nElems >= 0)
45404553
{
4541-
if (-idx > n)
4542-
idx = n;
4543-
else
4544-
idx = n + idx;
4545-
}
4554+
if (idx < 0)
4555+
{
4556+
if (-idx > n)
4557+
idx = n;
4558+
else
4559+
idx = n + idx;
4560+
}
45464561

4547-
if (idx >= n)
4548-
PG_RETURN_JSONB_P(in);
4562+
if (idx >= n)
4563+
PG_RETURN_JSONB_P(in);
4564+
}
45494565

45504566
pushJsonbValue(&state, r, NULL);
45514567

@@ -4562,6 +4578,15 @@ jsonb_delete_idx(PG_FUNCTION_ARGS)
45624578

45634579
Assert(res != NULL);
45644580

4581+
if (idx < 0 && -idx <= res->val.array.nElems)
4582+
{
4583+
idx = res->val.array.nElems + idx;
4584+
res->val.array.nElems--;
4585+
memmove(&res->val.array.elems[idx],
4586+
&res->val.array.elems[idx + 1],
4587+
sizeof(JsonValue) * (res->val.array.nElems - idx));
4588+
}
4589+
45654590
PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
45664591
}
45674592

@@ -4946,7 +4971,8 @@ setPath(JsonbIterator **it, Datum *path_elems,
49464971

49474972
(void) pushJsonbValue(st, r, NULL);
49484973
setPathArray(it, path_elems, path_nulls, path_len, st, level,
4949-
newval, v.val.array.nElems, op_type);
4974+
newval, v.val.array.nElems >= 0 ? v.val.array.nElems :
4975+
JsonGetArraySize((*it)->container), op_type);
49504976
r = JsonbIteratorNext(it, &v, false);
49514977
Assert(r == WJB_END_ARRAY);
49524978
res = pushJsonbValue(st, r, NULL);

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2158,7 +2158,11 @@ JsonbArraySize(JsonbValue *jb)
21582158
JsonbContainer *jbc = jb->val.binary.data;
21592159

21602160
if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
2161-
return JsonContainerSize(jbc);
2161+
{
2162+
int size = JsonContainerSize(jbc);
2163+
2164+
return size >= 0 ? size : JsonGetArraySize(jbc);
2165+
}
21622166
}
21632167

21642168
return -1;

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