3 * Test jsonb delete operator functions for 9.4+
5 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
7 * Author: Glyn Astill <glyn@8kb.co.uk>
13 #include "utils/jsonb.h"
14 #include "utils/builtins.h"
15 #include "jsonb_delete.h"
17 #ifdef PG_MODULE_MAGIC
21 Datum jsonb_delete_jsonb(PG_FUNCTION_ARGS);
23 PG_FUNCTION_INFO_V1(jsonb_delete_jsonb);
26 * Operator function to delete top level keys and values from left operand
27 * where a match is found in the right operand.
29 * jsonb, jsonb -> jsonb
33 jsonb_delete_jsonb(PG_FUNCTION_ARGS)
35 Jsonb *jb1 = PG_GETARG_JSONB(0);
36 Jsonb *jb2 = PG_GETARG_JSONB(1);
37 JsonbValue *res = NULL;
38 JsonbParseState *state = NULL;
39 JsonbIterator *it, *it2;
42 JsonbValue *lookup = NULL;
46 /* check if right jsonb is empty and return left if so */
47 if (JB_ROOT_COUNT(jb2) == 0)
50 it = JsonbIteratorInit(&jb1->root);
52 while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
59 case WJB_BEGIN_OBJECT:
62 res = pushJsonbValue(&state, r, NULL);
65 if (v.type == jbvBinary)
67 it2 = JsonbIteratorInit(&jb2->root);
68 while ((r2 = JsonbIteratorNext(&it2, &v2, true)) != WJB_DONE)
70 if (v2.type == jbvBinary && v2.val.binary.len == v.val.binary.len &&
71 memcmp(v2.val.binary.data, v.val.binary.data, v2.val.binary.len) == 0)
78 else if (findJsonbValueFromContainer(&jb2->root, JB_FARRAY, &v) != NULL)
83 if (v.type == jbvBinary)
84 res = pushJsonbBinary(&state, v.val.binary.data);
86 res = pushJsonbValue(&state, WJB_ELEM, &v);
90 lookup = findJsonbValueFromContainer(&jb2->root, JB_FOBJECT, &v);
93 r = JsonbIteratorNext(&it, &v, true);
95 Assert(r == WJB_VALUE);
97 if (lookup != NULL && lookup->type == v.type)
101 /* Nulls within json are equal, but should not be equal to SQL nulls */
106 if (DatumGetBool(DirectFunctionCall2(numeric_eq,
107 PointerGetDatum(lookup->val.numeric),
108 PointerGetDatum(v.val.numeric))))
112 if ((lookup->val.string.len == v.val.string.len) &&
113 (memcmp(lookup->val.string.val,
115 lookup->val.string.len) == 0))
119 if ((lookup->val.binary.len == v.val.binary.len) &&
120 (memcmp(lookup->val.binary.data,
122 lookup->val.binary.len) == 0))
126 if (lookup->val.boolean == v.val.boolean)
130 ereport(ERROR, (errcode(ERRCODE_SUCCESSFUL_COMPLETION), errmsg("unrecognized lookup type: %d", (int) lookup->type)));
131 /* inner switch end */
137 res = pushJsonbValue(&state, WJB_KEY, &key);
139 /* if our value is nested binary data, iterate separately pushing each val */
140 if (v.type == jbvBinary)
141 res = pushJsonbBinary(&state, v.val.binary.data);
143 res = pushJsonbValue(&state, r, &v);
147 /* should not be possible */
149 elog(ERROR, "impossible state: %d", r);
155 if (JB_ROOT_IS_SCALAR(jb1) && !res->val.array.rawScalar && res->val.array.nElems == 1)
156 res->val.array.rawScalar = true;
158 PG_FREE_IF_COPY(jb1, 0);
159 PG_FREE_IF_COPY(jb2, 1);
161 PG_RETURN_JSONB(JsonbValueToJsonb(res));