PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
jsonb_gin.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * jsonb_gin.c
4  * GIN support functions for jsonb
5  *
6  * Copyright (c) 2014-2016, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/jsonb_gin.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "access/gin.h"
17 #include "access/hash.h"
18 #include "access/stratnum.h"
19 #include "catalog/pg_collation.h"
20 #include "catalog/pg_type.h"
21 #include "utils/builtins.h"
22 #include "utils/jsonb.h"
23 
24 typedef struct PathHashStack
25 {
29 
30 static Datum make_text_key(char flag, const char *str, int len);
31 static Datum make_scalar_key(const JsonbValue *scalarVal, bool is_key);
32 
33 /*
34  *
35  * jsonb_ops GIN opclass support functions
36  *
37  */
38 
39 Datum
41 {
42  text *arg1 = PG_GETARG_TEXT_PP(0);
43  text *arg2 = PG_GETARG_TEXT_PP(1);
44  int32 result;
45  char *a1p,
46  *a2p;
47  int len1,
48  len2;
49 
50  a1p = VARDATA_ANY(arg1);
51  a2p = VARDATA_ANY(arg2);
52 
53  len1 = VARSIZE_ANY_EXHDR(arg1);
54  len2 = VARSIZE_ANY_EXHDR(arg2);
55 
56  /* Compare text as bttextcmp does, but always using C collation */
57  result = varstr_cmp(a1p, len1, a2p, len2, C_COLLATION_OID);
58 
59  PG_FREE_IF_COPY(arg1, 0);
60  PG_FREE_IF_COPY(arg2, 1);
61 
62  PG_RETURN_INT32(result);
63 }
64 
65 Datum
67 {
68  Jsonb *jb = (Jsonb *) PG_GETARG_JSONB(0);
69  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
70  int total = 2 * JB_ROOT_COUNT(jb);
71  JsonbIterator *it;
72  JsonbValue v;
74  int i = 0;
75  Datum *entries;
76 
77  /* If the root level is empty, we certainly have no keys */
78  if (total == 0)
79  {
80  *nentries = 0;
82  }
83 
84  /* Otherwise, use 2 * root count as initial estimate of result size */
85  entries = (Datum *) palloc(sizeof(Datum) * total);
86 
87  it = JsonbIteratorInit(&jb->root);
88 
89  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
90  {
91  /* Since we recurse into the object, we might need more space */
92  if (i >= total)
93  {
94  total *= 2;
95  entries = (Datum *) repalloc(entries, sizeof(Datum) * total);
96  }
97 
98  switch (r)
99  {
100  case WJB_KEY:
101  entries[i++] = make_scalar_key(&v, true);
102  break;
103  case WJB_ELEM:
104  /* Pretend string array elements are keys, see jsonb.h */
105  entries[i++] = make_scalar_key(&v, (v.type == jbvString));
106  break;
107  case WJB_VALUE:
108  entries[i++] = make_scalar_key(&v, false);
109  break;
110  default:
111  /* we can ignore structural items */
112  break;
113  }
114  }
115 
116  *nentries = i;
117 
118  PG_RETURN_POINTER(entries);
119 }
120 
121 Datum
123 {
124  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
125  StrategyNumber strategy = PG_GETARG_UINT16(2);
126  int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
127  Datum *entries;
128 
129  if (strategy == JsonbContainsStrategyNumber)
130  {
131  /* Query is a jsonb, so just apply gin_extract_jsonb... */
132  entries = (Datum *)
134  PG_GETARG_DATUM(0),
135  PointerGetDatum(nentries)));
136  /* ...although "contains {}" requires a full index scan */
137  if (*nentries == 0)
138  *searchMode = GIN_SEARCH_MODE_ALL;
139  }
140  else if (strategy == JsonbExistsStrategyNumber)
141  {
142  /* Query is a text string, which we treat as a key */
143  text *query = PG_GETARG_TEXT_PP(0);
144 
145  *nentries = 1;
146  entries = (Datum *) palloc(sizeof(Datum));
147  entries[0] = make_text_key(JGINFLAG_KEY,
148  VARDATA_ANY(query),
149  VARSIZE_ANY_EXHDR(query));
150  }
151  else if (strategy == JsonbExistsAnyStrategyNumber ||
152  strategy == JsonbExistsAllStrategyNumber)
153  {
154  /* Query is a text array; each element is treated as a key */
155  ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
156  Datum *key_datums;
157  bool *key_nulls;
158  int key_count;
159  int i,
160  j;
161 
162  deconstruct_array(query,
163  TEXTOID, -1, false, 'i',
164  &key_datums, &key_nulls, &key_count);
165 
166  entries = (Datum *) palloc(sizeof(Datum) * key_count);
167 
168  for (i = 0, j = 0; i < key_count; i++)
169  {
170  /* Nulls in the array are ignored */
171  if (key_nulls[i])
172  continue;
173  entries[j++] = make_text_key(JGINFLAG_KEY,
174  VARDATA_ANY(key_datums[i]),
175  VARSIZE_ANY_EXHDR(key_datums[i]));
176  }
177 
178  *nentries = j;
179  /* ExistsAll with no keys should match everything */
180  if (j == 0 && strategy == JsonbExistsAllStrategyNumber)
181  *searchMode = GIN_SEARCH_MODE_ALL;
182  }
183  else
184  {
185  elog(ERROR, "unrecognized strategy number: %d", strategy);
186  entries = NULL; /* keep compiler quiet */
187  }
188 
189  PG_RETURN_POINTER(entries);
190 }
191 
192 Datum
194 {
195  bool *check = (bool *) PG_GETARG_POINTER(0);
196  StrategyNumber strategy = PG_GETARG_UINT16(1);
197 
198  /* Jsonb *query = PG_GETARG_JSONB(2); */
199  int32 nkeys = PG_GETARG_INT32(3);
200 
201  /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
202  bool *recheck = (bool *) PG_GETARG_POINTER(5);
203  bool res = true;
204  int32 i;
205 
206  if (strategy == JsonbContainsStrategyNumber)
207  {
208  /*
209  * We must always recheck, since we can't tell from the index whether
210  * the positions of the matched items match the structure of the query
211  * object. (Even if we could, we'd also have to worry about hashed
212  * keys and the index's failure to distinguish keys from string array
213  * elements.) However, the tuple certainly doesn't match unless it
214  * contains all the query keys.
215  */
216  *recheck = true;
217  for (i = 0; i < nkeys; i++)
218  {
219  if (!check[i])
220  {
221  res = false;
222  break;
223  }
224  }
225  }
226  else if (strategy == JsonbExistsStrategyNumber)
227  {
228  /*
229  * Although the key is certainly present in the index, we must recheck
230  * because (1) the key might be hashed, and (2) the index match might
231  * be for a key that's not at top level of the JSON object. For (1),
232  * we could look at the query key to see if it's hashed and not
233  * recheck if not, but the index lacks enough info to tell about (2).
234  */
235  *recheck = true;
236  res = true;
237  }
238  else if (strategy == JsonbExistsAnyStrategyNumber)
239  {
240  /* As for plain exists, we must recheck */
241  *recheck = true;
242  res = true;
243  }
244  else if (strategy == JsonbExistsAllStrategyNumber)
245  {
246  /* As for plain exists, we must recheck */
247  *recheck = true;
248  /* ... but unless all the keys are present, we can say "false" */
249  for (i = 0; i < nkeys; i++)
250  {
251  if (!check[i])
252  {
253  res = false;
254  break;
255  }
256  }
257  }
258  else
259  elog(ERROR, "unrecognized strategy number: %d", strategy);
260 
261  PG_RETURN_BOOL(res);
262 }
263 
264 Datum
266 {
268  StrategyNumber strategy = PG_GETARG_UINT16(1);
269 
270  /* Jsonb *query = PG_GETARG_JSONB(2); */
271  int32 nkeys = PG_GETARG_INT32(3);
272 
273  /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
275  int32 i;
276 
277  /*
278  * Note that we never return GIN_TRUE, only GIN_MAYBE or GIN_FALSE; this
279  * corresponds to always forcing recheck in the regular consistent
280  * function, for the reasons listed there.
281  */
282  if (strategy == JsonbContainsStrategyNumber ||
283  strategy == JsonbExistsAllStrategyNumber)
284  {
285  /* All extracted keys must be present */
286  for (i = 0; i < nkeys; i++)
287  {
288  if (check[i] == GIN_FALSE)
289  {
290  res = GIN_FALSE;
291  break;
292  }
293  }
294  }
295  else if (strategy == JsonbExistsStrategyNumber ||
296  strategy == JsonbExistsAnyStrategyNumber)
297  {
298  /* At least one extracted key must be present */
299  res = GIN_FALSE;
300  for (i = 0; i < nkeys; i++)
301  {
302  if (check[i] == GIN_TRUE ||
303  check[i] == GIN_MAYBE)
304  {
305  res = GIN_MAYBE;
306  break;
307  }
308  }
309  }
310  else
311  elog(ERROR, "unrecognized strategy number: %d", strategy);
312 
314 }
315 
316 /*
317  *
318  * jsonb_path_ops GIN opclass support functions
319  *
320  * In a jsonb_path_ops index, the GIN keys are uint32 hashes, one per JSON
321  * value; but the JSON key(s) leading to each value are also included in its
322  * hash computation. This means we can only support containment queries,
323  * but the index can distinguish, for example, {"foo": 42} from {"bar": 42}
324  * since different hashes will be generated.
325  *
326  */
327 
328 Datum
330 {
331  Jsonb *jb = PG_GETARG_JSONB(0);
332  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
333  int total = 2 * JB_ROOT_COUNT(jb);
334  JsonbIterator *it;
335  JsonbValue v;
337  PathHashStack tail;
338  PathHashStack *stack;
339  int i = 0;
340  Datum *entries;
341 
342  /* If the root level is empty, we certainly have no keys */
343  if (total == 0)
344  {
345  *nentries = 0;
347  }
348 
349  /* Otherwise, use 2 * root count as initial estimate of result size */
350  entries = (Datum *) palloc(sizeof(Datum) * total);
351 
352  /* We keep a stack of partial hashes corresponding to parent key levels */
353  tail.parent = NULL;
354  tail.hash = 0;
355  stack = &tail;
356 
357  it = JsonbIteratorInit(&jb->root);
358 
359  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
360  {
362 
363  /* Since we recurse into the object, we might need more space */
364  if (i >= total)
365  {
366  total *= 2;
367  entries = (Datum *) repalloc(entries, sizeof(Datum) * total);
368  }
369 
370  switch (r)
371  {
372  case WJB_BEGIN_ARRAY:
373  case WJB_BEGIN_OBJECT:
374  /* Push a stack level for this object */
375  parent = stack;
376  stack = (PathHashStack *) palloc(sizeof(PathHashStack));
377 
378  /*
379  * We pass forward hashes from outer nesting levels so that
380  * the hashes for nested values will include outer keys as
381  * well as their own keys.
382  *
383  * Nesting an array within another array will not alter
384  * innermost scalar element hash values, but that seems
385  * inconsequential.
386  */
387  stack->hash = parent->hash;
388  stack->parent = parent;
389  break;
390  case WJB_KEY:
391  /* mix this key into the current outer hash */
392  JsonbHashScalarValue(&v, &stack->hash);
393  /* hash is now ready to incorporate the value */
394  break;
395  case WJB_ELEM:
396  case WJB_VALUE:
397  /* mix the element or value's hash into the prepared hash */
398  JsonbHashScalarValue(&v, &stack->hash);
399  /* and emit an index entry */
400  entries[i++] = UInt32GetDatum(stack->hash);
401  /* reset hash for next key, value, or sub-object */
402  stack->hash = stack->parent->hash;
403  break;
404  case WJB_END_ARRAY:
405  case WJB_END_OBJECT:
406  /* Pop the stack */
407  parent = stack->parent;
408  pfree(stack);
409  stack = parent;
410  /* reset hash for next key, value, or sub-object */
411  if (stack->parent)
412  stack->hash = stack->parent->hash;
413  else
414  stack->hash = 0;
415  break;
416  default:
417  elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
418  }
419  }
420 
421  *nentries = i;
422 
423  PG_RETURN_POINTER(entries);
424 }
425 
426 Datum
428 {
429  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
430  StrategyNumber strategy = PG_GETARG_UINT16(2);
431  int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
432  Datum *entries;
433 
434  if (strategy != JsonbContainsStrategyNumber)
435  elog(ERROR, "unrecognized strategy number: %d", strategy);
436 
437  /* Query is a jsonb, so just apply gin_extract_jsonb_path ... */
438  entries = (Datum *)
440  PG_GETARG_DATUM(0),
441  PointerGetDatum(nentries)));
442 
443  /* ... although "contains {}" requires a full index scan */
444  if (*nentries == 0)
445  *searchMode = GIN_SEARCH_MODE_ALL;
446 
447  PG_RETURN_POINTER(entries);
448 }
449 
450 Datum
452 {
453  bool *check = (bool *) PG_GETARG_POINTER(0);
454  StrategyNumber strategy = PG_GETARG_UINT16(1);
455 
456  /* Jsonb *query = PG_GETARG_JSONB(2); */
457  int32 nkeys = PG_GETARG_INT32(3);
458 
459  /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
460  bool *recheck = (bool *) PG_GETARG_POINTER(5);
461  bool res = true;
462  int32 i;
463 
464  if (strategy != JsonbContainsStrategyNumber)
465  elog(ERROR, "unrecognized strategy number: %d", strategy);
466 
467  /*
468  * jsonb_path_ops is necessarily lossy, not only because of hash
469  * collisions but also because it doesn't preserve complete information
470  * about the structure of the JSON object. Besides, there are some
471  * special rules around the containment of raw scalars in arrays that are
472  * not handled here. So we must always recheck a match. However, if not
473  * all of the keys are present, the tuple certainly doesn't match.
474  */
475  *recheck = true;
476  for (i = 0; i < nkeys; i++)
477  {
478  if (!check[i])
479  {
480  res = false;
481  break;
482  }
483  }
484 
485  PG_RETURN_BOOL(res);
486 }
487 
488 Datum
490 {
492  StrategyNumber strategy = PG_GETARG_UINT16(1);
493 
494  /* Jsonb *query = PG_GETARG_JSONB(2); */
495  int32 nkeys = PG_GETARG_INT32(3);
496 
497  /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
499  int32 i;
500 
501  if (strategy != JsonbContainsStrategyNumber)
502  elog(ERROR, "unrecognized strategy number: %d", strategy);
503 
504  /*
505  * Note that we never return GIN_TRUE, only GIN_MAYBE or GIN_FALSE; this
506  * corresponds to always forcing recheck in the regular consistent
507  * function, for the reasons listed there.
508  */
509  for (i = 0; i < nkeys; i++)
510  {
511  if (check[i] == GIN_FALSE)
512  {
513  res = GIN_FALSE;
514  break;
515  }
516  }
517 
519 }
520 
521 /*
522  * Construct a jsonb_ops GIN key from a flag byte and a textual representation
523  * (which need not be null-terminated). This function is responsible
524  * for hashing overlength text representations; it will add the
525  * JGINFLAG_HASHED bit to the flag value if it does that.
526  */
527 static Datum
528 make_text_key(char flag, const char *str, int len)
529 {
530  text *item;
531  char hashbuf[10];
532 
533  if (len > JGIN_MAXLENGTH)
534  {
535  uint32 hashval;
536 
537  hashval = DatumGetUInt32(hash_any((const unsigned char *) str, len));
538  snprintf(hashbuf, sizeof(hashbuf), "%08x", hashval);
539  str = hashbuf;
540  len = 8;
541  flag |= JGINFLAG_HASHED;
542  }
543 
544  /*
545  * Now build the text Datum. For simplicity we build a 4-byte-header
546  * varlena text Datum here, but we expect it will get converted to short
547  * header format when stored in the index.
548  */
549  item = (text *) palloc(VARHDRSZ + len + 1);
550  SET_VARSIZE(item, VARHDRSZ + len + 1);
551 
552  *VARDATA(item) = flag;
553 
554  memcpy(VARDATA(item) + 1, str, len);
555 
556  return PointerGetDatum(item);
557 }
558 
559 /*
560  * Create a textual representation of a JsonbValue that will serve as a GIN
561  * key in a jsonb_ops index. is_key is true if the JsonbValue is a key,
562  * or if it is a string array element (since we pretend those are keys,
563  * see jsonb.h).
564  */
565 static Datum
566 make_scalar_key(const JsonbValue *scalarVal, bool is_key)
567 {
568  Datum item;
569  char *cstr;
570 
571  switch (scalarVal->type)
572  {
573  case jbvNull:
574  Assert(!is_key);
575  item = make_text_key(JGINFLAG_NULL, "", 0);
576  break;
577  case jbvBool:
578  Assert(!is_key);
580  scalarVal->val.boolean ? "t" : "f", 1);
581  break;
582  case jbvNumeric:
583  Assert(!is_key);
584 
585  /*
586  * A normalized textual representation, free of trailing zeroes,
587  * is required so that numerically equal values will produce equal
588  * strings.
589  *
590  * It isn't ideal that numerics are stored in a relatively bulky
591  * textual format. However, it's a notationally convenient way of
592  * storing a "union" type in the GIN B-Tree, and indexing Jsonb
593  * strings takes precedence.
594  */
595  cstr = numeric_normalize(scalarVal->val.numeric);
596  item = make_text_key(JGINFLAG_NUM, cstr, strlen(cstr));
597  pfree(cstr);
598  break;
599  case jbvString:
600  item = make_text_key(is_key ? JGINFLAG_KEY : JGINFLAG_STR,
601  scalarVal->val.string.val,
602  scalarVal->val.string.len);
603  break;
604  default:
605  elog(ERROR, "unrecognized jsonb scalar type: %d", scalarVal->type);
606  item = 0; /* keep compiler quiet */
607  break;
608  }
609 
610  return item;
611 }
#define GIN_TRUE
Definition: gin.h:60
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define DatumGetUInt32(X)
Definition: postgres.h:494
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
struct PathHashStack * parent
Definition: jsonb_gin.c:27
#define JGINFLAG_HASHED
Definition: jsonb.h:64
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
#define VARDATA(PTR)
Definition: postgres.h:305
Definition: jsonb.h:209
char * numeric_normalize(Numeric num)
Definition: numeric.c:694
Datum gin_consistent_jsonb_path(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:451
#define GIN_MAYBE
Definition: gin.h:61
#define TEXTOID
Definition: pg_type.h:324
#define PointerGetDatum(X)
Definition: postgres.h:564
Datum gin_extract_jsonb_path(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:329
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define VARHDRSZ
Definition: c.h:429
char * val
Definition: jsonb.h:251
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define JGINFLAG_KEY
Definition: jsonb.h:59
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:216
uint16 StrategyNumber
Definition: stratnum.h:22
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define JsonbExistsAnyStrategyNumber
Definition: jsonb.h:35
Datum gin_compare_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:40
#define JsonbExistsAllStrategyNumber
Definition: jsonb.h:36
signed int int32
Definition: c.h:242
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
#define PG_RETURN_GIN_TERNARY_VALUE(x)
Definition: gin.h:66
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1213
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:35
void pfree(void *pointer)
Definition: mcxt.c:995
#define ERROR
Definition: elog.h:41
char GinTernaryValue
Definition: gin.h:57
#define JGIN_MAXLENGTH
Definition: jsonb.h:65
Datum gin_extract_jsonb_query_path(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:427
Datum gin_triconsistent_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:265
char * flag(int b)
Definition: test-ctype.c:33
unsigned int uint32
Definition: c.h:254
#define UInt32GetDatum(X)
Definition: postgres.h:501
Definition: jsonb.h:23
Datum gin_extract_jsonb_query(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:212
uint32 hash
Definition: jsonb_gin.c:26
#define JGINFLAG_NULL
Definition: jsonb.h:60
static Datum make_scalar_key(const JsonbValue *scalarVal, bool is_key)
Definition: jsonb_gin.c:566
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
uintptr_t Datum
Definition: postgres.h:374
enum JsonbValue::@67 type
struct PathHashStack PathHashStack
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:717
Datum hash_any(register const unsigned char *k, register int keylen)
Definition: hashfunc.c:308
#define JsonbExistsStrategyNumber
Definition: jsonb.h:34
int varstr_cmp(char *arg1, int len1, char *arg2, int len2, Oid collid)
Definition: varlena.c:1383
#define GIN_FALSE
Definition: gin.h:59
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
#define JGINFLAG_STR
Definition: jsonb.h:63
Datum gin_triconsistent_jsonb_path(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:489
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define C_COLLATION_OID
Definition: pg_collation.h:71
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1024
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
#define DatumGetPointer(X)
Definition: postgres.h:557
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
Datum gin_extract_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:66
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
void * palloc(Size size)
Definition: mcxt.c:894
#define JGINFLAG_NUM
Definition: jsonb.h:62
int i
Definition: c.h:423
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#define elog
Definition: elog.h:228
Datum gin_consistent_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:193
static Datum make_text_key(char flag, const char *str, int len)
Definition: jsonb_gin.c:528
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:550
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:753
Definition: jsonb.h:25
#define JGINFLAG_BOOL
Definition: jsonb.h:61