Coverage Report

Created: 2026-08-13 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/adt/jsonb_util.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * jsonb_util.c
4
 *    converting between Jsonb and JsonbValues, and iterating.
5
 *
6
 * Copyright (c) 2014-2026, PostgreSQL Global Development Group
7
 *
8
 *
9
 * IDENTIFICATION
10
 *    src/backend/utils/adt/jsonb_util.c
11
 *
12
 *-------------------------------------------------------------------------
13
 */
14
#include "postgres.h"
15
16
#include "catalog/pg_collation.h"
17
#include "catalog/pg_type.h"
18
#include "common/hashfn.h"
19
#include "miscadmin.h"
20
#include "port/pg_bitutils.h"
21
#include "utils/date.h"
22
#include "utils/datetime.h"
23
#include "utils/datum.h"
24
#include "utils/fmgrprotos.h"
25
#include "utils/json.h"
26
#include "utils/jsonb.h"
27
#include "utils/memutils.h"
28
#include "utils/varlena.h"
29
30
/*
31
 * Maximum number of elements in an array (or key/value pairs in an object).
32
 * This is limited by two things: the size of the JEntry array must fit
33
 * in MaxAllocSize, and the number of elements (or pairs) must fit in the bits
34
 * reserved for that in the JsonbContainer.header field.
35
 *
36
 * (The total size of an array's or object's elements is also limited by
37
 * JENTRY_OFFLENMASK, but we're not concerned about that here.)
38
 */
39
#define JSONB_MAX_ELEMS (Min(MaxAllocSize / sizeof(JsonbValue), JB_CMASK))
40
#define JSONB_MAX_PAIRS (Min(MaxAllocSize / sizeof(JsonbPair), JB_CMASK))
41
42
static void fillJsonbValue(JsonbContainer *container, int index,
43
               char *base_addr, uint32 offset,
44
               JsonbValue *result);
45
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b);
46
static int  compareJsonbScalarValue(JsonbValue *a, JsonbValue *b);
47
static Jsonb *convertToJsonb(JsonbValue *val);
48
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
49
static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
50
static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
51
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal);
52
53
static int  reserveFromBuffer(StringInfo buffer, int len);
54
static void appendToBuffer(StringInfo buffer, const void *data, int len);
55
static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len);
56
static short padBufferToInt(StringInfo buffer);
57
58
static JsonbIterator *iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent);
59
static JsonbIterator *freeAndGetParent(JsonbIterator *it);
60
static JsonbParseState *pushState(JsonbInState *pstate);
61
static void appendKey(JsonbInState *pstate, JsonbValue *string, bool needCopy);
62
static void appendValue(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy);
63
static void appendElement(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy);
64
static void copyScalarSubstructure(JsonbValue *v, MemoryContext outcontext);
65
static int  lengthCompareJsonbStringValue(const void *a, const void *b);
66
static int  lengthCompareJsonbString(const char *val1, int len1,
67
                   const char *val2, int len2);
68
static int  lengthCompareJsonbPair(const void *a, const void *b, void *binequal);
69
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys,
70
                 bool skip_nulls);
71
static void pushJsonbValueScalar(JsonbInState *pstate,
72
                 JsonbIteratorToken seq,
73
                 JsonbValue *scalarVal);
74
75
void
76
JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
77
0
{
78
0
  val->type = jbvBinary;
79
0
  val->val.binary.data = &jsonb->root;
80
0
  val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
81
0
}
82
83
/*
84
 * Turn an in-memory JsonbValue into a Jsonb for on-disk storage.
85
 *
86
 * Generally we find it more convenient to directly iterate through the Jsonb
87
 * representation and only really convert nested scalar values.
88
 * JsonbIteratorNext() does this, so that clients of the iteration code don't
89
 * have to directly deal with the binary representation (JsonbDeepContains() is
90
 * a notable exception, although all exceptions are internal to this module).
91
 * In general, functions that accept a JsonbValue argument are concerned with
92
 * the manipulation of scalar values, or simple containers of scalar values,
93
 * where it would be inconvenient to deal with a great amount of other state.
94
 */
95
Jsonb *
96
JsonbValueToJsonb(JsonbValue *val)
97
0
{
98
0
  Jsonb    *out;
99
100
0
  if (IsAJsonbScalar(val))
101
0
  {
102
    /* Scalar value, so wrap it in an array */
103
0
    JsonbInState pstate = {0};
104
0
    JsonbValue  scalarArray;
105
106
0
    scalarArray.type = jbvArray;
107
0
    scalarArray.val.array.rawScalar = true;
108
0
    scalarArray.val.array.nElems = 1;
109
110
0
    pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
111
0
    pushJsonbValue(&pstate, WJB_ELEM, val);
112
0
    pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
113
114
0
    out = convertToJsonb(pstate.result);
115
0
  }
116
0
  else if (val->type == jbvObject || val->type == jbvArray)
117
0
  {
118
0
    out = convertToJsonb(val);
119
0
  }
120
0
  else
121
0
  {
122
0
    Assert(val->type == jbvBinary);
123
0
    out = palloc(VARHDRSZ + val->val.binary.len);
124
0
    SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
125
0
    memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
126
0
  }
127
128
0
  return out;
129
0
}
130
131
/*
132
 * Get the offset of the variable-length portion of a Jsonb node within
133
 * the variable-length-data part of its container.  The node is identified
134
 * by index within the container's JEntry array.
135
 */
136
uint32
137
getJsonbOffset(const JsonbContainer *jc, int index)
138
0
{
139
0
  uint32    offset = 0;
140
0
  int     i;
141
142
  /*
143
   * Start offset of this entry is equal to the end offset of the previous
144
   * entry.  Walk backwards to the most recent entry stored as an end
145
   * offset, returning that offset plus any lengths in between.
146
   */
147
0
  for (i = index - 1; i >= 0; i--)
148
0
  {
149
0
    offset += JBE_OFFLENFLD(jc->children[i]);
150
0
    if (JBE_HAS_OFF(jc->children[i]))
151
0
      break;
152
0
  }
153
154
0
  return offset;
155
0
}
156
157
/*
158
 * Get the length of the variable-length portion of a Jsonb node.
159
 * The node is identified by index within the container's JEntry array.
160
 */
161
uint32
162
getJsonbLength(const JsonbContainer *jc, int index)
163
0
{
164
0
  uint32    off;
165
0
  uint32    len;
166
167
  /*
168
   * If the length is stored directly in the JEntry, just return it.
169
   * Otherwise, get the begin offset of the entry, and subtract that from
170
   * the stored end+1 offset.
171
   */
172
0
  if (JBE_HAS_OFF(jc->children[index]))
173
0
  {
174
0
    off = getJsonbOffset(jc, index);
175
0
    len = JBE_OFFLENFLD(jc->children[index]) - off;
176
0
  }
177
0
  else
178
0
    len = JBE_OFFLENFLD(jc->children[index]);
179
180
0
  return len;
181
0
}
182
183
/*
184
 * BT comparator worker function.  Returns an integer less than, equal to, or
185
 * greater than zero, indicating whether a is less than, equal to, or greater
186
 * than b.  Consistent with the requirements for a B-Tree operator class
187
 *
188
 * Strings are compared lexically, in contrast with other places where we use a
189
 * much simpler comparator logic for searching through Strings.  Since this is
190
 * called from B-Tree support function 1, we're careful about not leaking
191
 * memory here.
192
 */
193
int
194
compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
195
0
{
196
0
  JsonbIterator *ita,
197
0
         *itb;
198
0
  int     res = 0;
199
200
0
  ita = JsonbIteratorInit(a);
201
0
  itb = JsonbIteratorInit(b);
202
203
0
  do
204
0
  {
205
0
    JsonbValue  va,
206
0
          vb;
207
0
    JsonbIteratorToken ra,
208
0
          rb;
209
210
0
    ra = JsonbIteratorNext(&ita, &va, false);
211
0
    rb = JsonbIteratorNext(&itb, &vb, false);
212
213
0
    if (ra == rb)
214
0
    {
215
0
      if (ra == WJB_DONE)
216
0
      {
217
        /* Decisively equal */
218
0
        break;
219
0
      }
220
221
0
      if (ra == WJB_END_ARRAY || ra == WJB_END_OBJECT)
222
0
      {
223
        /*
224
         * There is no array or object to compare at this stage of
225
         * processing.  jbvArray/jbvObject values are compared
226
         * initially, at the WJB_BEGIN_ARRAY and WJB_BEGIN_OBJECT
227
         * tokens.
228
         */
229
0
        continue;
230
0
      }
231
232
0
      if (va.type == vb.type)
233
0
      {
234
0
        switch (va.type)
235
0
        {
236
0
          case jbvString:
237
0
          case jbvNull:
238
0
          case jbvNumeric:
239
0
          case jbvBool:
240
0
            res = compareJsonbScalarValue(&va, &vb);
241
0
            break;
242
0
          case jbvArray:
243
244
            /*
245
             * This could be a "raw scalar" pseudo array.  That's
246
             * a special case here though, since we still want the
247
             * general type-based comparisons to apply, and as far
248
             * as we're concerned a pseudo array is just a scalar.
249
             */
250
0
            if (va.val.array.rawScalar != vb.val.array.rawScalar)
251
0
              res = (va.val.array.rawScalar) ? -1 : 1;
252
253
            /*
254
             * There should be an "else" here, to prevent us from
255
             * overriding the above, but we can't change the sort
256
             * order now, so there is a mild anomaly that an empty
257
             * top level array sorts less than null.
258
             */
259
0
            if (va.val.array.nElems != vb.val.array.nElems)
260
0
              res = (va.val.array.nElems > vb.val.array.nElems) ? 1 : -1;
261
0
            break;
262
0
          case jbvObject:
263
0
            if (va.val.object.nPairs != vb.val.object.nPairs)
264
0
              res = (va.val.object.nPairs > vb.val.object.nPairs) ? 1 : -1;
265
0
            break;
266
0
          case jbvBinary:
267
0
            elog(ERROR, "unexpected jbvBinary value");
268
0
            break;
269
0
          case jbvDatetime:
270
0
            elog(ERROR, "unexpected jbvDatetime value");
271
0
            break;
272
0
        }
273
0
      }
274
0
      else
275
0
      {
276
        /* Type-defined order */
277
0
        res = (va.type > vb.type) ? 1 : -1;
278
0
      }
279
0
    }
280
0
    else
281
0
    {
282
      /*
283
       * It's not possible for one iterator to report end of array or
284
       * object while the other one reports something else, because we
285
       * would have detected a length mismatch when we processed the
286
       * container-start tokens above.  Likewise we can't see WJB_DONE
287
       * from one but not the other.  So we have two different-type
288
       * containers, or a container and some scalar type, or two
289
       * different scalar types.  Sort on the basis of the type code.
290
       */
291
0
      Assert(ra != WJB_DONE && ra != WJB_END_ARRAY && ra != WJB_END_OBJECT);
292
0
      Assert(rb != WJB_DONE && rb != WJB_END_ARRAY && rb != WJB_END_OBJECT);
293
294
0
      Assert(va.type != vb.type);
295
0
      Assert(va.type != jbvBinary);
296
0
      Assert(vb.type != jbvBinary);
297
      /* Type-defined order */
298
0
      res = (va.type > vb.type) ? 1 : -1;
299
0
    }
300
0
  }
301
0
  while (res == 0);
302
303
0
  while (ita != NULL)
304
0
  {
305
0
    JsonbIterator *i = ita->parent;
306
307
0
    pfree(ita);
308
0
    ita = i;
309
0
  }
310
0
  while (itb != NULL)
311
0
  {
312
0
    JsonbIterator *i = itb->parent;
313
314
0
    pfree(itb);
315
0
    itb = i;
316
0
  }
317
318
0
  return res;
319
0
}
320
321
/*
322
 * Find value in object (i.e. the "value" part of some key/value pair in an
323
 * object), or find a matching element if we're looking through an array.  Do
324
 * so on the basis of equality of the object keys only, or alternatively
325
 * element values only, with a caller-supplied value "key".  The "flags"
326
 * argument allows the caller to specify which container types are of interest.
327
 *
328
 * This exported utility function exists to facilitate various cases concerned
329
 * with "containment".  If asked to look through an object, the caller had
330
 * better pass a Jsonb String, because their keys can only be strings.
331
 * Otherwise, for an array, any type of JsonbValue will do.
332
 *
333
 * In order to proceed with the search, it is necessary for callers to have
334
 * both specified an interest in exactly one particular container type with an
335
 * appropriate flag, as well as having the pointed-to Jsonb container be of
336
 * one of those same container types at the top level. (Actually, we just do
337
 * whichever makes sense to save callers the trouble of figuring it out - at
338
 * most one can make sense, because the container either points to an array
339
 * (possibly a "raw scalar" pseudo array) or an object.)
340
 *
341
 * Note that we can return a jbvBinary JsonbValue if this is called on an
342
 * object, but we never do so on an array.  If the caller asks to look through
343
 * a container type that is not of the type pointed to by the container,
344
 * immediately fall through and return NULL.  If we cannot find the value,
345
 * return NULL.  Otherwise, return palloc()'d copy of value.
346
 */
347
JsonbValue *
348
findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
349
              JsonbValue *key)
350
0
{
351
0
  JEntry     *children = container->children;
352
0
  int     count = JsonContainerSize(container);
353
354
0
  Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
355
356
  /* Quick out without a palloc cycle if object/array is empty */
357
0
  if (count <= 0)
358
0
    return NULL;
359
360
0
  if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
361
0
  {
362
0
    JsonbValue *result = palloc_object(JsonbValue);
363
0
    char     *base_addr = (char *) (children + count);
364
0
    uint32    offset = 0;
365
0
    int     i;
366
367
0
    for (i = 0; i < count; i++)
368
0
    {
369
0
      fillJsonbValue(container, i, base_addr, offset, result);
370
371
0
      if (key->type == result->type)
372
0
      {
373
0
        if (equalsJsonbScalarValue(key, result))
374
0
          return result;
375
0
      }
376
377
0
      JBE_ADVANCE_OFFSET(offset, children[i]);
378
0
    }
379
380
0
    pfree(result);
381
0
  }
382
0
  else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
383
0
  {
384
    /* Object key passed by caller must be a string */
385
0
    Assert(key->type == jbvString);
386
387
0
    return getKeyJsonValueFromContainer(container, key->val.string.val,
388
0
                      key->val.string.len, NULL);
389
0
  }
390
391
  /* Not found */
392
0
  return NULL;
393
0
}
394
395
/*
396
 * Find value by key in Jsonb object and fetch it into 'res', which is also
397
 * returned.
398
 *
399
 * 'res' can be passed in as NULL, in which case it's newly palloc'ed here.
400
 */
401
JsonbValue *
402
getKeyJsonValueFromContainer(JsonbContainer *container,
403
               const char *keyVal, int keyLen, JsonbValue *res)
404
0
{
405
0
  JEntry     *children = container->children;
406
0
  int     count = JsonContainerSize(container);
407
0
  char     *baseAddr;
408
0
  uint32    stopLow,
409
0
        stopHigh;
410
411
0
  Assert(JsonContainerIsObject(container));
412
413
  /* Quick out without a palloc cycle if object is empty */
414
0
  if (count <= 0)
415
0
    return NULL;
416
417
  /*
418
   * Binary search the container. Since we know this is an object, account
419
   * for *Pairs* of Jentrys
420
   */
421
0
  baseAddr = (char *) (children + count * 2);
422
0
  stopLow = 0;
423
0
  stopHigh = count;
424
0
  while (stopLow < stopHigh)
425
0
  {
426
0
    uint32    stopMiddle;
427
0
    int     difference;
428
0
    const char *candidateVal;
429
0
    int     candidateLen;
430
431
0
    stopMiddle = stopLow + (stopHigh - stopLow) / 2;
432
433
0
    candidateVal = baseAddr + getJsonbOffset(container, stopMiddle);
434
0
    candidateLen = getJsonbLength(container, stopMiddle);
435
436
0
    difference = lengthCompareJsonbString(candidateVal, candidateLen,
437
0
                        keyVal, keyLen);
438
439
0
    if (difference == 0)
440
0
    {
441
      /* Found our key, return corresponding value */
442
0
      int     index = stopMiddle + count;
443
444
0
      if (!res)
445
0
        res = palloc_object(JsonbValue);
446
447
0
      fillJsonbValue(container, index, baseAddr,
448
0
               getJsonbOffset(container, index),
449
0
               res);
450
451
0
      return res;
452
0
    }
453
0
    else
454
0
    {
455
0
      if (difference < 0)
456
0
        stopLow = stopMiddle + 1;
457
0
      else
458
0
        stopHigh = stopMiddle;
459
0
    }
460
0
  }
461
462
  /* Not found */
463
0
  return NULL;
464
0
}
465
466
/*
467
 * Get i-th value of a Jsonb array.
468
 *
469
 * Returns palloc()'d copy of the value, or NULL if it does not exist.
470
 */
471
JsonbValue *
472
getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
473
0
{
474
0
  JsonbValue *result;
475
0
  char     *base_addr;
476
0
  uint32    nelements;
477
478
0
  if (!JsonContainerIsArray(container))
479
0
    elog(ERROR, "not a jsonb array");
480
481
0
  nelements = JsonContainerSize(container);
482
0
  base_addr = (char *) &container->children[nelements];
483
484
0
  if (i >= nelements)
485
0
    return NULL;
486
487
0
  result = palloc_object(JsonbValue);
488
489
0
  fillJsonbValue(container, i, base_addr,
490
0
           getJsonbOffset(container, i),
491
0
           result);
492
493
0
  return result;
494
0
}
495
496
/*
497
 * A helper function to fill in a JsonbValue to represent an element of an
498
 * array, or a key or value of an object.
499
 *
500
 * The node's JEntry is at container->children[index], and its variable-length
501
 * data is at base_addr + offset.  We make the caller determine the offset
502
 * since in many cases the caller can amortize that work across multiple
503
 * children.  When it can't, it can just call getJsonbOffset().
504
 *
505
 * A nested array or object will be returned as jbvBinary, ie. it won't be
506
 * expanded.
507
 */
508
static void
509
fillJsonbValue(JsonbContainer *container, int index,
510
         char *base_addr, uint32 offset,
511
         JsonbValue *result)
512
0
{
513
0
  JEntry    entry = container->children[index];
514
515
0
  if (JBE_ISNULL(entry))
516
0
  {
517
0
    result->type = jbvNull;
518
0
  }
519
0
  else if (JBE_ISSTRING(entry))
520
0
  {
521
0
    result->type = jbvString;
522
0
    result->val.string.val = base_addr + offset;
523
0
    result->val.string.len = getJsonbLength(container, index);
524
0
    Assert(result->val.string.len >= 0);
525
0
  }
526
0
  else if (JBE_ISNUMERIC(entry))
527
0
  {
528
0
    result->type = jbvNumeric;
529
0
    result->val.numeric = (Numeric) (base_addr + INTALIGN(offset));
530
0
  }
531
0
  else if (JBE_ISBOOL_TRUE(entry))
532
0
  {
533
0
    result->type = jbvBool;
534
0
    result->val.boolean = true;
535
0
  }
536
0
  else if (JBE_ISBOOL_FALSE(entry))
537
0
  {
538
0
    result->type = jbvBool;
539
0
    result->val.boolean = false;
540
0
  }
541
0
  else
542
0
  {
543
0
    Assert(JBE_ISCONTAINER(entry));
544
0
    result->type = jbvBinary;
545
    /* Remove alignment padding from data pointer and length */
546
0
    result->val.binary.data = (JsonbContainer *) (base_addr + INTALIGN(offset));
547
0
    result->val.binary.len = getJsonbLength(container, index) -
548
0
      (INTALIGN(offset) - offset);
549
0
  }
550
0
}
551
552
/*
553
 * Push JsonbValue into JsonbInState.
554
 *
555
 * Used, for example, when parsing JSON input.
556
 *
557
 * *pstate is typically initialized to all-zeroes, except that the caller
558
 * may provide outcontext and/or escontext.  (escontext is ignored by this
559
 * function and its subroutines, however.)
560
 *
561
 * "seq" tells what is being pushed (start/end of array or object, key,
562
 * value, etc).  WJB_DONE is not used here, but the other values of
563
 * JsonbIteratorToken are.  We assume the caller passes a valid sequence
564
 * of values.
565
 *
566
 * The passed "jbval" is typically transient storage, such as a local variable.
567
 * We will copy it into the outcontext (CurrentMemoryContext by default).
568
 * If outcontext isn't NULL, we will also make copies of any pass-by-reference
569
 * scalar values.
570
 *
571
 * Only sequential tokens pertaining to non-container types should pass a
572
 * JsonbValue.  There is one exception -- WJB_BEGIN_ARRAY callers may pass a
573
 * "raw scalar" pseudo array to append it - the actual scalar should be passed
574
 * next and it will be added as the only member of the array.
575
 *
576
 * Values of type jbvBinary, which are rolled up arrays and objects,
577
 * are unpacked before being added to the result.
578
 *
579
 * At the end of construction of a JsonbValue, pstate->result will reference
580
 * the top-level JsonbValue object.
581
 */
582
void
583
pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq,
584
         JsonbValue *jbval)
585
0
{
586
0
  JsonbIterator *it;
587
0
  JsonbValue  v;
588
0
  JsonbIteratorToken tok;
589
0
  int     i;
590
591
  /*
592
   * pushJsonbValueScalar handles all cases not involving pushing a
593
   * container object as an ELEM or VALUE.
594
   */
595
0
  if (!jbval || IsAJsonbScalar(jbval) ||
596
0
    (seq != WJB_ELEM && seq != WJB_VALUE))
597
0
  {
598
0
    pushJsonbValueScalar(pstate, seq, jbval);
599
0
    return;
600
0
  }
601
602
  /* If an object or array is pushed, recursively push its contents */
603
0
  if (jbval->type == jbvObject)
604
0
  {
605
0
    pushJsonbValue(pstate, WJB_BEGIN_OBJECT, NULL);
606
0
    for (i = 0; i < jbval->val.object.nPairs; i++)
607
0
    {
608
0
      pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
609
0
      pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
610
0
    }
611
0
    pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
612
0
    return;
613
0
  }
614
615
0
  if (jbval->type == jbvArray)
616
0
  {
617
0
    pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
618
0
    for (i = 0; i < jbval->val.array.nElems; i++)
619
0
    {
620
0
      pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
621
0
    }
622
0
    pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
623
0
    return;
624
0
  }
625
626
  /* Else it must be a jbvBinary value; push its contents */
627
0
  Assert(jbval->type == jbvBinary);
628
629
0
  it = JsonbIteratorInit(jbval->val.binary.data);
630
631
  /* ... with a special case for pushing a raw scalar */
632
0
  if ((jbval->val.binary.data->header & JB_FSCALAR) &&
633
0
    pstate->parseState != NULL)
634
0
  {
635
0
    tok = JsonbIteratorNext(&it, &v, true);
636
0
    Assert(tok == WJB_BEGIN_ARRAY);
637
0
    Assert(v.type == jbvArray && v.val.array.rawScalar);
638
639
0
    tok = JsonbIteratorNext(&it, &v, true);
640
0
    Assert(tok == WJB_ELEM);
641
642
0
    pushJsonbValueScalar(pstate, seq, &v);
643
644
0
    tok = JsonbIteratorNext(&it, &v, true);
645
0
    Assert(tok == WJB_END_ARRAY);
646
0
    Assert(it == NULL);
647
648
0
    return;
649
0
  }
650
651
0
  while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
652
0
    pushJsonbValueScalar(pstate, tok,
653
0
               tok < WJB_BEGIN_ARRAY ||
654
0
               (tok == WJB_BEGIN_ARRAY &&
655
0
                v.val.array.rawScalar) ? &v : NULL);
656
0
}
657
658
/*
659
 * Do the actual pushing, with only scalar or pseudo-scalar-array values
660
 * accepted.
661
 */
662
static void
663
pushJsonbValueScalar(JsonbInState *pstate, JsonbIteratorToken seq,
664
           JsonbValue *scalarVal)
665
0
{
666
0
  JsonbParseState *ppstate;
667
0
  JsonbValue *val;
668
0
  MemoryContext outcontext;
669
670
0
  switch (seq)
671
0
  {
672
0
    case WJB_BEGIN_ARRAY:
673
0
      Assert(!scalarVal || scalarVal->val.array.rawScalar);
674
0
      ppstate = pushState(pstate);
675
0
      val = &ppstate->contVal;
676
0
      val->type = jbvArray;
677
0
      val->val.array.nElems = 0;
678
0
      val->val.array.rawScalar = (scalarVal &&
679
0
                    scalarVal->val.array.rawScalar);
680
0
      if (scalarVal && scalarVal->val.array.nElems > 0)
681
0
      {
682
        /* Assume that this array is still really a scalar */
683
0
        Assert(scalarVal->type == jbvArray);
684
0
        ppstate->size = scalarVal->val.array.nElems;
685
0
      }
686
0
      else
687
0
      {
688
0
        ppstate->size = 4;  /* initial guess at array size */
689
0
      }
690
0
      outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
691
0
      val->val.array.elems = MemoryContextAlloc(outcontext,
692
0
                            sizeof(JsonbValue) *
693
0
                            ppstate->size);
694
0
      break;
695
0
    case WJB_BEGIN_OBJECT:
696
0
      Assert(!scalarVal);
697
0
      ppstate = pushState(pstate);
698
0
      val = &ppstate->contVal;
699
0
      val->type = jbvObject;
700
0
      val->val.object.nPairs = 0;
701
0
      ppstate->size = 4;  /* initial guess at object size */
702
0
      outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
703
0
      val->val.object.pairs = MemoryContextAlloc(outcontext,
704
0
                             sizeof(JsonbPair) *
705
0
                             ppstate->size);
706
0
      break;
707
0
    case WJB_KEY:
708
0
      Assert(scalarVal->type == jbvString);
709
0
      appendKey(pstate, scalarVal, true);
710
0
      break;
711
0
    case WJB_VALUE:
712
0
      Assert(IsAJsonbScalar(scalarVal));
713
0
      appendValue(pstate, scalarVal, true);
714
0
      break;
715
0
    case WJB_ELEM:
716
0
      Assert(IsAJsonbScalar(scalarVal));
717
0
      appendElement(pstate, scalarVal, true);
718
0
      break;
719
0
    case WJB_END_OBJECT:
720
0
      ppstate = pstate->parseState;
721
0
      uniqueifyJsonbObject(&ppstate->contVal,
722
0
                 ppstate->unique_keys,
723
0
                 ppstate->skip_nulls);
724
0
      pg_fallthrough;
725
0
    case WJB_END_ARRAY:
726
      /* Steps here common to WJB_END_OBJECT case */
727
0
      Assert(!scalarVal);
728
0
      ppstate = pstate->parseState;
729
0
      val = &ppstate->contVal;
730
731
      /*
732
       * Pop stack and push current array/object as value in parent
733
       * array/object, or return it as the final result.  We don't need
734
       * to re-copy any scalars that are in the data structure.
735
       */
736
0
      pstate->parseState = ppstate = ppstate->next;
737
0
      if (ppstate)
738
0
      {
739
0
        switch (ppstate->contVal.type)
740
0
        {
741
0
          case jbvArray:
742
0
            appendElement(pstate, val, false);
743
0
            break;
744
0
          case jbvObject:
745
0
            appendValue(pstate, val, false);
746
0
            break;
747
0
          default:
748
0
            elog(ERROR, "invalid jsonb container type");
749
0
        }
750
0
      }
751
0
      else
752
0
        pstate->result = val;
753
0
      break;
754
0
    default:
755
0
      elog(ERROR, "unrecognized jsonb sequential processing token");
756
0
  }
757
0
}
758
759
/*
760
 * Push a new JsonbParseState onto the JsonbInState's stack
761
 *
762
 * As a notational convenience, the new state's address is returned.
763
 * The caller must initialize the new state's contVal and size fields.
764
 */
765
static JsonbParseState *
766
pushState(JsonbInState *pstate)
767
0
{
768
0
  MemoryContext outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
769
0
  JsonbParseState *ns = MemoryContextAlloc(outcontext,
770
0
                       sizeof(JsonbParseState));
771
772
0
  ns->next = pstate->parseState;
773
  /* This module never changes these fields, but callers can: */
774
0
  ns->unique_keys = false;
775
0
  ns->skip_nulls = false;
776
777
0
  pstate->parseState = ns;
778
0
  return ns;
779
0
}
780
781
/*
782
 * pushJsonbValue() worker:  Append a pair key to pstate
783
 */
784
static void
785
appendKey(JsonbInState *pstate, JsonbValue *string, bool needCopy)
786
0
{
787
0
  JsonbParseState *ppstate = pstate->parseState;
788
0
  JsonbValue *object = &ppstate->contVal;
789
0
  JsonbPair  *pair;
790
791
0
  Assert(object->type == jbvObject);
792
0
  Assert(string->type == jbvString);
793
794
0
  if (object->val.object.nPairs >= ppstate->size)
795
0
  {
796
0
    if (unlikely(object->val.object.nPairs >= JSONB_MAX_PAIRS))
797
0
      ereport(ERROR,
798
0
          (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
799
0
           errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
800
0
              JSONB_MAX_PAIRS)));
801
0
    ppstate->size = Min(ppstate->size * 2, JSONB_MAX_PAIRS);
802
0
    object->val.object.pairs = repalloc(object->val.object.pairs,
803
0
                      sizeof(JsonbPair) * ppstate->size);
804
0
  }
805
806
0
  pair = &object->val.object.pairs[object->val.object.nPairs];
807
0
  pair->key = *string;
808
0
  pair->order = object->val.object.nPairs;
809
810
0
  if (needCopy)
811
0
    copyScalarSubstructure(&pair->key, pstate->outcontext);
812
0
}
813
814
/*
815
 * pushJsonbValue() worker:  Append a pair value to pstate
816
 */
817
static void
818
appendValue(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
819
0
{
820
0
  JsonbValue *object = &pstate->parseState->contVal;
821
0
  JsonbPair  *pair;
822
823
0
  Assert(object->type == jbvObject);
824
825
0
  pair = &object->val.object.pairs[object->val.object.nPairs];
826
0
  pair->value = *scalarVal;
827
0
  object->val.object.nPairs++;
828
829
0
  if (needCopy)
830
0
    copyScalarSubstructure(&pair->value, pstate->outcontext);
831
0
}
832
833
/*
834
 * pushJsonbValue() worker:  Append an array element to pstate
835
 */
836
static void
837
appendElement(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
838
0
{
839
0
  JsonbParseState *ppstate = pstate->parseState;
840
0
  JsonbValue *array = &ppstate->contVal;
841
0
  JsonbValue *elem;
842
843
0
  Assert(array->type == jbvArray);
844
845
0
  if (array->val.array.nElems >= ppstate->size)
846
0
  {
847
0
    if (unlikely(array->val.array.nElems >= JSONB_MAX_ELEMS))
848
0
      ereport(ERROR,
849
0
          (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
850
0
           errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
851
0
              JSONB_MAX_ELEMS)));
852
0
    ppstate->size = Min(ppstate->size * 2, JSONB_MAX_ELEMS);
853
0
    array->val.array.elems = repalloc(array->val.array.elems,
854
0
                      sizeof(JsonbValue) * ppstate->size);
855
0
  }
856
857
0
  elem = &array->val.array.elems[array->val.array.nElems];
858
0
  *elem = *scalarVal;
859
0
  array->val.array.nElems++;
860
861
0
  if (needCopy)
862
0
    copyScalarSubstructure(elem, pstate->outcontext);
863
0
}
864
865
/*
866
 * Copy any infrastructure of a scalar JsonbValue into the outcontext,
867
 * adjusting the pointer(s) in *v.
868
 *
869
 * We need not deal with containers here, as the routines above ensure
870
 * that they are built fresh.
871
 */
872
static void
873
copyScalarSubstructure(JsonbValue *v, MemoryContext outcontext)
874
0
{
875
0
  MemoryContext oldcontext;
876
877
  /* Nothing to do if caller did not specify an outcontext */
878
0
  if (outcontext == NULL)
879
0
    return;
880
0
  switch (v->type)
881
0
  {
882
0
    case jbvNull:
883
0
    case jbvBool:
884
      /* pass-by-value, nothing to do */
885
0
      break;
886
0
    case jbvString:
887
0
      {
888
0
        char     *buf = MemoryContextAlloc(outcontext,
889
0
                           v->val.string.len);
890
891
0
        memcpy(buf, v->val.string.val, v->val.string.len);
892
0
        v->val.string.val = buf;
893
0
      }
894
0
      break;
895
0
    case jbvNumeric:
896
0
      oldcontext = MemoryContextSwitchTo(outcontext);
897
0
      v->val.numeric =
898
0
        DatumGetNumeric(datumCopy(NumericGetDatum(v->val.numeric),
899
0
                      false, -1));
900
0
      MemoryContextSwitchTo(oldcontext);
901
0
      break;
902
0
    case jbvDatetime:
903
0
      switch (v->val.datetime.typid)
904
0
      {
905
0
        case DATEOID:
906
0
        case TIMEOID:
907
0
        case TIMESTAMPOID:
908
0
        case TIMESTAMPTZOID:
909
          /* pass-by-value, nothing to do */
910
0
          break;
911
0
        case TIMETZOID:
912
          /* pass-by-reference */
913
0
          oldcontext = MemoryContextSwitchTo(outcontext);
914
0
          v->val.datetime.value = datumCopy(v->val.datetime.value,
915
0
                            false, TIMETZ_TYPLEN);
916
0
          MemoryContextSwitchTo(oldcontext);
917
0
          break;
918
0
        default:
919
0
          elog(ERROR, "unexpected jsonb datetime type oid %u",
920
0
             v->val.datetime.typid);
921
0
      }
922
0
      break;
923
0
    default:
924
0
      elog(ERROR, "invalid jsonb scalar type");
925
0
  }
926
0
}
927
928
/*
929
 * Given a JsonbContainer, expand to JsonbIterator to iterate over items
930
 * fully expanded to in-memory representation for manipulation.
931
 *
932
 * See JsonbIteratorNext() for notes on memory management.
933
 */
934
JsonbIterator *
935
JsonbIteratorInit(JsonbContainer *container)
936
0
{
937
0
  return iteratorFromContainer(container, NULL);
938
0
}
939
940
/*
941
 * Get next JsonbValue while iterating
942
 *
943
 * Caller should initially pass their own, original iterator.  They may get
944
 * back a child iterator palloc()'d here instead.  The function can be relied
945
 * on to free those child iterators, lest the memory allocated for highly
946
 * nested objects become unreasonable, but only if callers don't end iteration
947
 * early (by breaking upon having found something in a search, for example).
948
 *
949
 * Callers in such a scenario, that are particularly sensitive to leaking
950
 * memory in a long-lived context may walk the ancestral tree from the final
951
 * iterator we left them with to its oldest ancestor, pfree()ing as they go.
952
 * They do not have to free any other memory previously allocated for iterators
953
 * but not accessible as direct ancestors of the iterator they're last passed
954
 * back.
955
 *
956
 * Returns "Jsonb sequential processing" token value.  Iterator "state"
957
 * reflects the current stage of the process in a less granular fashion, and is
958
 * mostly used here to track things internally with respect to particular
959
 * iterators.
960
 *
961
 * Clients of this function should not have to handle any jbvBinary values
962
 * (since recursive calls will deal with this), provided skipNested is false.
963
 * It is our job to expand the jbvBinary representation without bothering them
964
 * with it.  However, clients should not take it upon themselves to touch array
965
 * or Object element/pair buffers, since their element/pair pointers are
966
 * garbage.
967
 *
968
 * *val is not meaningful when the result is WJB_DONE, WJB_END_ARRAY or
969
 * WJB_END_OBJECT.  However, we set val->type = jbvNull in those cases,
970
 * so that callers may assume that val->type is always well-defined.
971
 */
972
JsonbIteratorToken
973
JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
974
0
{
975
0
  if (*it == NULL)
976
0
  {
977
0
    val->type = jbvNull;
978
0
    return WJB_DONE;
979
0
  }
980
981
  /*
982
   * When stepping into a nested container, we jump back here to start
983
   * processing the child. We will not recurse further in one call, because
984
   * processing the child will always begin in JBI_ARRAY_START or
985
   * JBI_OBJECT_START state.
986
   */
987
0
recurse:
988
0
  switch ((*it)->state)
989
0
  {
990
0
    case JBI_ARRAY_START:
991
      /* Set v to array on first array call */
992
0
      val->type = jbvArray;
993
0
      val->val.array.nElems = (*it)->nElems;
994
995
      /*
996
       * v->val.array.elems is not actually set, because we aren't doing
997
       * a full conversion
998
       */
999
0
      val->val.array.rawScalar = (*it)->isScalar;
1000
0
      (*it)->curIndex = 0;
1001
0
      (*it)->curDataOffset = 0;
1002
0
      (*it)->curValueOffset = 0;  /* not actually used */
1003
      /* Set state for next call */
1004
0
      (*it)->state = JBI_ARRAY_ELEM;
1005
0
      return WJB_BEGIN_ARRAY;
1006
1007
0
    case JBI_ARRAY_ELEM:
1008
0
      if ((*it)->curIndex >= (*it)->nElems)
1009
0
      {
1010
        /*
1011
         * All elements within array already processed.  Report this
1012
         * to caller, and give it back original parent iterator (which
1013
         * independently tracks iteration progress at its level of
1014
         * nesting).
1015
         */
1016
0
        *it = freeAndGetParent(*it);
1017
0
        val->type = jbvNull;
1018
0
        return WJB_END_ARRAY;
1019
0
      }
1020
1021
0
      fillJsonbValue((*it)->container, (*it)->curIndex,
1022
0
               (*it)->dataProper, (*it)->curDataOffset,
1023
0
               val);
1024
1025
0
      JBE_ADVANCE_OFFSET((*it)->curDataOffset,
1026
0
                 (*it)->children[(*it)->curIndex]);
1027
0
      (*it)->curIndex++;
1028
1029
0
      if (!IsAJsonbScalar(val) && !skipNested)
1030
0
      {
1031
        /* Recurse into container. */
1032
0
        *it = iteratorFromContainer(val->val.binary.data, *it);
1033
0
        goto recurse;
1034
0
      }
1035
0
      else
1036
0
      {
1037
        /*
1038
         * Scalar item in array, or a container and caller didn't want
1039
         * us to recurse into it.
1040
         */
1041
0
        return WJB_ELEM;
1042
0
      }
1043
1044
0
    case JBI_OBJECT_START:
1045
      /* Set v to object on first object call */
1046
0
      val->type = jbvObject;
1047
0
      val->val.object.nPairs = (*it)->nElems;
1048
1049
      /*
1050
       * v->val.object.pairs is not actually set, because we aren't
1051
       * doing a full conversion
1052
       */
1053
0
      (*it)->curIndex = 0;
1054
0
      (*it)->curDataOffset = 0;
1055
0
      (*it)->curValueOffset = getJsonbOffset((*it)->container,
1056
0
                           (*it)->nElems);
1057
      /* Set state for next call */
1058
0
      (*it)->state = JBI_OBJECT_KEY;
1059
0
      return WJB_BEGIN_OBJECT;
1060
1061
0
    case JBI_OBJECT_KEY:
1062
0
      if ((*it)->curIndex >= (*it)->nElems)
1063
0
      {
1064
        /*
1065
         * All pairs within object already processed.  Report this to
1066
         * caller, and give it back original containing iterator
1067
         * (which independently tracks iteration progress at its level
1068
         * of nesting).
1069
         */
1070
0
        *it = freeAndGetParent(*it);
1071
0
        val->type = jbvNull;
1072
0
        return WJB_END_OBJECT;
1073
0
      }
1074
0
      else
1075
0
      {
1076
        /* Return key of a key/value pair.  */
1077
0
        fillJsonbValue((*it)->container, (*it)->curIndex,
1078
0
                 (*it)->dataProper, (*it)->curDataOffset,
1079
0
                 val);
1080
0
        if (val->type != jbvString)
1081
0
          elog(ERROR, "unexpected jsonb type as object key");
1082
1083
        /* Set state for next call */
1084
0
        (*it)->state = JBI_OBJECT_VALUE;
1085
0
        return WJB_KEY;
1086
0
      }
1087
1088
0
    case JBI_OBJECT_VALUE:
1089
      /* Set state for next call */
1090
0
      (*it)->state = JBI_OBJECT_KEY;
1091
1092
0
      fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
1093
0
               (*it)->dataProper, (*it)->curValueOffset,
1094
0
               val);
1095
1096
0
      JBE_ADVANCE_OFFSET((*it)->curDataOffset,
1097
0
                 (*it)->children[(*it)->curIndex]);
1098
0
      JBE_ADVANCE_OFFSET((*it)->curValueOffset,
1099
0
                 (*it)->children[(*it)->curIndex + (*it)->nElems]);
1100
0
      (*it)->curIndex++;
1101
1102
      /*
1103
       * Value may be a container, in which case we recurse with new,
1104
       * child iterator (unless the caller asked not to, by passing
1105
       * skipNested).
1106
       */
1107
0
      if (!IsAJsonbScalar(val) && !skipNested)
1108
0
      {
1109
0
        *it = iteratorFromContainer(val->val.binary.data, *it);
1110
0
        goto recurse;
1111
0
      }
1112
0
      else
1113
0
        return WJB_VALUE;
1114
0
  }
1115
1116
0
  elog(ERROR, "invalid jsonb iterator state");
1117
  /* satisfy compilers that don't know that elog(ERROR) doesn't return */
1118
0
  val->type = jbvNull;
1119
0
  return WJB_DONE;
1120
0
}
1121
1122
/*
1123
 * Initialize an iterator for iterating all elements in a container.
1124
 */
1125
static JsonbIterator *
1126
iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
1127
0
{
1128
0
  JsonbIterator *it;
1129
1130
0
  it = palloc0_object(JsonbIterator);
1131
0
  it->container = container;
1132
0
  it->parent = parent;
1133
0
  it->nElems = JsonContainerSize(container);
1134
1135
  /* Array starts just after header */
1136
0
  it->children = container->children;
1137
1138
0
  switch (container->header & (JB_FARRAY | JB_FOBJECT))
1139
0
  {
1140
0
    case JB_FARRAY:
1141
0
      it->dataProper =
1142
0
        (char *) it->children + it->nElems * sizeof(JEntry);
1143
0
      it->isScalar = JsonContainerIsScalar(container);
1144
      /* This is either a "raw scalar", or an array */
1145
0
      Assert(!it->isScalar || it->nElems == 1);
1146
1147
0
      it->state = JBI_ARRAY_START;
1148
0
      break;
1149
1150
0
    case JB_FOBJECT:
1151
0
      it->dataProper =
1152
0
        (char *) it->children + it->nElems * sizeof(JEntry) * 2;
1153
0
      it->state = JBI_OBJECT_START;
1154
0
      break;
1155
1156
0
    default:
1157
0
      elog(ERROR, "unknown type of jsonb container");
1158
0
  }
1159
1160
0
  return it;
1161
0
}
1162
1163
/*
1164
 * JsonbIteratorNext() worker:  Return parent, while freeing memory for current
1165
 * iterator
1166
 */
1167
static JsonbIterator *
1168
freeAndGetParent(JsonbIterator *it)
1169
0
{
1170
0
  JsonbIterator *v = it->parent;
1171
1172
0
  pfree(it);
1173
0
  return v;
1174
0
}
1175
1176
/*
1177
 * Worker for "contains" operator's function
1178
 *
1179
 * Formally speaking, containment is top-down, unordered subtree isomorphism.
1180
 *
1181
 * Takes iterators that belong to some container type.  These iterators
1182
 * "belong" to those values in the sense that they've just been initialized in
1183
 * respect of them by the caller (perhaps in a nested fashion).
1184
 *
1185
 * "val" is lhs Jsonb, and mContained is rhs Jsonb when called from top level.
1186
 * We determine if mContained is contained within val.
1187
 */
1188
bool
1189
JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
1190
0
{
1191
0
  JsonbValue  vval,
1192
0
        vcontained;
1193
0
  JsonbIteratorToken rval,
1194
0
        rcont;
1195
1196
  /*
1197
   * Guard against stack overflow due to overly complex Jsonb.
1198
   *
1199
   * Functions called here independently take this precaution, but that
1200
   * might not be sufficient since this is also a recursive function.
1201
   */
1202
0
  check_stack_depth();
1203
1204
0
  rval = JsonbIteratorNext(val, &vval, false);
1205
0
  rcont = JsonbIteratorNext(mContained, &vcontained, false);
1206
1207
0
  if (rval != rcont)
1208
0
  {
1209
    /*
1210
     * The differing return values can immediately be taken as indicating
1211
     * two differing container types at this nesting level, which is
1212
     * sufficient reason to give up entirely (but it should be the case
1213
     * that they're both some container type).
1214
     */
1215
0
    Assert(rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY);
1216
0
    Assert(rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY);
1217
0
    return false;
1218
0
  }
1219
0
  else if (rcont == WJB_BEGIN_OBJECT)
1220
0
  {
1221
0
    Assert(vval.type == jbvObject);
1222
0
    Assert(vcontained.type == jbvObject);
1223
1224
    /*
1225
     * If the lhs has fewer pairs than the rhs, it can't possibly contain
1226
     * the rhs.  (This conclusion is safe only because we de-duplicate
1227
     * keys in all Jsonb objects; thus there can be no corresponding
1228
     * optimization in the array case.)  The case probably won't arise
1229
     * often, but since it's such a cheap check we may as well make it.
1230
     */
1231
0
    if (vval.val.object.nPairs < vcontained.val.object.nPairs)
1232
0
      return false;
1233
1234
    /* Work through rhs "is it contained within?" object */
1235
0
    for (;;)
1236
0
    {
1237
0
      JsonbValue *lhsVal; /* lhsVal is from pair in lhs object */
1238
0
      JsonbValue  lhsValBuf;
1239
1240
0
      rcont = JsonbIteratorNext(mContained, &vcontained, false);
1241
1242
      /*
1243
       * When we get through caller's rhs "is it contained within?"
1244
       * object without failing to find one of its values, it's
1245
       * contained.
1246
       */
1247
0
      if (rcont == WJB_END_OBJECT)
1248
0
        return true;
1249
1250
0
      Assert(rcont == WJB_KEY);
1251
0
      Assert(vcontained.type == jbvString);
1252
1253
      /* First, find value by key... */
1254
0
      lhsVal =
1255
0
        getKeyJsonValueFromContainer((*val)->container,
1256
0
                       vcontained.val.string.val,
1257
0
                       vcontained.val.string.len,
1258
0
                       &lhsValBuf);
1259
0
      if (!lhsVal)
1260
0
        return false;
1261
1262
      /*
1263
       * ...at this stage it is apparent that there is at least a key
1264
       * match for this rhs pair.
1265
       */
1266
0
      rcont = JsonbIteratorNext(mContained, &vcontained, true);
1267
1268
0
      Assert(rcont == WJB_VALUE);
1269
1270
      /*
1271
       * Compare rhs pair's value with lhs pair's value just found using
1272
       * key
1273
       */
1274
0
      if (lhsVal->type != vcontained.type)
1275
0
      {
1276
0
        return false;
1277
0
      }
1278
0
      else if (IsAJsonbScalar(lhsVal))
1279
0
      {
1280
0
        if (!equalsJsonbScalarValue(lhsVal, &vcontained))
1281
0
          return false;
1282
0
      }
1283
0
      else
1284
0
      {
1285
        /* Nested container value (object or array) */
1286
0
        JsonbIterator *nestval,
1287
0
               *nestContained;
1288
1289
0
        Assert(lhsVal->type == jbvBinary);
1290
0
        Assert(vcontained.type == jbvBinary);
1291
1292
0
        nestval = JsonbIteratorInit(lhsVal->val.binary.data);
1293
0
        nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1294
1295
        /*
1296
         * Match "value" side of rhs datum object's pair recursively.
1297
         * It's a nested structure.
1298
         *
1299
         * Note that nesting still has to "match up" at the right
1300
         * nesting sub-levels.  However, there need only be zero or
1301
         * more matching pairs (or elements) at each nesting level
1302
         * (provided the *rhs* pairs/elements *all* match on each
1303
         * level), which enables searching nested structures for a
1304
         * single String or other primitive type sub-datum quite
1305
         * effectively (provided the user constructed the rhs nested
1306
         * structure such that we "know where to look").
1307
         *
1308
         * In other words, the mapping of container nodes in the rhs
1309
         * "vcontained" Jsonb to internal nodes on the lhs is
1310
         * injective, and parent-child edges on the rhs must be mapped
1311
         * to parent-child edges on the lhs to satisfy the condition
1312
         * of containment (plus of course the mapped nodes must be
1313
         * equal).
1314
         */
1315
0
        if (!JsonbDeepContains(&nestval, &nestContained))
1316
0
          return false;
1317
0
      }
1318
0
    }
1319
0
  }
1320
0
  else if (rcont == WJB_BEGIN_ARRAY)
1321
0
  {
1322
0
    JsonbValue *lhsConts = NULL;
1323
0
    uint32    nLhsElems = vval.val.array.nElems;
1324
1325
0
    Assert(vval.type == jbvArray);
1326
0
    Assert(vcontained.type == jbvArray);
1327
1328
    /*
1329
     * Handle distinction between "raw scalar" pseudo arrays, and real
1330
     * arrays.
1331
     *
1332
     * A raw scalar may contain another raw scalar, and an array may
1333
     * contain a raw scalar, but a raw scalar may not contain an array. We
1334
     * don't do something like this for the object case, since objects can
1335
     * only contain pairs, never raw scalars (a pair is represented by an
1336
     * rhs object argument with a single contained pair).
1337
     */
1338
0
    if (vval.val.array.rawScalar && !vcontained.val.array.rawScalar)
1339
0
      return false;
1340
1341
    /* Work through rhs "is it contained within?" array */
1342
0
    for (;;)
1343
0
    {
1344
0
      rcont = JsonbIteratorNext(mContained, &vcontained, true);
1345
1346
      /*
1347
       * When we get through caller's rhs "is it contained within?"
1348
       * array without failing to find one of its values, it's
1349
       * contained.
1350
       */
1351
0
      if (rcont == WJB_END_ARRAY)
1352
0
        return true;
1353
1354
0
      Assert(rcont == WJB_ELEM);
1355
1356
0
      if (IsAJsonbScalar(&vcontained))
1357
0
      {
1358
0
        if (!findJsonbValueFromContainer((*val)->container,
1359
0
                         JB_FARRAY,
1360
0
                         &vcontained))
1361
0
          return false;
1362
0
      }
1363
0
      else
1364
0
      {
1365
0
        uint32    i;
1366
1367
        /*
1368
         * If this is first container found in rhs array (at this
1369
         * depth), initialize temp lhs array of containers
1370
         */
1371
0
        if (lhsConts == NULL)
1372
0
        {
1373
0
          uint32    j = 0;
1374
1375
          /* Make room for all possible values */
1376
0
          lhsConts = palloc_array(JsonbValue, nLhsElems);
1377
1378
0
          for (i = 0; i < nLhsElems; i++)
1379
0
          {
1380
            /* Store all lhs elements in temp array */
1381
0
            rcont = JsonbIteratorNext(val, &vval, true);
1382
0
            Assert(rcont == WJB_ELEM);
1383
1384
0
            if (vval.type == jbvBinary)
1385
0
              lhsConts[j++] = vval;
1386
0
          }
1387
1388
          /* No container elements in temp array, so give up now */
1389
0
          if (j == 0)
1390
0
            return false;
1391
1392
          /* We may have only partially filled array */
1393
0
          nLhsElems = j;
1394
0
        }
1395
1396
        /* XXX: Nested array containment is O(N^2) */
1397
0
        for (i = 0; i < nLhsElems; i++)
1398
0
        {
1399
          /* Nested container value (object or array) */
1400
0
          JsonbIterator *nestval,
1401
0
                 *nestContained;
1402
0
          bool    contains;
1403
1404
0
          nestval = JsonbIteratorInit(lhsConts[i].val.binary.data);
1405
0
          nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1406
1407
0
          contains = JsonbDeepContains(&nestval, &nestContained);
1408
1409
0
          if (nestval)
1410
0
            pfree(nestval);
1411
0
          if (nestContained)
1412
0
            pfree(nestContained);
1413
0
          if (contains)
1414
0
            break;
1415
0
        }
1416
1417
        /*
1418
         * Report rhs container value is not contained if couldn't
1419
         * match rhs container to *some* lhs cont
1420
         */
1421
0
        if (i == nLhsElems)
1422
0
          return false;
1423
0
      }
1424
0
    }
1425
0
  }
1426
0
  else
1427
0
  {
1428
0
    elog(ERROR, "invalid jsonb container type");
1429
0
  }
1430
1431
0
  elog(ERROR, "unexpectedly fell off end of jsonb container");
1432
0
  return false;
1433
0
}
1434
1435
/*
1436
 * Hash a JsonbValue scalar value, mixing the hash value into an existing
1437
 * hash provided by the caller.
1438
 *
1439
 * Some callers may wish to independently XOR in JB_FOBJECT and JB_FARRAY
1440
 * flags.
1441
 */
1442
void
1443
JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
1444
0
{
1445
0
  uint32    tmp;
1446
1447
  /* Compute hash value for scalarVal */
1448
0
  switch (scalarVal->type)
1449
0
  {
1450
0
    case jbvNull:
1451
0
      tmp = 0x01;
1452
0
      break;
1453
0
    case jbvString:
1454
0
      tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1455
0
                      scalarVal->val.string.len));
1456
0
      break;
1457
0
    case jbvNumeric:
1458
      /* Must hash equal numerics to equal hash codes */
1459
0
      tmp = DatumGetUInt32(DirectFunctionCall1(hash_numeric,
1460
0
                           NumericGetDatum(scalarVal->val.numeric)));
1461
0
      break;
1462
0
    case jbvBool:
1463
0
      tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1464
1465
0
      break;
1466
0
    default:
1467
0
      elog(ERROR, "invalid jsonb scalar type");
1468
0
      tmp = 0;      /* keep compiler quiet */
1469
0
      break;
1470
0
  }
1471
1472
  /*
1473
   * Combine hash values of successive keys, values and elements by rotating
1474
   * the previous value left 1 bit, then XOR'ing in the new
1475
   * key/value/element's hash value.
1476
   */
1477
0
  *hash = pg_rotate_left32(*hash, 1);
1478
0
  *hash ^= tmp;
1479
0
}
1480
1481
/*
1482
 * Hash a value to a 64-bit value, with a seed. Otherwise, similar to
1483
 * JsonbHashScalarValue.
1484
 */
1485
void
1486
JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash,
1487
               uint64 seed)
1488
0
{
1489
0
  uint64    tmp;
1490
1491
0
  switch (scalarVal->type)
1492
0
  {
1493
0
    case jbvNull:
1494
0
      tmp = seed + 0x01;
1495
0
      break;
1496
0
    case jbvString:
1497
0
      tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1498
0
                           scalarVal->val.string.len,
1499
0
                           seed));
1500
0
      break;
1501
0
    case jbvNumeric:
1502
0
      tmp = DatumGetUInt64(DirectFunctionCall2(hash_numeric_extended,
1503
0
                           NumericGetDatum(scalarVal->val.numeric),
1504
0
                           UInt64GetDatum(seed)));
1505
0
      break;
1506
0
    case jbvBool:
1507
0
      if (seed)
1508
0
        tmp = DatumGetUInt64(DirectFunctionCall2(hashcharextended,
1509
0
                             BoolGetDatum(scalarVal->val.boolean),
1510
0
                             UInt64GetDatum(seed)));
1511
0
      else
1512
0
        tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1513
1514
0
      break;
1515
0
    default:
1516
0
      elog(ERROR, "invalid jsonb scalar type");
1517
0
      break;
1518
0
  }
1519
1520
0
  *hash = ROTATE_HIGH_AND_LOW_32BITS(*hash);
1521
0
  *hash ^= tmp;
1522
0
}
1523
1524
/*
1525
 * Are two scalar JsonbValues of the same type a and b equal?
1526
 */
1527
static bool
1528
equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
1529
0
{
1530
0
  if (a->type == b->type)
1531
0
  {
1532
0
    switch (a->type)
1533
0
    {
1534
0
      case jbvNull:
1535
0
        return true;
1536
0
      case jbvString:
1537
0
        return lengthCompareJsonbStringValue(a, b) == 0;
1538
0
      case jbvNumeric:
1539
0
        return DatumGetBool(DirectFunctionCall2(numeric_eq,
1540
0
                            PointerGetDatum(a->val.numeric),
1541
0
                            PointerGetDatum(b->val.numeric)));
1542
0
      case jbvBool:
1543
0
        return a->val.boolean == b->val.boolean;
1544
1545
0
      default:
1546
0
        elog(ERROR, "invalid jsonb scalar type");
1547
0
    }
1548
0
  }
1549
0
  elog(ERROR, "jsonb scalar type mismatch");
1550
0
  return false;
1551
0
}
1552
1553
/*
1554
 * Compare two scalar JsonbValues, returning -1, 0, or 1.
1555
 *
1556
 * Strings are compared using the default collation.  Used by B-tree
1557
 * operators, where a lexical sort order is generally expected.
1558
 */
1559
static int
1560
compareJsonbScalarValue(JsonbValue *a, JsonbValue *b)
1561
0
{
1562
0
  if (a->type == b->type)
1563
0
  {
1564
0
    switch (a->type)
1565
0
    {
1566
0
      case jbvNull:
1567
0
        return 0;
1568
0
      case jbvString:
1569
0
        return varstr_cmp(a->val.string.val,
1570
0
                  a->val.string.len,
1571
0
                  b->val.string.val,
1572
0
                  b->val.string.len,
1573
0
                  DEFAULT_COLLATION_OID);
1574
0
      case jbvNumeric:
1575
0
        return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
1576
0
                             PointerGetDatum(a->val.numeric),
1577
0
                             PointerGetDatum(b->val.numeric)));
1578
0
      case jbvBool:
1579
0
        if (a->val.boolean == b->val.boolean)
1580
0
          return 0;
1581
0
        else if (a->val.boolean > b->val.boolean)
1582
0
          return 1;
1583
0
        else
1584
0
          return -1;
1585
0
      default:
1586
0
        elog(ERROR, "invalid jsonb scalar type");
1587
0
    }
1588
0
  }
1589
0
  elog(ERROR, "jsonb scalar type mismatch");
1590
0
  return -1;
1591
0
}
1592
1593
1594
/*
1595
 * Functions for manipulating the resizable buffer used by convertJsonb and
1596
 * its subroutines.
1597
 */
1598
1599
/*
1600
 * Reserve 'len' bytes, at the end of the buffer, enlarging it if necessary.
1601
 * Returns the offset to the reserved area. The caller is expected to fill
1602
 * the reserved area later with copyToBuffer().
1603
 */
1604
static int
1605
reserveFromBuffer(StringInfo buffer, int len)
1606
0
{
1607
0
  int     offset;
1608
1609
  /* Make more room if needed */
1610
0
  enlargeStringInfo(buffer, len);
1611
1612
  /* remember current offset */
1613
0
  offset = buffer->len;
1614
1615
  /* reserve the space */
1616
0
  buffer->len += len;
1617
1618
  /*
1619
   * Keep a trailing null in place, even though it's not useful for us; it
1620
   * seems best to preserve the invariants of StringInfos.
1621
   */
1622
0
  buffer->data[buffer->len] = '\0';
1623
1624
0
  return offset;
1625
0
}
1626
1627
/*
1628
 * Copy 'len' bytes to a previously reserved area in buffer.
1629
 */
1630
static void
1631
copyToBuffer(StringInfo buffer, int offset, const void *data, int len)
1632
0
{
1633
0
  memcpy(buffer->data + offset, data, len);
1634
0
}
1635
1636
/*
1637
 * A shorthand for reserveFromBuffer + copyToBuffer.
1638
 */
1639
static void
1640
appendToBuffer(StringInfo buffer, const void *data, int len)
1641
0
{
1642
0
  int     offset;
1643
1644
0
  offset = reserveFromBuffer(buffer, len);
1645
0
  copyToBuffer(buffer, offset, data, len);
1646
0
}
1647
1648
1649
/*
1650
 * Append padding, so that the length of the StringInfo is int-aligned.
1651
 * Returns the number of padding bytes appended.
1652
 */
1653
static short
1654
padBufferToInt(StringInfo buffer)
1655
0
{
1656
0
  int     padlen,
1657
0
        p,
1658
0
        offset;
1659
1660
0
  padlen = INTALIGN(buffer->len) - buffer->len;
1661
1662
0
  offset = reserveFromBuffer(buffer, padlen);
1663
1664
  /* padlen must be small, so this is probably faster than a memset */
1665
0
  for (p = 0; p < padlen; p++)
1666
0
    buffer->data[offset + p] = '\0';
1667
1668
0
  return padlen;
1669
0
}
1670
1671
/*
1672
 * Given a JsonbValue, convert to Jsonb. The result is palloc'd.
1673
 */
1674
static Jsonb *
1675
convertToJsonb(JsonbValue *val)
1676
0
{
1677
0
  StringInfoData buffer;
1678
0
  JEntry    jentry;
1679
0
  Jsonb    *res;
1680
1681
  /* Should not already have binary representation */
1682
0
  Assert(val->type != jbvBinary);
1683
1684
  /* Allocate an output buffer. It will be enlarged as needed */
1685
0
  initStringInfo(&buffer);
1686
1687
  /* Make room for the varlena header */
1688
0
  reserveFromBuffer(&buffer, VARHDRSZ);
1689
1690
0
  convertJsonbValue(&buffer, &jentry, val, 0);
1691
1692
  /*
1693
   * Note: the JEntry of the root is discarded. Therefore the root
1694
   * JsonbContainer struct must contain enough information to tell what kind
1695
   * of value it is.
1696
   */
1697
1698
0
  res = (Jsonb *) buffer.data;
1699
1700
0
  SET_VARSIZE(res, buffer.len);
1701
1702
0
  return res;
1703
0
}
1704
1705
/*
1706
 * Subroutine of convertJsonb: serialize a single JsonbValue into buffer.
1707
 *
1708
 * The JEntry header for this node is returned in *header.  It is filled in
1709
 * with the length of this value and appropriate type bits.  If we wish to
1710
 * store an end offset rather than a length, it is the caller's responsibility
1711
 * to adjust for that.
1712
 *
1713
 * If the value is an array or an object, this recurses. 'level' is only used
1714
 * for debugging purposes.
1715
 */
1716
static void
1717
convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1718
0
{
1719
0
  check_stack_depth();
1720
1721
0
  if (!val)
1722
0
    return;
1723
1724
  /*
1725
   * A JsonbValue passed as val should never have a type of jbvBinary, and
1726
   * neither should any of its sub-components. Those values will be produced
1727
   * by convertJsonbArray and convertJsonbObject, the results of which will
1728
   * not be passed back to this function as an argument.
1729
   */
1730
1731
0
  if (IsAJsonbScalar(val))
1732
0
    convertJsonbScalar(buffer, header, val);
1733
0
  else if (val->type == jbvArray)
1734
0
    convertJsonbArray(buffer, header, val, level);
1735
0
  else if (val->type == jbvObject)
1736
0
    convertJsonbObject(buffer, header, val, level);
1737
0
  else
1738
0
    elog(ERROR, "unknown type of jsonb container to convert");
1739
0
}
1740
1741
static void
1742
convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1743
0
{
1744
0
  int     base_offset;
1745
0
  int     jentry_offset;
1746
0
  int     i;
1747
0
  int     totallen;
1748
0
  uint32    containerhead;
1749
0
  int     nElems = val->val.array.nElems;
1750
1751
  /* Remember where in the buffer this array starts. */
1752
0
  base_offset = buffer->len;
1753
1754
  /* Align to 4-byte boundary (any padding counts as part of my data) */
1755
0
  padBufferToInt(buffer);
1756
1757
  /*
1758
   * Construct the header Jentry and store it in the beginning of the
1759
   * variable-length payload.
1760
   */
1761
0
  containerhead = nElems | JB_FARRAY;
1762
0
  if (val->val.array.rawScalar)
1763
0
  {
1764
0
    Assert(nElems == 1);
1765
0
    Assert(level == 0);
1766
0
    containerhead |= JB_FSCALAR;
1767
0
  }
1768
1769
0
  appendToBuffer(buffer, &containerhead, sizeof(uint32));
1770
1771
  /* Reserve space for the JEntries of the elements. */
1772
0
  jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems);
1773
1774
0
  totallen = 0;
1775
0
  for (i = 0; i < nElems; i++)
1776
0
  {
1777
0
    JsonbValue *elem = &val->val.array.elems[i];
1778
0
    int     len;
1779
0
    JEntry    meta;
1780
1781
    /*
1782
     * Convert element, producing a JEntry and appending its
1783
     * variable-length data to buffer
1784
     */
1785
0
    convertJsonbValue(buffer, &meta, elem, level + 1);
1786
1787
0
    len = JBE_OFFLENFLD(meta);
1788
0
    totallen += len;
1789
1790
    /*
1791
     * Bail out if total variable-length data exceeds what will fit in a
1792
     * JEntry length field.  We check this in each iteration, not just
1793
     * once at the end, to forestall possible integer overflow.
1794
     */
1795
0
    if (totallen > JENTRY_OFFLENMASK)
1796
0
      ereport(ERROR,
1797
0
          (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1798
0
           errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1799
0
              JENTRY_OFFLENMASK)));
1800
1801
    /*
1802
     * Convert each JB_OFFSET_STRIDE'th length to an offset.
1803
     */
1804
0
    if ((i % JB_OFFSET_STRIDE) == 0)
1805
0
      meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1806
1807
0
    copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1808
0
    jentry_offset += sizeof(JEntry);
1809
0
  }
1810
1811
  /* Total data size is everything we've appended to buffer */
1812
0
  totallen = buffer->len - base_offset;
1813
1814
  /* Check length again, since we didn't include the metadata above */
1815
0
  if (totallen > JENTRY_OFFLENMASK)
1816
0
    ereport(ERROR,
1817
0
        (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1818
0
         errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1819
0
            JENTRY_OFFLENMASK)));
1820
1821
  /* Initialize the header of this node in the container's JEntry array */
1822
0
  *header = JENTRY_ISCONTAINER | totallen;
1823
0
}
1824
1825
static void
1826
convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1827
0
{
1828
0
  int     base_offset;
1829
0
  int     jentry_offset;
1830
0
  int     i;
1831
0
  int     totallen;
1832
0
  uint32    containerheader;
1833
0
  int     nPairs = val->val.object.nPairs;
1834
1835
  /* Remember where in the buffer this object starts. */
1836
0
  base_offset = buffer->len;
1837
1838
  /* Align to 4-byte boundary (any padding counts as part of my data) */
1839
0
  padBufferToInt(buffer);
1840
1841
  /*
1842
   * Construct the header Jentry and store it in the beginning of the
1843
   * variable-length payload.
1844
   */
1845
0
  containerheader = nPairs | JB_FOBJECT;
1846
0
  appendToBuffer(buffer, &containerheader, sizeof(uint32));
1847
1848
  /* Reserve space for the JEntries of the keys and values. */
1849
0
  jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nPairs * 2);
1850
1851
  /*
1852
   * Iterate over the keys, then over the values, since that is the ordering
1853
   * we want in the on-disk representation.
1854
   */
1855
0
  totallen = 0;
1856
0
  for (i = 0; i < nPairs; i++)
1857
0
  {
1858
0
    JsonbPair  *pair = &val->val.object.pairs[i];
1859
0
    int     len;
1860
0
    JEntry    meta;
1861
1862
    /*
1863
     * Convert key, producing a JEntry and appending its variable-length
1864
     * data to buffer
1865
     */
1866
0
    convertJsonbScalar(buffer, &meta, &pair->key);
1867
1868
0
    len = JBE_OFFLENFLD(meta);
1869
0
    totallen += len;
1870
1871
    /*
1872
     * Bail out if total variable-length data exceeds what will fit in a
1873
     * JEntry length field.  We check this in each iteration, not just
1874
     * once at the end, to forestall possible integer overflow.
1875
     */
1876
0
    if (totallen > JENTRY_OFFLENMASK)
1877
0
      ereport(ERROR,
1878
0
          (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1879
0
           errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1880
0
              JENTRY_OFFLENMASK)));
1881
1882
    /*
1883
     * Convert each JB_OFFSET_STRIDE'th length to an offset.
1884
     */
1885
0
    if ((i % JB_OFFSET_STRIDE) == 0)
1886
0
      meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1887
1888
0
    copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1889
0
    jentry_offset += sizeof(JEntry);
1890
0
  }
1891
0
  for (i = 0; i < nPairs; i++)
1892
0
  {
1893
0
    JsonbPair  *pair = &val->val.object.pairs[i];
1894
0
    int     len;
1895
0
    JEntry    meta;
1896
1897
    /*
1898
     * Convert value, producing a JEntry and appending its variable-length
1899
     * data to buffer
1900
     */
1901
0
    convertJsonbValue(buffer, &meta, &pair->value, level + 1);
1902
1903
0
    len = JBE_OFFLENFLD(meta);
1904
0
    totallen += len;
1905
1906
    /*
1907
     * Bail out if total variable-length data exceeds what will fit in a
1908
     * JEntry length field.  We check this in each iteration, not just
1909
     * once at the end, to forestall possible integer overflow.
1910
     */
1911
0
    if (totallen > JENTRY_OFFLENMASK)
1912
0
      ereport(ERROR,
1913
0
          (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1914
0
           errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1915
0
              JENTRY_OFFLENMASK)));
1916
1917
    /*
1918
     * Convert each JB_OFFSET_STRIDE'th length to an offset.
1919
     */
1920
0
    if (((i + nPairs) % JB_OFFSET_STRIDE) == 0)
1921
0
      meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1922
1923
0
    copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1924
0
    jentry_offset += sizeof(JEntry);
1925
0
  }
1926
1927
  /* Total data size is everything we've appended to buffer */
1928
0
  totallen = buffer->len - base_offset;
1929
1930
  /* Check length again, since we didn't include the metadata above */
1931
0
  if (totallen > JENTRY_OFFLENMASK)
1932
0
    ereport(ERROR,
1933
0
        (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1934
0
         errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1935
0
            JENTRY_OFFLENMASK)));
1936
1937
  /* Initialize the header of this node in the container's JEntry array */
1938
0
  *header = JENTRY_ISCONTAINER | totallen;
1939
0
}
1940
1941
static void
1942
convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
1943
0
{
1944
0
  int     numlen;
1945
0
  short   padlen;
1946
1947
0
  switch (scalarVal->type)
1948
0
  {
1949
0
    case jbvNull:
1950
0
      *header = JENTRY_ISNULL;
1951
0
      break;
1952
1953
0
    case jbvString:
1954
0
      appendToBuffer(buffer, scalarVal->val.string.val, scalarVal->val.string.len);
1955
1956
0
      *header = scalarVal->val.string.len;
1957
0
      break;
1958
1959
0
    case jbvNumeric:
1960
0
      numlen = VARSIZE_ANY(scalarVal->val.numeric);
1961
0
      padlen = padBufferToInt(buffer);
1962
1963
0
      appendToBuffer(buffer, scalarVal->val.numeric, numlen);
1964
1965
0
      *header = JENTRY_ISNUMERIC | (padlen + numlen);
1966
0
      break;
1967
1968
0
    case jbvBool:
1969
0
      *header = (scalarVal->val.boolean) ?
1970
0
        JENTRY_ISBOOL_TRUE : JENTRY_ISBOOL_FALSE;
1971
0
      break;
1972
1973
0
    case jbvDatetime:
1974
0
      {
1975
0
        char    buf[MAXDATELEN + 1];
1976
0
        size_t    len;
1977
1978
0
        JsonEncodeDateTime(buf,
1979
0
                   scalarVal->val.datetime.value,
1980
0
                   scalarVal->val.datetime.typid,
1981
0
                   &scalarVal->val.datetime.tz);
1982
0
        len = strlen(buf);
1983
0
        appendToBuffer(buffer, buf, len);
1984
1985
0
        *header = len;
1986
0
      }
1987
0
      break;
1988
1989
0
    default:
1990
0
      elog(ERROR, "invalid jsonb scalar type");
1991
0
  }
1992
0
}
1993
1994
/*
1995
 * Compare two jbvString JsonbValue values, a and b.
1996
 *
1997
 * This is a special qsort() comparator used to sort strings in certain
1998
 * internal contexts where it is sufficient to have a well-defined sort order.
1999
 * In particular, object pair keys are sorted according to this criteria to
2000
 * facilitate cheap binary searches where we don't care about lexical sort
2001
 * order.
2002
 *
2003
 * a and b are first sorted based on their length.  If a tie-breaker is
2004
 * required, only then do we consider string binary equality.
2005
 */
2006
static int
2007
lengthCompareJsonbStringValue(const void *a, const void *b)
2008
0
{
2009
0
  const JsonbValue *va = (const JsonbValue *) a;
2010
0
  const JsonbValue *vb = (const JsonbValue *) b;
2011
2012
0
  Assert(va->type == jbvString);
2013
0
  Assert(vb->type == jbvString);
2014
2015
0
  return lengthCompareJsonbString(va->val.string.val, va->val.string.len,
2016
0
                  vb->val.string.val, vb->val.string.len);
2017
0
}
2018
2019
/*
2020
 * Subroutine for lengthCompareJsonbStringValue
2021
 *
2022
 * This is also useful separately to implement binary search on
2023
 * JsonbContainers.
2024
 */
2025
static int
2026
lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
2027
0
{
2028
0
  if (len1 == len2)
2029
0
    return memcmp(val1, val2, len1);
2030
0
  else
2031
0
    return len1 > len2 ? 1 : -1;
2032
0
}
2033
2034
/*
2035
 * qsort_arg() comparator to compare JsonbPair values.
2036
 *
2037
 * Third argument 'binequal' may point to a bool. If it's set, *binequal is set
2038
 * to true iff a and b have full binary equality, since some callers have an
2039
 * interest in whether the two values are equal or merely equivalent.
2040
 *
2041
 * N.B: String comparisons here are "length-wise"
2042
 *
2043
 * Pairs with equals keys are ordered such that the order field is respected.
2044
 */
2045
static int
2046
lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
2047
0
{
2048
0
  const JsonbPair *pa = (const JsonbPair *) a;
2049
0
  const JsonbPair *pb = (const JsonbPair *) b;
2050
0
  int     res;
2051
2052
0
  res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
2053
0
  if (res == 0 && binequal)
2054
0
    *((bool *) binequal) = true;
2055
2056
  /*
2057
   * Guarantee keeping order of equal pair.  Unique algorithm will prefer
2058
   * first element as value.
2059
   */
2060
0
  if (res == 0)
2061
0
    res = (pa->order > pb->order) ? -1 : 1;
2062
2063
0
  return res;
2064
0
}
2065
2066
/*
2067
 * Sort and unique-ify pairs in JsonbValue object
2068
 */
2069
static void
2070
uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
2071
0
{
2072
0
  JsonbPair  *pairs = object->val.object.pairs;
2073
0
  int     nPairs = object->val.object.nPairs;
2074
0
  bool    hasNonUniq = false;
2075
2076
0
  Assert(object->type == jbvObject);
2077
2078
0
  if (nPairs > 1)
2079
0
    qsort_arg(pairs, nPairs, sizeof(JsonbPair),
2080
0
          lengthCompareJsonbPair, &hasNonUniq);
2081
2082
0
  if (hasNonUniq && unique_keys)
2083
0
    ereport(ERROR,
2084
0
        errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
2085
0
        errmsg("duplicate JSON object key value"));
2086
2087
0
  if (hasNonUniq || skip_nulls)
2088
0
  {
2089
0
    int     nNewPairs = 0;
2090
2091
0
    for (int i = 0; i < nPairs; i++)
2092
0
    {
2093
0
      JsonbPair  *ptr = pairs + i;
2094
2095
      /* Skip duplicate keys */
2096
0
      if (nNewPairs > 0 &&
2097
0
        lengthCompareJsonbStringValue(&pairs[nNewPairs - 1].key,
2098
0
                        &ptr->key) == 0)
2099
0
        continue;
2100
      /* Skip null values, if told to */
2101
0
      if (skip_nulls && ptr->value.type == jbvNull)
2102
0
        continue;
2103
      /* Emit this pair, but avoid no-op copy */
2104
0
      if (i > nNewPairs)
2105
0
        pairs[nNewPairs] = *ptr;
2106
0
      nNewPairs++;
2107
0
    }
2108
0
    object->val.object.nPairs = nNewPairs;
2109
0
  }
2110
0
}