]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/jsonb_op.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / utils / adt / jsonb_op.c
1 /*-------------------------------------------------------------------------
2  *
3  * jsonb_op.c
4  *       Special operators for jsonb only, used by various index access methods
5  *
6  * Copyright (c) 2014-2019, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  *        src/backend/utils/adt/jsonb_op.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include "catalog/pg_type.h"
17 #include "miscadmin.h"
18 #include "utils/builtins.h"
19 #include "utils/jsonb.h"
20
21 Datum
22 jsonb_exists(PG_FUNCTION_ARGS)
23 {
24         Jsonb      *jb = PG_GETARG_JSONB_P(0);
25         text       *key = PG_GETARG_TEXT_PP(1);
26         JsonbValue      kval;
27         JsonbValue *v = NULL;
28
29         /*
30          * We only match Object keys (which are naturally always Strings), or
31          * string elements in arrays.  In particular, we do not match non-string
32          * scalar elements.  Existence of a key/element is only considered at the
33          * top level.  No recursion occurs.
34          */
35         kval.type = jbvString;
36         kval.val.string.val = VARDATA_ANY(key);
37         kval.val.string.len = VARSIZE_ANY_EXHDR(key);
38
39         v = findJsonbValueFromContainer(&jb->root,
40                                                                         JB_FOBJECT | JB_FARRAY,
41                                                                         &kval);
42
43         PG_RETURN_BOOL(v != NULL);
44 }
45
46 Datum
47 jsonb_exists_any(PG_FUNCTION_ARGS)
48 {
49         Jsonb      *jb = PG_GETARG_JSONB_P(0);
50         ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
51         int                     i;
52         Datum      *key_datums;
53         bool       *key_nulls;
54         int                     elem_count;
55
56         deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
57                                           &elem_count);
58
59         for (i = 0; i < elem_count; i++)
60         {
61                 JsonbValue      strVal;
62
63                 if (key_nulls[i])
64                         continue;
65
66                 strVal.type = jbvString;
67                 strVal.val.string.val = VARDATA(key_datums[i]);
68                 strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
69
70                 if (findJsonbValueFromContainer(&jb->root,
71                                                                                 JB_FOBJECT | JB_FARRAY,
72                                                                                 &strVal) != NULL)
73                         PG_RETURN_BOOL(true);
74         }
75
76         PG_RETURN_BOOL(false);
77 }
78
79 Datum
80 jsonb_exists_all(PG_FUNCTION_ARGS)
81 {
82         Jsonb      *jb = PG_GETARG_JSONB_P(0);
83         ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
84         int                     i;
85         Datum      *key_datums;
86         bool       *key_nulls;
87         int                     elem_count;
88
89         deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
90                                           &elem_count);
91
92         for (i = 0; i < elem_count; i++)
93         {
94                 JsonbValue      strVal;
95
96                 if (key_nulls[i])
97                         continue;
98
99                 strVal.type = jbvString;
100                 strVal.val.string.val = VARDATA(key_datums[i]);
101                 strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
102
103                 if (findJsonbValueFromContainer(&jb->root,
104                                                                                 JB_FOBJECT | JB_FARRAY,
105                                                                                 &strVal) == NULL)
106                         PG_RETURN_BOOL(false);
107         }
108
109         PG_RETURN_BOOL(true);
110 }
111
112 Datum
113 jsonb_contains(PG_FUNCTION_ARGS)
114 {
115         Jsonb      *val = PG_GETARG_JSONB_P(0);
116         Jsonb      *tmpl = PG_GETARG_JSONB_P(1);
117
118         JsonbIterator *it1,
119                            *it2;
120
121         if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
122                 PG_RETURN_BOOL(false);
123
124         it1 = JsonbIteratorInit(&val->root);
125         it2 = JsonbIteratorInit(&tmpl->root);
126
127         PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
128 }
129
130 Datum
131 jsonb_contained(PG_FUNCTION_ARGS)
132 {
133         /* Commutator of "contains" */
134         Jsonb      *tmpl = PG_GETARG_JSONB_P(0);
135         Jsonb      *val = PG_GETARG_JSONB_P(1);
136
137         JsonbIterator *it1,
138                            *it2;
139
140         if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
141                 PG_RETURN_BOOL(false);
142
143         it1 = JsonbIteratorInit(&val->root);
144         it2 = JsonbIteratorInit(&tmpl->root);
145
146         PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
147 }
148
149 Datum
150 jsonb_ne(PG_FUNCTION_ARGS)
151 {
152         Jsonb      *jba = PG_GETARG_JSONB_P(0);
153         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
154         bool            res;
155
156         res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
157
158         PG_FREE_IF_COPY(jba, 0);
159         PG_FREE_IF_COPY(jbb, 1);
160         PG_RETURN_BOOL(res);
161 }
162
163 /*
164  * B-Tree operator class operators, support function
165  */
166 Datum
167 jsonb_lt(PG_FUNCTION_ARGS)
168 {
169         Jsonb      *jba = PG_GETARG_JSONB_P(0);
170         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
171         bool            res;
172
173         res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
174
175         PG_FREE_IF_COPY(jba, 0);
176         PG_FREE_IF_COPY(jbb, 1);
177         PG_RETURN_BOOL(res);
178 }
179
180 Datum
181 jsonb_gt(PG_FUNCTION_ARGS)
182 {
183         Jsonb      *jba = PG_GETARG_JSONB_P(0);
184         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
185         bool            res;
186
187         res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
188
189         PG_FREE_IF_COPY(jba, 0);
190         PG_FREE_IF_COPY(jbb, 1);
191         PG_RETURN_BOOL(res);
192 }
193
194 Datum
195 jsonb_le(PG_FUNCTION_ARGS)
196 {
197         Jsonb      *jba = PG_GETARG_JSONB_P(0);
198         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
199         bool            res;
200
201         res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
202
203         PG_FREE_IF_COPY(jba, 0);
204         PG_FREE_IF_COPY(jbb, 1);
205         PG_RETURN_BOOL(res);
206 }
207
208 Datum
209 jsonb_ge(PG_FUNCTION_ARGS)
210 {
211         Jsonb      *jba = PG_GETARG_JSONB_P(0);
212         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
213         bool            res;
214
215         res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
216
217         PG_FREE_IF_COPY(jba, 0);
218         PG_FREE_IF_COPY(jbb, 1);
219         PG_RETURN_BOOL(res);
220 }
221
222 Datum
223 jsonb_eq(PG_FUNCTION_ARGS)
224 {
225         Jsonb      *jba = PG_GETARG_JSONB_P(0);
226         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
227         bool            res;
228
229         res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
230
231         PG_FREE_IF_COPY(jba, 0);
232         PG_FREE_IF_COPY(jbb, 1);
233         PG_RETURN_BOOL(res);
234 }
235
236 Datum
237 jsonb_cmp(PG_FUNCTION_ARGS)
238 {
239         Jsonb      *jba = PG_GETARG_JSONB_P(0);
240         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
241         int                     res;
242
243         res = compareJsonbContainers(&jba->root, &jbb->root);
244
245         PG_FREE_IF_COPY(jba, 0);
246         PG_FREE_IF_COPY(jbb, 1);
247         PG_RETURN_INT32(res);
248 }
249
250 /*
251  * Hash operator class jsonb hashing function
252  */
253 Datum
254 jsonb_hash(PG_FUNCTION_ARGS)
255 {
256         Jsonb      *jb = PG_GETARG_JSONB_P(0);
257         JsonbIterator *it;
258         JsonbValue      v;
259         JsonbIteratorToken r;
260         uint32          hash = 0;
261
262         if (JB_ROOT_COUNT(jb) == 0)
263                 PG_RETURN_INT32(0);
264
265         it = JsonbIteratorInit(&jb->root);
266
267         while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
268         {
269                 switch (r)
270                 {
271                                 /* Rotation is left to JsonbHashScalarValue() */
272                         case WJB_BEGIN_ARRAY:
273                                 hash ^= JB_FARRAY;
274                                 break;
275                         case WJB_BEGIN_OBJECT:
276                                 hash ^= JB_FOBJECT;
277                                 break;
278                         case WJB_KEY:
279                         case WJB_VALUE:
280                         case WJB_ELEM:
281                                 JsonbHashScalarValue(&v, &hash);
282                                 break;
283                         case WJB_END_ARRAY:
284                         case WJB_END_OBJECT:
285                                 break;
286                         default:
287                                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
288                 }
289         }
290
291         PG_FREE_IF_COPY(jb, 0);
292         PG_RETURN_INT32(hash);
293 }
294
295 Datum
296 jsonb_hash_extended(PG_FUNCTION_ARGS)
297 {
298         Jsonb      *jb = PG_GETARG_JSONB_P(0);
299         uint64          seed = PG_GETARG_INT64(1);
300         JsonbIterator *it;
301         JsonbValue      v;
302         JsonbIteratorToken r;
303         uint64          hash = 0;
304
305         if (JB_ROOT_COUNT(jb) == 0)
306                 PG_RETURN_UINT64(seed);
307
308         it = JsonbIteratorInit(&jb->root);
309
310         while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
311         {
312                 switch (r)
313                 {
314                                 /* Rotation is left to JsonbHashScalarValueExtended() */
315                         case WJB_BEGIN_ARRAY:
316                                 hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
317                                 break;
318                         case WJB_BEGIN_OBJECT:
319                                 hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
320                                 break;
321                         case WJB_KEY:
322                         case WJB_VALUE:
323                         case WJB_ELEM:
324                                 JsonbHashScalarValueExtended(&v, &hash, seed);
325                                 break;
326                         case WJB_END_ARRAY:
327                         case WJB_END_OBJECT:
328                                 break;
329                         default:
330                                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
331                 }
332         }
333
334         PG_FREE_IF_COPY(jb, 0);
335         PG_RETURN_UINT64(hash);
336 }