mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Implement array version of jsonb_delete and operator
This makes it possible to delete multiple keys from a jsonb value by passing in an array of text values, which makes the operaiton much faster than individually deleting the keys (which would require copying the jsonb structure over and over again. Reviewed by Dmitry Dolgov and Michael Paquier
This commit is contained in:
@ -3437,6 +3437,92 @@ jsonb_delete(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_JSONB(JsonbValueToJsonb(res));
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function jsonb_delete (jsonb, variadic text[])
|
||||
*
|
||||
* return a copy of the jsonb with the indicated items
|
||||
* removed.
|
||||
*/
|
||||
Datum
|
||||
jsonb_delete_array(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Jsonb *in = PG_GETARG_JSONB(0);
|
||||
ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
|
||||
Datum *keys_elems;
|
||||
bool *keys_nulls;
|
||||
int keys_len;
|
||||
JsonbParseState *state = NULL;
|
||||
JsonbIterator *it;
|
||||
JsonbValue v,
|
||||
*res = NULL;
|
||||
bool skipNested = false;
|
||||
JsonbIteratorToken r;
|
||||
|
||||
if (ARR_NDIM(keys) > 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||
errmsg("wrong number of array subscripts")));
|
||||
|
||||
if (JB_ROOT_IS_SCALAR(in))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("cannot delete from scalar")));
|
||||
|
||||
if (JB_ROOT_COUNT(in) == 0)
|
||||
PG_RETURN_JSONB(in);
|
||||
|
||||
deconstruct_array(keys, TEXTOID, -1, false, 'i',
|
||||
&keys_elems, &keys_nulls, &keys_len);
|
||||
|
||||
if (keys_len == 0)
|
||||
PG_RETURN_JSONB(in);
|
||||
|
||||
it = JsonbIteratorInit(&in->root);
|
||||
|
||||
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
|
||||
{
|
||||
skipNested = true;
|
||||
|
||||
if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
|
||||
{
|
||||
int i;
|
||||
bool found = false;
|
||||
|
||||
for (i = 0; i < keys_len; i++)
|
||||
{
|
||||
char *keyptr;
|
||||
int keylen;
|
||||
|
||||
if (keys_nulls[i])
|
||||
continue;
|
||||
|
||||
keyptr = VARDATA_ANY(keys_elems[i]);
|
||||
keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
|
||||
if (keylen == v.val.string.len &&
|
||||
memcmp(keyptr, v.val.string.val, keylen) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
/* skip corresponding value as well */
|
||||
if (r == WJB_KEY)
|
||||
JsonbIteratorNext(&it, &v, true);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
|
||||
}
|
||||
|
||||
Assert(res != NULL);
|
||||
|
||||
PG_RETURN_JSONB(JsonbValueToJsonb(res));
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function jsonb_delete (jsonb, int)
|
||||
*
|
||||
|
Reference in New Issue
Block a user