Coverage Report

Created: 2026-10-22 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/util/jsonb_document.h
Line
Count
Source
1
/*
2
 *  Copyright (c) 2014, Facebook, Inc.
3
 *  All rights reserved.
4
 *
5
 *  This source code is licensed under the BSD-style license found in the
6
 *  LICENSE file in the root directory of this source tree. An additional grant
7
 *  of patent rights can be found in the PATENTS file in the same directory.
8
 *
9
 */
10
11
/*
12
 * This header defines JsonbDocument, JsonbKeyValue, and various value classes
13
 * which are derived from JsonbValue, and a forward iterator for container
14
 * values - essentially everything that is related to JSONB binary data
15
 * structures.
16
 *
17
 * Implementation notes:
18
 *
19
 * None of the classes in this header file can be instantiated directly (i.e.
20
 * you cannot create a JsonbKeyValue or JsonbValue object - all constructors
21
 * are declared non-public). We use the classes as wrappers on the packed JSONB
22
 * bytes (serialized), and cast the classes (types) to the underlying packed
23
 * byte array.
24
 *
25
 * For the same reason, we cannot define any JSONB value class to be virtual,
26
 * since we never call constructors, and will not instantiate vtbl and vptrs.
27
 *
28
 * Therefore, the classes are defined as packed structures (i.e. no data
29
 * alignment and padding), and the private member variables of the classes are
30
 * defined precisely in the same order as the JSONB spec. This ensures we
31
 * access the packed JSONB bytes correctly.
32
 *
33
 * The packed structures are highly optimized for in-place operations with low
34
 * overhead. The reads (and in-place writes) are performed directly on packed
35
 * bytes. There is no memory allocation at all at runtime.
36
 *
37
 * For updates/writes of values that will expand the original JSONB size, the
38
 * write will fail, and the caller needs to handle buffer increase.
39
 *
40
 * ** Iterator **
41
 * Both ObjectVal class and ArrayVal class have iterator type that you can use
42
 * to declare an iterator on a container object to go through the key-value
43
 * pairs or value list. The iterator has both non-const and const types.
44
 *
45
 * Note: iterators are forward direction only.
46
 *
47
 * ** Query **
48
 * Querying into containers is through the member functions find (for key/value
49
 * pairs) and get (for array elements), and is in streaming style. We don't
50
 * need to read/scan the whole JSONB packed bytes in order to return results.
51
 * Once the key/index is found, we will stop search.  You can use text to query
52
 * both objects and array (for array, text will be converted to integer index),
53
 * and use index to retrieve from array. Array index is 0-based.
54
 *
55
 * ** External dictionary **
56
 * During query processing, you can also pass a call-back function, so the
57
 * search will first try to check if the key string exists in the dictionary.
58
 * If so, search will be based on the id instead of the key string.
59
 * @author Tian Xia <tianx@fb.com>
60
 * 
61
 * this file is copied from 
62
 * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonDocument.h
63
 * and modified by Doris
64
 */
65
66
#ifndef JSONB_JSONBDOCUMENT_H
67
#define JSONB_JSONBDOCUMENT_H
68
69
#include <algorithm>
70
#include <array>
71
#include <cctype>
72
#include <charconv>
73
#include <cmath>
74
#include <cstddef>
75
#include <cstdint>
76
#include <limits>
77
#include <string>
78
#include <string_view>
79
#include <type_traits>
80
81
#include "common/compiler_util.h" // IWYU pragma: keep
82
#include "common/status.h"
83
#include "core/data_type/define_primitive_type.h"
84
#include "core/string_ref.h"
85
#include "core/types.h"
86
#include "util/string_util.h"
87
88
// #include "util/string_parser.hpp"
89
90
// Concept to check for supported decimal types
91
template <typename T>
92
concept JsonbDecimalType =
93
        std::same_as<T, doris::Decimal256> || std::same_as<T, doris::Decimal64> ||
94
        std::same_as<T, doris::Decimal128V3> || std::same_as<T, doris::Decimal32>;
95
96
namespace doris {
97
98
template <typename T>
99
constexpr bool is_pod_v = std::is_trivial_v<T> && std::is_standard_layout_v<T>;
100
101
struct JsonbStringVal;
102
struct ObjectVal;
103
struct ArrayVal;
104
struct JsonbBinaryVal;
105
struct ContainerVal;
106
107
template <JsonbDecimalType T>
108
struct JsonbDecimalVal;
109
110
using JsonbDecimal256 = JsonbDecimalVal<Decimal256>;
111
using JsonbDecimal128 = JsonbDecimalVal<Decimal128V3>;
112
using JsonbDecimal64 = JsonbDecimalVal<Decimal64>;
113
using JsonbDecimal32 = JsonbDecimalVal<Decimal32>;
114
115
template <typename T>
116
    requires std::is_integral_v<T> || std::is_floating_point_v<T>
117
struct NumberValT;
118
119
using JsonbInt8Val = NumberValT<int8_t>;
120
using JsonbInt16Val = NumberValT<int16_t>;
121
using JsonbInt32Val = NumberValT<int32_t>;
122
using JsonbInt64Val = NumberValT<int64_t>;
123
using JsonbInt128Val = NumberValT<int128_t>;
124
using JsonbDoubleVal = NumberValT<double>;
125
using JsonbFloatVal = NumberValT<float>;
126
127
template <typename T>
128
concept JsonbPodType = (std::same_as<T, JsonbStringVal> || std::same_as<T, ObjectVal> ||
129
                        std::same_as<T, ContainerVal> || std::same_as<T, ArrayVal> ||
130
                        std::same_as<T, JsonbBinaryVal> || std::same_as<T, JsonbDecimal32> ||
131
                        std::same_as<T, JsonbDecimal64> || std::same_as<T, JsonbDecimal128> ||
132
                        std::same_as<T, JsonbDecimal256> || std::same_as<T, JsonbDecimal32> ||
133
                        std::same_as<T, JsonbInt8Val> || std::same_as<T, JsonbInt16Val> ||
134
                        std::same_as<T, JsonbInt32Val> || std::same_as<T, JsonbInt64Val> ||
135
                        std::same_as<T, JsonbInt128Val> || std::same_as<T, JsonbFloatVal> ||
136
                        std::same_as<T, JsonbFloatVal> || std::same_as<T, JsonbDoubleVal>);
137
138
249k
#define JSONB_VER 1
139
140
using int128_t = __int128;
141
142
// forward declaration
143
struct JsonbValue;
144
145
class JsonbOutStream;
146
147
template <class OS_TYPE>
148
class JsonbWriterT;
149
150
using JsonbWriter = JsonbWriterT<JsonbOutStream>;
151
152
const int MaxNestingLevel = 100;
153
154
/*
155
 * JsonbType defines 10 primitive types and 2 container types, as described
156
 * below.
157
 * NOTE: Do NOT modify the existing values or their order in this enum.
158
 *      You may only append new entries at the end before `NUM_TYPES`.
159
 *      This enum will be used in serialized data and/or persisted data.
160
 *      Changing existing values may break backward compatibility
161
 *      with previously stored or transmitted data.
162
 *
163
 * primitive_value ::=
164
 *   0x00        //null value (0 byte)
165
 * | 0x01        //boolean true (0 byte)
166
 * | 0x02        //boolean false (0 byte)
167
 * | 0x03 int8   //char/int8 (1 byte)
168
 * | 0x04 int16  //int16 (2 bytes)
169
 * | 0x05 int32  //int32 (4 bytes)
170
 * | 0x06 int64  //int64 (8 bytes)
171
 * | 0x07 double //floating point (8 bytes)
172
 * | 0x08 string //variable length string
173
 * | 0x09 binary //variable length binary
174
 *
175
 * container ::=
176
 *   0x0A int32 key_value_list //object, int32 is the total bytes of the object
177
 * | 0x0B int32 value_list     //array, int32 is the total bytes of the array
178
 */
179
enum class JsonbType : char {
180
    T_Null = 0x00,
181
    T_True = 0x01,
182
    T_False = 0x02,
183
    T_Int8 = 0x03,
184
    T_Int16 = 0x04,
185
    T_Int32 = 0x05,
186
    T_Int64 = 0x06,
187
    T_Double = 0x07,
188
    T_String = 0x08,
189
    T_Binary = 0x09,
190
    T_Object = 0x0A,
191
    T_Array = 0x0B,
192
    T_Int128 = 0x0C,
193
    T_Float = 0x0D,
194
    T_Decimal32 = 0x0E,  // DecimalV3 only
195
    T_Decimal64 = 0x0F,  // DecimalV3 only
196
    T_Decimal128 = 0x10, // DecimalV3 only
197
    T_Decimal256 = 0x11, // DecimalV3 only
198
    NUM_TYPES,
199
};
200
201
11
inline PrimitiveType get_primitive_type_from_json_type(JsonbType json_type) {
202
11
    switch (json_type) {
203
1
    case JsonbType::T_Null:
204
1
        return TYPE_NULL;
205
1
    case JsonbType::T_True:
206
2
    case JsonbType::T_False:
207
2
        return TYPE_BOOLEAN;
208
0
    case JsonbType::T_Int8:
209
0
        return TYPE_TINYINT;
210
0
    case JsonbType::T_Int16:
211
0
        return TYPE_SMALLINT;
212
0
    case JsonbType::T_Int32:
213
0
        return TYPE_INT;
214
0
    case JsonbType::T_Int64:
215
0
        return TYPE_BIGINT;
216
0
    case JsonbType::T_Double:
217
0
        return TYPE_DOUBLE;
218
1
    case JsonbType::T_String:
219
1
        return TYPE_STRING;
220
0
    case JsonbType::T_Binary:
221
0
        return TYPE_BINARY;
222
0
    case JsonbType::T_Object:
223
0
        return TYPE_STRUCT;
224
1
    case JsonbType::T_Array:
225
1
        return TYPE_ARRAY;
226
1
    case JsonbType::T_Int128:
227
1
        return TYPE_LARGEINT;
228
1
    case JsonbType::T_Float:
229
1
        return TYPE_FLOAT;
230
1
    case JsonbType::T_Decimal32:
231
1
        return TYPE_DECIMAL32;
232
1
    case JsonbType::T_Decimal64:
233
1
        return TYPE_DECIMAL64;
234
1
    case JsonbType::T_Decimal128:
235
1
        return TYPE_DECIMAL128I;
236
1
    case JsonbType::T_Decimal256:
237
1
        return TYPE_DECIMAL256;
238
0
    default:
239
0
        throw Exception(ErrorCode::INTERNAL_ERROR, "Unsupported JsonbType: {}",
240
0
                        static_cast<int>(json_type));
241
11
    }
242
11
}
243
244
//for parse json path
245
constexpr char SCOPE = '$';
246
constexpr char BEGIN_MEMBER = '.';
247
constexpr char BEGIN_ARRAY = '[';
248
constexpr char END_ARRAY = ']';
249
constexpr char DOUBLE_QUOTE = '"';
250
constexpr char WILDCARD = '*';
251
constexpr char MINUS = '-';
252
constexpr char LAST[] = "last";
253
constexpr char ESCAPE = '\\';
254
constexpr unsigned int MEMBER_CODE = 0;
255
constexpr unsigned int ARRAY_CODE = 1;
256
257
/// A simple input stream class for the JSON path parser.
258
class Stream {
259
public:
260
    /// Creates an input stream reading from a character string.
261
    /// @param string  the input string
262
    /// @param length  the length of the input string
263
175
    Stream(const char* string, size_t length) : m_position(string), m_end(string + length) {}
264
265
    /// Returns a pointer to the current position in the stream.
266
247
    const char* position() const { return m_position; }
267
268
    /// Returns a pointer to the position just after the end of the stream.
269
0
    const char* end() const { return m_end; }
270
271
    /// Returns the number of bytes remaining in the stream.
272
3.80k
    size_t remaining() const {
273
3.80k
        assert(m_position <= m_end);
274
3.80k
        return m_end - m_position;
275
3.80k
    }
276
277
    /// Tells if the stream has been exhausted.
278
3.49k
    bool exhausted() const { return remaining() == 0; }
279
280
    /// Reads the next byte from the stream and moves the position forward.
281
167
    char read() {
282
167
        assert(!exhausted());
283
167
        return *m_position++;
284
167
    }
285
286
    /// Reads the next byte from the stream without moving the position forward.
287
1.99k
    char peek() const {
288
1.99k
        assert(!exhausted());
289
1.99k
        return *m_position;
290
1.99k
    }
291
292
    /// Moves the position to the next non-whitespace character.
293
652
    void skip_whitespace() {
294
652
        m_position = std::find_if_not(m_position, m_end, [](char c) { return std::isspace(c); });
295
652
    }
296
297
    /// Moves the position n bytes forward.
298
306
    void skip(size_t n) {
299
306
        assert(remaining() >= n);
300
306
        m_position += n;
301
306
        skip_whitespace();
302
306
    }
303
304
286
    void advance() { m_position++; }
305
306
399
    void clear_leg_ptr() { leg_ptr = nullptr; }
307
308
220
    void set_leg_ptr(char* ptr) {
309
220
        clear_leg_ptr();
310
220
        leg_ptr = ptr;
311
220
    }
312
313
279
    char* get_leg_ptr() { return leg_ptr; }
314
315
187
    void clear_leg_len() { leg_len = 0; }
316
317
348
    void add_leg_len() { leg_len++; }
318
319
318
    unsigned int get_leg_len() const { return leg_len; }
320
321
12
    void remove_escapes() {
322
12
        unsigned int new_len = 0;
323
86
        for (unsigned int i = 0; i < leg_len; ++i) {
324
75
            if (leg_ptr[i] != ESCAPE) {
325
45
                leg_ptr[new_len++] = leg_ptr[i];
326
45
                continue;
327
45
            }
328
329
30
            ++i;
330
30
            if (i >= leg_len) {
331
1
                break;
332
1
            }
333
334
29
            switch (leg_ptr[i]) {
335
2
            case 'b':
336
2
                leg_ptr[new_len++] = '\b';
337
2
                break;
338
2
            case 'f':
339
2
                leg_ptr[new_len++] = '\f';
340
2
                break;
341
3
            case 'n':
342
3
                leg_ptr[new_len++] = '\n';
343
3
                break;
344
2
            case 'r':
345
2
                leg_ptr[new_len++] = '\r';
346
2
                break;
347
2
            case 't':
348
2
                leg_ptr[new_len++] = '\t';
349
2
                break;
350
11
            case 'u': {
351
11
                if (i + 4 >= leg_len || leg_ptr[i + 1] != '0' || leg_ptr[i + 2] != '0') {
352
2
                    leg_ptr[new_len++] = leg_ptr[i];
353
2
                    break;
354
2
                }
355
356
18
                auto hex_to_int = [](char c) -> int {
357
18
                    if (c >= '0' && c <= '9') {
358
12
                        return c - '0';
359
12
                    }
360
6
                    if (c >= 'a' && c <= 'f') {
361
2
                        return c - 'a' + 10;
362
2
                    }
363
4
                    if (c >= 'A' && c <= 'F') {
364
1
                        return c - 'A' + 10;
365
1
                    }
366
3
                    return -1;
367
4
                };
368
9
                int high = hex_to_int(leg_ptr[i + 3]);
369
9
                int low = hex_to_int(leg_ptr[i + 4]);
370
9
                if (high < 0 || low < 0) {
371
3
                    leg_ptr[new_len++] = leg_ptr[i];
372
3
                    break;
373
3
                }
374
6
                leg_ptr[new_len++] = static_cast<char>((high << 4) | low);
375
6
                i += 4;
376
6
                break;
377
9
            }
378
7
            default:
379
7
                leg_ptr[new_len++] = leg_ptr[i];
380
7
                break;
381
29
            }
382
29
        }
383
12
        leg_ptr[new_len] = '\0';
384
12
        leg_len = new_len;
385
12
    }
386
387
191
    void set_has_escapes(bool has) { has_escapes = has; }
388
389
102
    bool get_has_escapes() const { return has_escapes; }
390
391
private:
392
    /// The current position in the stream.
393
    const char* m_position = nullptr;
394
395
    /// The end of the stream.
396
    const char* const m_end;
397
398
    ///path leg ptr
399
    char* leg_ptr = nullptr;
400
401
    ///path leg len
402
    unsigned int leg_len;
403
404
    ///Whether to contain escape characters
405
    bool has_escapes = false;
406
};
407
408
struct leg_info {
409
    ///path leg ptr
410
    char* leg_ptr = nullptr;
411
412
    ///path leg len
413
    unsigned int leg_len;
414
415
    ///array_index
416
    int array_index;
417
418
    ///type: 0 is member 1 is array
419
    unsigned int type;
420
421
    ///true only for an unquoted `*` member leg or a `[*]` array leg; a quoted "*" member leg
422
    ///is the literal key `*`
423
    bool is_wildcard = false;
424
425
    // NOLINTNEXTLINE(readability-non-const-parameter): str is an output parameter.
426
32
    bool to_string(std::string* str) const {
427
32
        if (type == MEMBER_CODE) {
428
29
            str->push_back(BEGIN_MEMBER);
429
            // JsonbPath::parse_member reads an unquoted member leg until the next '.' or '[',
430
            // rejects unquoted whitespace, treats a leading '*' as a wildcard and rejects an
431
            // unquoted empty leg. A key that would not read back as this same single leg must be
432
            // double-quoted so the emitted path can be parsed again (for example by
433
            // JSON_EXTRACT on the result of JSON_SEARCH). A parsed wildcard leg stays `*`.
434
29
            bool needs_quotes = leg_len == 0 || (!is_wildcard && *leg_ptr == WILDCARD);
435
29
            std::string tmp;
436
122
            for (auto* it = leg_ptr; it != (leg_ptr + leg_len); ++it) {
437
93
                auto c = static_cast<unsigned char>(*it);
438
93
                if (std::isspace(c) || *it == BEGIN_MEMBER || *it == BEGIN_ARRAY) {
439
13
                    needs_quotes = true;
440
13
                }
441
442
93
                switch (*it) {
443
4
                case '"':
444
4
                    tmp.append("\\\"");
445
4
                    break;
446
2
                case ESCAPE:
447
2
                    tmp.append("\\\\");
448
2
                    break;
449
2
                case '\b':
450
2
                    tmp.append("\\b");
451
2
                    break;
452
2
                case '\f':
453
2
                    tmp.append("\\f");
454
2
                    break;
455
3
                case '\n':
456
3
                    tmp.append("\\n");
457
3
                    break;
458
2
                case '\r':
459
2
                    tmp.append("\\r");
460
2
                    break;
461
2
                case '\t':
462
2
                    tmp.append("\\t");
463
2
                    break;
464
76
                default:
465
76
                    if (c < 0x20) {
466
6
                        constexpr char hex[] = "0123456789abcdef";
467
6
                        tmp.append("\\u00");
468
6
                        tmp.push_back(hex[c >> 4]);
469
6
                        tmp.push_back(hex[c & 0x0F]);
470
70
                    } else {
471
70
                        tmp.push_back(*it);
472
70
                    }
473
76
                    break;
474
93
                }
475
93
            }
476
29
            if (needs_quotes) {
477
16
                str->push_back(DOUBLE_QUOTE);
478
16
            }
479
29
            str->append(tmp);
480
29
            if (needs_quotes) {
481
16
                str->push_back(DOUBLE_QUOTE);
482
16
            }
483
29
            return true;
484
29
        } else if (type == ARRAY_CODE) {
485
3
            str->push_back(BEGIN_ARRAY);
486
3
            if (is_wildcard) {
487
2
                str->push_back(WILDCARD);
488
2
            } else {
489
1
                str->append(std::to_string(array_index));
490
1
            }
491
3
            str->push_back(END_ARRAY);
492
3
            return true;
493
3
        } else {
494
0
            return false;
495
0
        }
496
32
    }
497
};
498
499
class JsonbPath {
500
public:
501
    // parse json path
502
    static bool parsePath(Stream* stream, JsonbPath* path);
503
504
    static bool parse_array(Stream* stream, JsonbPath* path);
505
    static bool parse_member(Stream* stream, JsonbPath* path);
506
507
    //return true if json path valid else return false
508
    bool seek(const char* string, size_t length);
509
510
202
    void add_leg_to_leg_vector(std::unique_ptr<leg_info> leg) {
511
202
        leg_vector.emplace_back(leg.release());
512
202
    }
513
514
0
    void pop_leg_from_leg_vector() { leg_vector.pop_back(); }
515
516
    // NOLINTNEXTLINE(readability-non-const-parameter): res is an output parameter.
517
17
    bool to_string(std::string* res) const {
518
17
        res->push_back(SCOPE);
519
21
        for (const auto& leg : leg_vector) {
520
21
            auto valid = leg->to_string(res);
521
21
            if (!valid) {
522
0
                return false;
523
0
            }
524
21
        }
525
17
        return true;
526
17
    }
527
528
417
    size_t get_leg_vector_size() const { return leg_vector.size(); }
529
530
662
    leg_info* get_leg_from_leg_vector(size_t i) const { return leg_vector[i].get(); }
531
532
42
    bool is_wildcard() const { return _is_wildcard; }
533
167
    bool is_supper_wildcard() const { return _is_supper_wildcard; }
534
535
9
    void clean() { leg_vector.clear(); }
536
537
private:
538
    std::vector<std::unique_ptr<leg_info>> leg_vector;
539
    bool _is_wildcard = false;        // whether the path is a wildcard path
540
    bool _is_supper_wildcard = false; // supper wildcard likes '$**.a' or '$**[1]'
541
};
542
543
/*
544
 * JsonbFwdIteratorT implements JSONB's iterator template.
545
 *
546
 * Note: it is an FORWARD iterator only due to the design of JSONB format.
547
 */
548
template <class Iter_Type, class Cont_Type>
549
class JsonbFwdIteratorT {
550
public:
551
    using iterator = Iter_Type;
552
    using pointer = typename std::iterator_traits<Iter_Type>::pointer;
553
    using reference = typename std::iterator_traits<Iter_Type>::reference;
554
555
    explicit JsonbFwdIteratorT() : current_(nullptr) {}
556
22.5k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEC2ERKS3_
Line
Count
Source
556
22.1k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEC2ERKS3_
Line
Count
Source
556
417
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
557
558
    // allow non-const to const iterator conversion (same container type)
559
    template <class Iter_Ty>
560
    JsonbFwdIteratorT(const JsonbFwdIteratorT<Iter_Ty, Cont_Type>& rhs) : current_(rhs.base()) {}
561
562
23.1k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEeqERKS5_
Line
Count
Source
562
21.3k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEeqERKS5_
Line
Count
Source
562
1.82k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
563
564
21.6k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEneERKS5_
Line
Count
Source
564
19.9k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEneERKS5_
Line
Count
Source
564
1.66k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
565
566
2.97k
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEltERKS5_
Line
Count
Source
566
59
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEltERKS5_
Line
Count
Source
566
2.91k
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
567
568
    bool operator>(const JsonbFwdIteratorT& rhs) const { return !operator<(rhs); }
569
570
19.5k
    JsonbFwdIteratorT& operator++() {
571
19.5k
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
572
19.5k
        return *this;
573
19.5k
    }
_ZN5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEppEv
Line
Count
Source
570
18.7k
    JsonbFwdIteratorT& operator++() {
571
18.7k
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
572
18.7k
        return *this;
573
18.7k
    }
_ZN5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEppEv
Line
Count
Source
570
779
    JsonbFwdIteratorT& operator++() {
571
779
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
572
779
        return *this;
573
779
    }
574
575
    JsonbFwdIteratorT operator++(int) {
576
        auto tmp = *this;
577
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
578
        return tmp;
579
    }
580
581
751
    explicit operator pointer() { return current_; }
582
583
83
    reference operator*() const { return *current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEdeEv
Line
Count
Source
583
19
    reference operator*() const { return *current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEdeEv
Line
Count
Source
583
64
    reference operator*() const { return *current_; }
584
585
33.3k
    pointer operator->() const { return current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEptEv
Line
Count
Source
585
33.3k
    pointer operator->() const { return current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEptEv
Line
Count
Source
585
28
    pointer operator->() const { return current_; }
586
587
    iterator base() const { return current_; }
588
589
private:
590
    iterator current_;
591
};
592
using JsonbTypeUnder = std::underlying_type_t<JsonbType>;
593
594
#if defined(__clang__)
595
#pragma clang diagnostic push
596
#pragma clang diagnostic ignored "-Wzero-length-array"
597
#endif
598
#pragma pack(push, 1)
599
600
/*
601
 * JsonbDocument is the main object that accesses and queries JSONB packed
602
 * bytes. NOTE: JsonbDocument only allows object container as the top level
603
 * JSONB value. However, you can use the static method "createValue" to get any
604
 * JsonbValue object from the packed bytes.
605
 *
606
 * JsonbDocument object also dereferences to an object container value
607
 * (ObjectVal) once JSONB is loaded.
608
 *
609
 * ** Load **
610
 * JsonbDocument is usable after loading packed bytes (memory location) into
611
 * the object. We only need the header and first few bytes of the payload after
612
 * header to verify the JSONB.
613
 *
614
 * Note: creating an JsonbDocument (through createDocument) does not allocate
615
 * any memory. The document object is an efficient wrapper on the packed bytes
616
 * which is accessed directly.
617
 *
618
 * ** Query **
619
 * Query is through dereferencing into ObjectVal.
620
 */
621
class JsonbDocument {
622
public:
623
    // create an JsonbDocument object from JSONB packed bytes
624
    [[nodiscard]] static Status checkAndCreateDocument(const char* pb, size_t size,
625
                                                       const JsonbDocument** doc);
626
627
    // create an JsonbValue from JSONB packed bytes
628
    static const JsonbValue* createValue(const char* pb, size_t size);
629
630
0
    uint8_t version() const { return header_.ver_; }
631
632
39.5k
    const JsonbValue* getValue() const { return ((const JsonbValue*)payload_); }
633
634
    unsigned int numPackedBytes() const;
635
636
    const ObjectVal* operator->() const;
637
638
private:
639
    /*
640
   * JsonbHeader class defines JSONB header (internal to JsonbDocument).
641
   *
642
   * Currently it only contains version information (1-byte). We may expand the
643
   * header to include checksum of the JSONB binary for more security.
644
   */
645
    struct JsonbHeader {
646
        uint8_t ver_;
647
    } header_;
648
649
    char payload_[0];
650
};
651
652
/*
653
 * JsonbKeyValue class defines JSONB key type, as described below.
654
 *
655
 * key ::=
656
 *   0x00 int8    //1-byte dictionary id
657
 * | int8 (byte*) //int8 (>0) is the size of the key string
658
 *
659
 * value ::= primitive_value | container
660
 *
661
 * JsonbKeyValue can be either an id mapping to the key string in an external
662
 * dictionary, or it is the original key string. Whether to read an id or a
663
 * string is decided by the first byte (size).
664
 *
665
 * Note: a key object must be followed by a value object. Therefore, a key
666
 * object implicitly refers to a key-value pair, and you can get the value
667
 * object right after the key object. The function numPackedBytes hence
668
 * indicates the total size of the key-value pair, so that we will be able go
669
 * to next pair from the key.
670
 *
671
 * ** Dictionary size **
672
 * By default, the dictionary size is 255 (1-byte). Users can define
673
 * "USE_LARGE_DICT" to increase the dictionary size to 655535 (2-byte).
674
 */
675
class JsonbKeyValue {
676
public:
677
    // now we use sMaxKeyId to represent an empty key
678
    static const int sMaxKeyId = 65535;
679
    using keyid_type = uint16_t;
680
681
    static const uint8_t sMaxKeyLen = 64;
682
683
    // size of the key. 0 indicates it is stored as id
684
3.57k
    uint8_t klen() const { return size; }
685
686
    // get the key string. Note the string may not be null terminated.
687
1.85k
    const char* getKeyStr() const { return key.str_; }
688
689
9.36k
    keyid_type getKeyId() const { return key.id_; }
690
691
37.7k
    unsigned int keyPackedBytes() const {
692
37.7k
        return size ? (sizeof(size) + size) : (sizeof(size) + sizeof(keyid_type));
693
37.7k
    }
694
695
18.8k
    const JsonbValue* value() const {
696
18.8k
        return (const JsonbValue*)(((char*)this) + keyPackedBytes());
697
18.8k
    }
698
699
    // size of the total packed bytes (key+value)
700
    unsigned int numPackedBytes() const;
701
702
    uint8_t size;
703
704
    union key_ {
705
        keyid_type id_;
706
        char str_[1];
707
    } key;
708
};
709
710
struct JsonbFindResult {
711
    const JsonbValue* value = nullptr;   // found value
712
    std::unique_ptr<JsonbWriter> writer; // writer to write the value
713
    bool is_wildcard = false;            // whether the path is a wildcard path
714
};
715
716
/*
717
 * JsonbValue is the base class of all JSONB types. It contains only one member
718
 * variable - type info, which can be retrieved by member functions is[Type]()
719
 * or type().
720
 */
721
struct JsonbValue {
722
    static const uint32_t sMaxValueLen = 1 << 24; // 16M
723
724
4.33k
    bool isNull() const { return (type == JsonbType::T_Null); }
725
23
    bool isTrue() const { return (type == JsonbType::T_True); }
726
2
    bool isFalse() const { return (type == JsonbType::T_False); }
727
59
    bool isInt() const { return isInt8() || isInt16() || isInt32() || isInt64() || isInt128(); }
728
59
    bool isInt8() const { return (type == JsonbType::T_Int8); }
729
30
    bool isInt16() const { return (type == JsonbType::T_Int16); }
730
28
    bool isInt32() const { return (type == JsonbType::T_Int32); }
731
32
    bool isInt64() const { return (type == JsonbType::T_Int64); }
732
215
    bool isDouble() const { return (type == JsonbType::T_Double); }
733
178
    bool isFloat() const { return (type == JsonbType::T_Float); }
734
103
    bool isString() const { return (type == JsonbType::T_String); }
735
1.10k
    bool isBinary() const { return (type == JsonbType::T_Binary); }
736
127
    bool isObject() const { return (type == JsonbType::T_Object); }
737
79
    bool isArray() const { return (type == JsonbType::T_Array); }
738
31
    bool isInt128() const { return (type == JsonbType::T_Int128); }
739
84
    bool isDecimal() const {
740
84
        return (type == JsonbType::T_Decimal32 || type == JsonbType::T_Decimal64 ||
741
84
                type == JsonbType::T_Decimal128 || type == JsonbType::T_Decimal256);
742
84
    }
743
1
    bool isDecimal32() const { return (type == JsonbType::T_Decimal32); }
744
1
    bool isDecimal64() const { return (type == JsonbType::T_Decimal64); }
745
1
    bool isDecimal128() const { return (type == JsonbType::T_Decimal128); }
746
1
    bool isDecimal256() const { return (type == JsonbType::T_Decimal256); }
747
748
11
    PrimitiveType get_primitive_type() const { return get_primitive_type_from_json_type(type); }
749
750
0
    const char* typeName() const {
751
0
        switch (type) {
752
0
        case JsonbType::T_Null:
753
0
            return "null";
754
0
        case JsonbType::T_True:
755
0
        case JsonbType::T_False:
756
0
            return "bool";
757
0
        case JsonbType::T_Int8:
758
0
        case JsonbType::T_Int16:
759
0
        case JsonbType::T_Int32:
760
0
            return "int";
761
0
        case JsonbType::T_Int64:
762
0
            return "bigint";
763
0
        case JsonbType::T_Int128:
764
0
            return "largeint";
765
0
        case JsonbType::T_Double:
766
0
            return "double";
767
0
        case JsonbType::T_Float:
768
0
            return "float";
769
0
        case JsonbType::T_String:
770
0
            return "string";
771
0
        case JsonbType::T_Binary:
772
0
            return "binary";
773
0
        case JsonbType::T_Object:
774
0
            return "object";
775
0
        case JsonbType::T_Array:
776
0
            return "array";
777
0
        case JsonbType::T_Decimal32:
778
0
            return "Decimal32";
779
0
        case JsonbType::T_Decimal64:
780
0
            return "Decimal64";
781
0
        case JsonbType::T_Decimal128:
782
0
            return "Decimal128";
783
0
        case JsonbType::T_Decimal256:
784
0
            return "Decimal256";
785
0
        default:
786
0
            return "unknown";
787
0
        }
788
0
    }
789
790
    // size of the total packed bytes
791
    unsigned int numPackedBytes() const;
792
793
    // size of the value in bytes
794
    unsigned int size() const;
795
796
    //Get the number of jsonbvalue elements
797
    int numElements() const;
798
799
    //Whether to include the jsonbvalue rhs
800
    bool contains(const JsonbValue* rhs) const;
801
802
    // find the JSONB value by JsonbPath
803
    JsonbFindResult findValue(JsonbPath& path) const;
804
    friend class JsonbDocument;
805
806
    JsonbType type; // type info
807
808
    char payload[0]; // payload, which is the packed bytes of the value
809
810
    /**
811
    * @brief Unpacks the underlying Jsonb binary content as a pointer to type `T`.
812
    *
813
    * @tparam T A POD (Plain Old Data) type that must satisfy the `JsonbPodType` concept.
814
    *           This ensures that `T` is trivially copyable, standard-layout, and safe to
815
    *           reinterpret from raw bytes without invoking undefined behavior.
816
    *
817
    * @return A pointer to a `const T` object, interpreted from the internal buffer.
818
    *
819
    * @note The caller must ensure that the current JsonbValue actually contains data
820
    *       compatible with type `T`, otherwise the result is undefined.
821
    */
822
    template <JsonbPodType T>
823
88.2k
    const T* unpack() const {
824
88.2k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
88.2k
        return reinterpret_cast<const T*>(payload);
826
88.2k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_9ObjectValEEEPKT_v
Line
Count
Source
823
20.7k
    const T* unpack() const {
824
20.7k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
20.7k
        return reinterpret_cast<const T*>(payload);
826
20.7k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIaEEEEPKT_v
Line
Count
Source
823
1.24k
    const T* unpack() const {
824
1.24k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
1.24k
        return reinterpret_cast<const T*>(payload);
826
1.24k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIsEEEEPKT_v
Line
Count
Source
823
364
    const T* unpack() const {
824
364
        static_assert(is_pod_v<T>, "T must be a POD type");
825
364
        return reinterpret_cast<const T*>(payload);
826
364
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIiEEEEPKT_v
Line
Count
Source
823
3.48k
    const T* unpack() const {
824
3.48k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
3.48k
        return reinterpret_cast<const T*>(payload);
826
3.48k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIlEEEEPKT_v
Line
Count
Source
823
5.97k
    const T* unpack() const {
824
5.97k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
5.97k
        return reinterpret_cast<const T*>(payload);
826
5.97k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTInEEEEPKT_v
Line
Count
Source
823
4.17k
    const T* unpack() const {
824
4.17k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
4.17k
        return reinterpret_cast<const T*>(payload);
826
4.17k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIdEEEEPKT_v
Line
Count
Source
823
194
    const T* unpack() const {
824
194
        static_assert(is_pod_v<T>, "T must be a POD type");
825
194
        return reinterpret_cast<const T*>(payload);
826
194
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIfEEEEPKT_v
Line
Count
Source
823
28
    const T* unpack() const {
824
28
        static_assert(is_pod_v<T>, "T must be a POD type");
825
28
        return reinterpret_cast<const T*>(payload);
826
28
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_7DecimalIiEEEEEEPKT_v
Line
Count
Source
823
26
    const T* unpack() const {
824
26
        static_assert(is_pod_v<T>, "T must be a POD type");
825
26
        return reinterpret_cast<const T*>(payload);
826
26
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_7DecimalIlEEEEEEPKT_v
Line
Count
Source
823
16
    const T* unpack() const {
824
16
        static_assert(is_pod_v<T>, "T must be a POD type");
825
16
        return reinterpret_cast<const T*>(payload);
826
16
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_12Decimal128V3EEEEEPKT_v
Line
Count
Source
823
63
    const T* unpack() const {
824
63
        static_assert(is_pod_v<T>, "T must be a POD type");
825
63
        return reinterpret_cast<const T*>(payload);
826
63
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_7DecimalIN4wide7integerILm256EiEEEEEEEEPKT_v
Line
Count
Source
823
13
    const T* unpack() const {
824
13
        static_assert(is_pod_v<T>, "T must be a POD type");
825
13
        return reinterpret_cast<const T*>(payload);
826
13
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_14JsonbBinaryValEEEPKT_v
Line
Count
Source
823
32.0k
    const T* unpack() const {
824
32.0k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
32.0k
        return reinterpret_cast<const T*>(payload);
826
32.0k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_12ContainerValEEEPKT_v
Line
Count
Source
823
3.01k
    const T* unpack() const {
824
3.01k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
3.01k
        return reinterpret_cast<const T*>(payload);
826
3.01k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_8ArrayValEEEPKT_v
Line
Count
Source
823
245
    const T* unpack() const {
824
245
        static_assert(is_pod_v<T>, "T must be a POD type");
825
245
        return reinterpret_cast<const T*>(payload);
826
245
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_14JsonbStringValEEEPKT_v
Line
Count
Source
823
16.6k
    const T* unpack() const {
824
16.6k
        static_assert(is_pod_v<T>, "T must be a POD type");
825
16.6k
        return reinterpret_cast<const T*>(payload);
826
16.6k
    }
827
828
    // /**
829
    // * @brief Unpacks the underlying Jsonb binary content as a pointer to type `T`.
830
    // *
831
    // * @tparam T A POD (Plain Old Data) type that must satisfy the `JsonbPodType` concept.
832
    // *           This ensures that `T` is trivially copyable, standard-layout, and safe to
833
    // *           reinterpret from raw bytes without invoking undefined behavior.
834
    // *
835
    // * @return A pointer to a `T` object, interpreted from the internal buffer.
836
    // *
837
    // * @note The caller must ensure that the current JsonbValue actually contains data
838
    // *       compatible with type `T`, otherwise the result is undefined.
839
    // */
840
    // template <JsonbPodType T>
841
    // T* unpack() {
842
    //     static_assert(is_pod_v<T>, "T must be a POD type");
843
    //     return reinterpret_cast<T*>(payload);
844
    // }
845
846
    int128_t int_val() const;
847
};
848
849
// inline ObjectVal* JsonbDocument::operator->() {
850
//     return (((JsonbValue*)payload_)->unpack<ObjectVal>());
851
// }
852
853
19.2k
inline const ObjectVal* JsonbDocument::operator->() const {
854
19.2k
    return (((const JsonbValue*)payload_)->unpack<ObjectVal>());
855
19.2k
}
856
857
/*
858
 * NumerValT is the template class (derived from JsonbValue) of all number
859
 * types (integers and double).
860
 */
861
template <typename T>
862
    requires std::is_integral_v<T> || std::is_floating_point_v<T>
863
struct NumberValT {
864
public:
865
15.4k
    T val() const { return num; }
_ZNK5doris10NumberValTIaE3valEv
Line
Count
Source
865
1.24k
    T val() const { return num; }
_ZNK5doris10NumberValTIsE3valEv
Line
Count
Source
865
364
    T val() const { return num; }
_ZNK5doris10NumberValTIiE3valEv
Line
Count
Source
865
3.48k
    T val() const { return num; }
_ZNK5doris10NumberValTIlE3valEv
Line
Count
Source
865
5.97k
    T val() const { return num; }
_ZNK5doris10NumberValTInE3valEv
Line
Count
Source
865
4.17k
    T val() const { return num; }
_ZNK5doris10NumberValTIdE3valEv
Line
Count
Source
865
194
    T val() const { return num; }
_ZNK5doris10NumberValTIfE3valEv
Line
Count
Source
865
28
    T val() const { return num; }
866
867
    static unsigned int numPackedBytes() { return sizeof(JsonbValue) + sizeof(T); }
868
869
    T num;
870
};
871
872
60
inline int128_t JsonbValue::int_val() const {
873
60
    switch (type) {
874
52
    case JsonbType::T_Int8:
875
52
        return unpack<JsonbInt8Val>()->val();
876
1
    case JsonbType::T_Int16:
877
1
        return unpack<JsonbInt16Val>()->val();
878
0
    case JsonbType::T_Int32:
879
0
        return unpack<JsonbInt32Val>()->val();
880
4
    case JsonbType::T_Int64:
881
4
        return unpack<JsonbInt64Val>()->val();
882
3
    case JsonbType::T_Int128:
883
3
        return unpack<JsonbInt128Val>()->val();
884
0
    default:
885
0
        throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
886
0
                        static_cast<int32_t>(type));
887
60
    }
888
60
}
889
890
template <JsonbDecimalType T>
891
struct JsonbDecimalVal {
892
public:
893
    using NativeType = typename T::NativeType;
894
895
    // get the decimal value
896
86
    NativeType val() const {
897
        // to avoid memory alignment issues, we use memcpy to copy the value
898
86
        NativeType tmp;
899
86
        memcpy(&tmp, &value, sizeof(NativeType));
900
86
        return tmp;
901
86
    }
_ZNK5doris15JsonbDecimalValINS_7DecimalIiEEE3valEv
Line
Count
Source
896
17
    NativeType val() const {
897
        // to avoid memory alignment issues, we use memcpy to copy the value
898
17
        NativeType tmp;
899
17
        memcpy(&tmp, &value, sizeof(NativeType));
900
17
        return tmp;
901
17
    }
_ZNK5doris15JsonbDecimalValINS_7DecimalIlEEE3valEv
Line
Count
Source
896
9
    NativeType val() const {
897
        // to avoid memory alignment issues, we use memcpy to copy the value
898
9
        NativeType tmp;
899
9
        memcpy(&tmp, &value, sizeof(NativeType));
900
9
        return tmp;
901
9
    }
_ZNK5doris15JsonbDecimalValINS_12Decimal128V3EE3valEv
Line
Count
Source
896
54
    NativeType val() const {
897
        // to avoid memory alignment issues, we use memcpy to copy the value
898
54
        NativeType tmp;
899
54
        memcpy(&tmp, &value, sizeof(NativeType));
900
54
        return tmp;
901
54
    }
_ZNK5doris15JsonbDecimalValINS_7DecimalIN4wide7integerILm256EiEEEEE3valEv
Line
Count
Source
896
6
    NativeType val() const {
897
        // to avoid memory alignment issues, we use memcpy to copy the value
898
6
        NativeType tmp;
899
6
        memcpy(&tmp, &value, sizeof(NativeType));
900
6
        return tmp;
901
6
    }
902
903
176
    static constexpr int numPackedBytes() {
904
176
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
905
176
    }
_ZN5doris15JsonbDecimalValINS_7DecimalIiEEE14numPackedBytesEv
Line
Count
Source
903
45
    static constexpr int numPackedBytes() {
904
45
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
905
45
    }
_ZN5doris15JsonbDecimalValINS_7DecimalIlEEE14numPackedBytesEv
Line
Count
Source
903
33
    static constexpr int numPackedBytes() {
904
33
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
905
33
    }
_ZN5doris15JsonbDecimalValINS_12Decimal128V3EE14numPackedBytesEv
Line
Count
Source
903
92
    static constexpr int numPackedBytes() {
904
92
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
905
92
    }
_ZN5doris15JsonbDecimalValINS_7DecimalIN4wide7integerILm256EiEEEEE14numPackedBytesEv
Line
Count
Source
903
6
    static constexpr int numPackedBytes() {
904
6
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
905
6
    }
906
907
    uint32_t precision;
908
    uint32_t scale;
909
    NativeType value;
910
};
911
912
/*
913
 * BlobVal is the base class (derived from JsonbValue) for string and binary
914
 * types. The size indicates the total bytes of the payload.
915
 */
916
struct JsonbBinaryVal {
917
public:
918
    // size of the blob payload only
919
10.4k
    unsigned int getBlobLen() const { return size; }
920
921
    // return the blob as byte array
922
12.7k
    const char* getBlob() const { return payload; }
923
924
    // size of the total packed bytes
925
27.6k
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(size) + size; }
926
    friend class JsonbDocument;
927
928
    uint32_t size;
929
    char payload[0];
930
};
931
932
/*
933
 * String type
934
 * Note: JSONB string may not be a c-string (NULL-terminated)
935
 */
936
struct JsonbStringVal : public JsonbBinaryVal {
937
public:
938
    /*
939
    This function return the actual size of a string. Since for
940
    a string, it can be null-terminated with null paddings or it
941
    can take all the space in the payload without null in the end.
942
    So we need to check it to get the true actual length of a string.
943
  */
944
7
    size_t length() const {
945
        // It's an empty string
946
7
        if (0 == size) {
947
0
            return size;
948
0
        }
949
        // The string stored takes all the spaces in payload
950
7
        if (payload[size - 1] != 0) {
951
7
            return size;
952
7
        }
953
        // It's shorter than the size of payload
954
0
        return strnlen(payload, size);
955
7
    }
956
};
957
958
/*
959
 * ContainerVal is the base class (derived from JsonbValue) for object and
960
 * array types. The size indicates the total bytes of the payload.
961
 */
962
struct ContainerVal {
963
    // size of the container payload only
964
0
    unsigned int getContainerSize() const { return size; }
965
966
    // return the container payload as byte array
967
0
    const char* getPayload() const { return payload; }
968
969
    // size of the total packed bytes
970
3.01k
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(size) + size; }
971
    friend class JsonbDocument;
972
973
    uint32_t size;
974
    char payload[0];
975
};
976
977
/*
978
 * Object type
979
 */
980
struct ObjectVal : public ContainerVal {
981
    using value_type = JsonbKeyValue;
982
    using pointer = value_type*;
983
    using const_pointer = const value_type*;
984
    using const_iterator = JsonbFwdIteratorT<const_pointer, ObjectVal>;
985
986
1
    const_iterator search(const char* key) const {
987
1
        if (!key) {
988
0
            return end();
989
0
        }
990
1
        return search(key, (unsigned int)strlen(key));
991
1
    }
992
993
92
    const_iterator search(const char* key, unsigned int klen) const {
994
        // An empty key is a valid object key, so klen == 0 is still searched.
995
92
        if (!key) {
996
0
            return end();
997
0
        }
998
92
        return internalSearch(key, klen);
999
92
    }
1000
1001
    // Get number of elements in object
1002
58
    int numElem() const {
1003
58
        const char* pch = payload;
1004
58
        const char* fence = payload + size;
1005
1006
58
        unsigned int num = 0;
1007
150
        while (pch < fence) {
1008
92
            auto* pkey = (JsonbKeyValue*)(pch);
1009
92
            ++num;
1010
92
            pch += pkey->numPackedBytes();
1011
92
        }
1012
1013
58
        assert(pch == fence);
1014
1015
58
        return num;
1016
58
    }
1017
1018
    // find the JSONB value by a key string (null terminated)
1019
1
    const JsonbValue* find(const char* key) const {
1020
1
        if (!key) {
1021
0
            return nullptr;
1022
0
        }
1023
1
        return find(key, (unsigned int)strlen(key));
1024
1
    }
1025
1026
    // find the JSONB value by a key string (with length)
1027
90
    const JsonbValue* find(const char* key, unsigned int klen) const {
1028
90
        const_iterator kv = search(key, klen);
1029
90
        if (end() == kv) {
1030
15
            return nullptr;
1031
15
        }
1032
75
        return kv->value();
1033
90
    }
1034
1035
    // find the JSONB value by a key id, as stored when klen() == 0 (sMaxKeyId is the empty key)
1036
4
    const JsonbValue* find_by_key_id(JsonbKeyValue::keyid_type key_id) const {
1037
6
        for (auto it = begin(); it != end(); ++it) {
1038
4
            if (it->klen() == 0 && it->getKeyId() == key_id) {
1039
2
                return it->value();
1040
2
            }
1041
4
        }
1042
2
        return nullptr;
1043
4
    }
1044
1045
2.49k
    const_iterator begin() const { return const_iterator((pointer)payload); }
1046
1047
19.5k
    const_iterator end() const { return const_iterator((pointer)(payload + size)); }
1048
1049
    std::vector<std::pair<StringRef, const JsonbValue*>> get_ordered_key_value_pairs() const;
1050
1051
private:
1052
92
    const_iterator internalSearch(const char* key, unsigned int klen) const {
1053
92
        const char* pch = payload;
1054
92
        const char* fence = payload + size;
1055
1056
111
        while (pch < fence) {
1057
96
            const auto* pkey = (const JsonbKeyValue*)(pch);
1058
            // A key id entry is also stored with klen() == 0, so an empty name only matches
1059
            // the sMaxKeyId sentinel that JsonbWriter writes for an empty key.
1060
96
            if (klen == 0 ? pkey->klen() == 0 && pkey->getKeyId() == JsonbKeyValue::sMaxKeyId
1061
96
                          : klen == pkey->klen() && strncmp(key, pkey->getKeyStr(), klen) == 0) {
1062
77
                return const_iterator(pkey);
1063
77
            }
1064
19
            pch += pkey->numPackedBytes();
1065
19
        }
1066
1067
92
        assert(pch == fence);
1068
1069
15
        return end();
1070
15
    }
1071
};
1072
1073
/*
1074
 * Array type
1075
 */
1076
struct ArrayVal : public ContainerVal {
1077
    using value_type = JsonbValue;
1078
    using pointer = value_type*;
1079
    using const_pointer = const value_type*;
1080
    using const_iterator = JsonbFwdIteratorT<const_pointer, ArrayVal>;
1081
1082
    // get the JSONB value at index
1083
92
    const JsonbValue* get(int idx) const {
1084
92
        if (idx < 0) {
1085
0
            return nullptr;
1086
0
        }
1087
1088
92
        const char* pch = payload;
1089
92
        const char* fence = payload + size;
1090
1091
571
        while (pch < fence && idx-- > 0) {
1092
479
            pch += ((const JsonbValue*)pch)->numPackedBytes();
1093
479
        }
1094
92
        if (idx > 0 || pch == fence) {
1095
11
            return nullptr;
1096
11
        }
1097
1098
81
        return (const JsonbValue*)pch;
1099
92
    }
1100
1101
    // Get number of elements in array
1102
21
    int numElem() const {
1103
21
        const char* pch = payload;
1104
21
        const char* fence = payload + size;
1105
1106
21
        unsigned int num = 0;
1107
82
        while (pch < fence) {
1108
61
            ++num;
1109
61
            pch += ((const JsonbValue*)pch)->numPackedBytes();
1110
61
        }
1111
1112
21
        assert(pch == fence);
1113
1114
21
        return num;
1115
21
    }
1116
1117
195
    const_iterator begin() const { return const_iterator((pointer)payload); }
1118
1119
222
    const_iterator end() const { return const_iterator((pointer)(payload + size)); }
1120
};
1121
1122
namespace jsonb_detail {
1123
1124
struct JsonbScaledDecimal {
1125
    wide::Int256 value;
1126
    uint32_t scale;
1127
};
1128
1129
26
inline void validate_decimal_scale(uint32_t scale) {
1130
26
    if (scale > static_cast<uint32_t>(BeConsts::MAX_DECIMALV3_SCALE)) {
1131
2
        throw Exception(ErrorCode::INTERNAL_ERROR,
1132
2
                        "Invalid JSONB decimal scale: {}, max allowed scale: {}", scale,
1133
2
                        BeConsts::MAX_DECIMALV3_SCALE);
1134
2
    }
1135
26
}
1136
1137
44
inline bool is_numeric(const JsonbValue* value) {
1138
44
    return value->isInt() || value->isDouble() || value->isFloat() || value->isDecimal();
1139
44
}
1140
1141
10
inline double floating_value(const JsonbValue* value) {
1142
10
    if (value->isDouble()) {
1143
10
        return value->unpack<JsonbDoubleVal>()->val();
1144
10
    }
1145
0
    return value->unpack<JsonbFloatVal>()->val();
1146
10
}
1147
1148
20
inline JsonbScaledDecimal get_scaled_decimal(const JsonbValue* value) {
1149
20
    switch (value->type) {
1150
12
    case JsonbType::T_Decimal32: {
1151
12
        const auto* decimal = value->unpack<JsonbDecimal32>();
1152
12
        validate_decimal_scale(decimal->scale);
1153
12
        return {wide::Int256(decimal->val()), decimal->scale};
1154
0
    }
1155
2
    case JsonbType::T_Decimal64: {
1156
2
        const auto* decimal = value->unpack<JsonbDecimal64>();
1157
2
        validate_decimal_scale(decimal->scale);
1158
2
        return {wide::Int256(decimal->val()), decimal->scale};
1159
0
    }
1160
6
    case JsonbType::T_Decimal128: {
1161
6
        const auto* decimal = value->unpack<JsonbDecimal128>();
1162
6
        validate_decimal_scale(decimal->scale);
1163
6
        return {wide::Int256(decimal->val()), decimal->scale};
1164
0
    }
1165
0
    case JsonbType::T_Decimal256: {
1166
0
        const auto* decimal = value->unpack<JsonbDecimal256>();
1167
0
        validate_decimal_scale(decimal->scale);
1168
0
        return {decimal->val(), decimal->scale};
1169
0
    }
1170
0
    default:
1171
0
        throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB decimal value type: {}",
1172
0
                        static_cast<int32_t>(value->type));
1173
20
    }
1174
20
}
1175
1176
inline bool scaled_decimal_equal_decimal(const JsonbScaledDecimal& lhs,
1177
4
                                         const JsonbScaledDecimal& rhs) {
1178
4
    if (lhs.scale == rhs.scale) {
1179
0
        return lhs.value == rhs.value;
1180
0
    }
1181
1182
4
    if (lhs.scale < rhs.scale) {
1183
2
        const auto scale_multiplier = decimal_scale_multiplier<wide::Int256>(rhs.scale - lhs.scale);
1184
2
        return rhs.value % scale_multiplier == 0 && lhs.value == rhs.value / scale_multiplier;
1185
2
    }
1186
1187
2
    const auto scale_multiplier = decimal_scale_multiplier<wide::Int256>(lhs.scale - rhs.scale);
1188
2
    return lhs.value % scale_multiplier == 0 && lhs.value / scale_multiplier == rhs.value;
1189
4
}
1190
1191
4
inline bool scaled_decimal_equal_integer(const JsonbScaledDecimal& decimal, int128_t integer) {
1192
4
    const auto integer_value = wide::Int256(integer);
1193
4
    if (decimal.scale == 0) {
1194
0
        return decimal.value == integer_value;
1195
0
    }
1196
1197
4
    const auto scale_multiplier = decimal_scale_multiplier<wide::Int256>(decimal.scale);
1198
4
    return decimal.value % scale_multiplier == 0 &&
1199
4
           decimal.value / scale_multiplier == integer_value;
1200
4
}
1201
1202
inline constexpr auto kPowersOfFive = [] {
1203
    std::array<wide::Int256, BeConsts::MAX_DECIMALV3_SCALE + 1> powers {};
1204
    powers[0] = 1;
1205
    for (size_t i = 1; i < powers.size(); ++i) {
1206
        powers[i] = powers[i - 1] * 5;
1207
    }
1208
    return powers;
1209
}();
1210
1211
6
inline wide::Int256 power_of_five(uint32_t exponent) {
1212
6
    validate_decimal_scale(exponent);
1213
6
    return kPowersOfFive[exponent];
1214
6
}
1215
1216
6
inline bool scaled_binary_equal(wide::Int256 value, int exponent, wide::Int256 significand) {
1217
6
    if (exponent < 0) {
1218
4
        const int divisor_exponent = -exponent;
1219
4
        if (divisor_exponent >= std::numeric_limits<int64_t>::digits) {
1220
0
            return false;
1221
0
        }
1222
4
        const auto divisor = wide::Int256(1) << divisor_exponent;
1223
4
        return significand % divisor == 0 && value == significand / divisor;
1224
4
    }
1225
2
    constexpr int max_positive_int256_shift = std::numeric_limits<wide::Int256>::digits;
1226
    // wide::Int256 is signed, so shifting 1 by 255 reaches the sign bit.
1227
2
    if (exponent >= max_positive_int256_shift) {
1228
0
        return false;
1229
0
    }
1230
2
    const auto multiplier = wide::Int256(1) << exponent;
1231
2
    return value % multiplier == 0 && value / multiplier == significand;
1232
2
}
1233
1234
4
inline bool floating_equal_integer(const JsonbValue* floating, int128_t integer) {
1235
4
    const double value = floating_value(floating);
1236
4
    int exponent = 0;
1237
4
    std::frexp(value, &exponent);
1238
4
    if (!std::isfinite(value) || std::trunc(value) != value) {
1239
1
        return false;
1240
1
    }
1241
3
    if (exponent >= 128) {
1242
0
        return value == -std::ldexp(1.0, 127) && integer == std::numeric_limits<int128_t>::min();
1243
0
    }
1244
3
    if (exponent <= -1) {
1245
0
        return false;
1246
0
    }
1247
3
    return static_cast<int128_t>(value) == integer;
1248
3
}
1249
1250
6
inline bool floating_equal_decimal(const JsonbValue* floating, const JsonbScaledDecimal& decimal) {
1251
6
    const double value = floating_value(floating);
1252
6
    if (!std::isfinite(value)) {
1253
0
        return false;
1254
0
    }
1255
6
    if (value == 0) {
1256
0
        return decimal.value == 0;
1257
0
    }
1258
1259
6
    int exponent = 0;
1260
6
    const double significand_fraction = std::frexp(value, &exponent);
1261
6
    const double significand_double =
1262
6
            std::ldexp(significand_fraction, std::numeric_limits<double>::digits);
1263
6
    auto significand = wide::Int256(static_cast<int64_t>(significand_double));
1264
6
    exponent -= std::numeric_limits<double>::digits;
1265
1266
6
    const auto five_multiplier = power_of_five(decimal.scale);
1267
6
    if (decimal.value % five_multiplier != 0) {
1268
0
        return false;
1269
0
    }
1270
6
    const auto binary_scaled_decimal = decimal.value / five_multiplier;
1271
6
    return scaled_binary_equal(binary_scaled_decimal, exponent + decimal.scale, significand);
1272
6
}
1273
1274
44
inline bool numeric_equal(const JsonbValue* lhs, const JsonbValue* rhs) {
1275
44
    if (!is_numeric(rhs)) {
1276
2
        return false;
1277
2
    }
1278
1279
42
    if ((lhs->isDouble() || lhs->isFloat()) && rhs->isInt()) {
1280
1
        return floating_equal_integer(lhs, rhs->int_val());
1281
1
    }
1282
1283
41
    if ((rhs->isDouble() || rhs->isFloat()) && lhs->isInt()) {
1284
3
        return floating_equal_integer(rhs, lhs->int_val());
1285
3
    }
1286
1287
38
    if ((lhs->isDouble() || lhs->isFloat()) && rhs->isDecimal()) {
1288
4
        return floating_equal_decimal(lhs, get_scaled_decimal(rhs));
1289
4
    }
1290
1291
34
    if ((rhs->isDouble() || rhs->isFloat()) && lhs->isDecimal()) {
1292
4
        return floating_equal_decimal(rhs, get_scaled_decimal(lhs));
1293
4
    }
1294
1295
30
    if (lhs->isDouble() || lhs->isFloat()) {
1296
0
        return (rhs->isDouble() || rhs->isFloat()) && floating_value(lhs) == floating_value(rhs);
1297
0
    }
1298
1299
30
    if (lhs->isDecimal()) {
1300
6
        const auto lhs_decimal = get_scaled_decimal(lhs);
1301
6
        if (rhs->isDecimal()) {
1302
4
            return scaled_decimal_equal_decimal(lhs_decimal, get_scaled_decimal(rhs));
1303
4
        }
1304
2
        return scaled_decimal_equal_integer(lhs_decimal, rhs->int_val());
1305
6
    }
1306
1307
24
    if (rhs->isDecimal()) {
1308
2
        return scaled_decimal_equal_integer(get_scaled_decimal(rhs), lhs->int_val());
1309
2
    }
1310
1311
22
    return lhs->int_val() == rhs->int_val();
1312
24
}
1313
1314
17
inline bool array_contains_value(const ArrayVal* target_array, const JsonbValue* candidate) {
1315
30
    for (auto it = target_array->begin(); it < target_array->end(); ++it) {
1316
25
        if (it->contains(candidate)) {
1317
12
            return true;
1318
12
        }
1319
25
    }
1320
5
    return false;
1321
17
}
1322
1323
10
inline bool array_contains_array(const ArrayVal* target_array, const ArrayVal* candidate_array) {
1324
21
    for (auto it = candidate_array->begin(); it < candidate_array->end(); ++it) {
1325
15
        if (!array_contains_value(target_array, &*it)) {
1326
4
            return false;
1327
4
        }
1328
15
    }
1329
6
    return true;
1330
10
}
1331
1332
} // namespace jsonb_detail
1333
1334
23
inline const JsonbValue* JsonbDocument::createValue(const char* pb, size_t size) {
1335
23
    if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) {
1336
0
        return nullptr;
1337
0
    }
1338
1339
23
    auto* doc = (JsonbDocument*)pb;
1340
23
    if (doc->header_.ver_ != JSONB_VER) {
1341
0
        return nullptr;
1342
0
    }
1343
1344
23
    const auto* val = (const JsonbValue*)doc->payload_;
1345
23
    if (size != sizeof(JsonbHeader) + val->numPackedBytes()) {
1346
0
        return nullptr;
1347
0
    }
1348
1349
23
    return val;
1350
23
}
1351
1352
34
inline unsigned int JsonbDocument::numPackedBytes() const {
1353
34
    return ((const JsonbValue*)payload_)->numPackedBytes() + sizeof(header_);
1354
34
}
1355
1356
18.8k
inline unsigned int JsonbKeyValue::numPackedBytes() const {
1357
18.8k
    unsigned int ks = keyPackedBytes();
1358
18.8k
    const auto* val = (const JsonbValue*)(((char*)this) + ks);
1359
18.8k
    return ks + val->numPackedBytes();
1360
18.8k
}
1361
1362
// Poor man's "virtual" function JsonbValue::numPackedBytes
1363
94.5k
inline unsigned int JsonbValue::numPackedBytes() const {
1364
94.5k
    switch (type) {
1365
2.82k
    case JsonbType::T_Null:
1366
12.4k
    case JsonbType::T_True:
1367
13.1k
    case JsonbType::T_False: {
1368
13.1k
        return sizeof(type);
1369
12.4k
    }
1370
1371
1.46k
    case JsonbType::T_Int8: {
1372
1.46k
        return sizeof(type) + sizeof(int8_t);
1373
12.4k
    }
1374
412
    case JsonbType::T_Int16: {
1375
412
        return sizeof(type) + sizeof(int16_t);
1376
12.4k
    }
1377
3.54k
    case JsonbType::T_Int32: {
1378
3.54k
        return sizeof(type) + sizeof(int32_t);
1379
12.4k
    }
1380
20.3k
    case JsonbType::T_Int64: {
1381
20.3k
        return sizeof(type) + sizeof(int64_t);
1382
12.4k
    }
1383
10.8k
    case JsonbType::T_Double: {
1384
10.8k
        return sizeof(type) + sizeof(double);
1385
12.4k
    }
1386
44
    case JsonbType::T_Float: {
1387
44
        return sizeof(type) + sizeof(float);
1388
12.4k
    }
1389
13.9k
    case JsonbType::T_Int128: {
1390
13.9k
        return sizeof(type) + sizeof(int128_t);
1391
12.4k
    }
1392
23.2k
    case JsonbType::T_String:
1393
27.6k
    case JsonbType::T_Binary: {
1394
27.6k
        return unpack<JsonbBinaryVal>()->numPackedBytes();
1395
23.2k
    }
1396
1397
2.66k
    case JsonbType::T_Object:
1398
3.01k
    case JsonbType::T_Array: {
1399
3.01k
        return unpack<ContainerVal>()->numPackedBytes();
1400
2.66k
    }
1401
45
    case JsonbType::T_Decimal32: {
1402
45
        return JsonbDecimal32::numPackedBytes();
1403
2.66k
    }
1404
33
    case JsonbType::T_Decimal64: {
1405
33
        return JsonbDecimal64::numPackedBytes();
1406
2.66k
    }
1407
92
    case JsonbType::T_Decimal128: {
1408
92
        return JsonbDecimal128::numPackedBytes();
1409
2.66k
    }
1410
6
    case JsonbType::T_Decimal256: {
1411
6
        return JsonbDecimal256::numPackedBytes();
1412
2.66k
    }
1413
0
    case JsonbType::NUM_TYPES:
1414
0
        break;
1415
94.5k
    }
1416
1417
0
    throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
1418
0
                    static_cast<int32_t>(type));
1419
94.5k
}
1420
1421
11
inline int JsonbValue::numElements() const {
1422
11
    switch (type) {
1423
1
    case JsonbType::T_Int8:
1424
1
    case JsonbType::T_Int16:
1425
1
    case JsonbType::T_Int32:
1426
1
    case JsonbType::T_Int64:
1427
1
    case JsonbType::T_Double:
1428
1
    case JsonbType::T_Float:
1429
1
    case JsonbType::T_Int128:
1430
2
    case JsonbType::T_String:
1431
2
    case JsonbType::T_Binary:
1432
3
    case JsonbType::T_Null:
1433
3
    case JsonbType::T_True:
1434
3
    case JsonbType::T_False:
1435
3
    case JsonbType::T_Decimal32:
1436
3
    case JsonbType::T_Decimal64:
1437
3
    case JsonbType::T_Decimal128:
1438
3
    case JsonbType::T_Decimal256: {
1439
3
        return 1;
1440
3
    }
1441
0
    case JsonbType::T_Object: {
1442
0
        return unpack<ObjectVal>()->numElem();
1443
3
    }
1444
8
    case JsonbType::T_Array: {
1445
8
        return unpack<ArrayVal>()->numElem();
1446
3
    }
1447
0
    case JsonbType::NUM_TYPES:
1448
0
        break;
1449
11
    }
1450
0
    throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
1451
0
                    static_cast<int32_t>(type));
1452
11
}
1453
1454
64
inline bool JsonbValue::contains(const JsonbValue* rhs) const {
1455
64
    switch (type) {
1456
28
    case JsonbType::T_Int8:
1457
28
    case JsonbType::T_Int16:
1458
28
    case JsonbType::T_Int32:
1459
28
    case JsonbType::T_Int64:
1460
29
    case JsonbType::T_Int128:
1461
34
    case JsonbType::T_Double:
1462
34
    case JsonbType::T_Float:
1463
40
    case JsonbType::T_Decimal32:
1464
41
    case JsonbType::T_Decimal64:
1465
44
    case JsonbType::T_Decimal128:
1466
44
    case JsonbType::T_Decimal256: {
1467
44
        return jsonb_detail::numeric_equal(this, rhs);
1468
44
    }
1469
1
    case JsonbType::T_String:
1470
1
    case JsonbType::T_Binary: {
1471
1
        if (rhs->isString() || rhs->isBinary()) {
1472
1
            const auto* str_value1 = unpack<JsonbStringVal>();
1473
1
            const auto* str_value2 = rhs->unpack<JsonbStringVal>();
1474
1
            return str_value1->length() == str_value2->length() &&
1475
1
                   std::memcmp(str_value1->getBlob(), str_value2->getBlob(),
1476
1
                               str_value1->length()) == 0;
1477
1
        }
1478
0
        return false;
1479
1
    }
1480
12
    case JsonbType::T_Array: {
1481
12
        const auto* lhs_array = unpack<ArrayVal>();
1482
12
        if (rhs->isArray()) {
1483
10
            return jsonb_detail::array_contains_array(lhs_array, rhs->unpack<ArrayVal>());
1484
10
        }
1485
2
        return jsonb_detail::array_contains_value(lhs_array, rhs);
1486
12
    }
1487
7
    case JsonbType::T_Object: {
1488
7
        if (rhs->isObject()) {
1489
6
            const auto* obj_value1 = unpack<ObjectVal>();
1490
6
            const auto* obj_value2 = rhs->unpack<ObjectVal>();
1491
9
            for (auto it = obj_value2->begin(); it != obj_value2->end(); ++it) {
1492
                // A key stored as an id (including the empty key sentinel) has klen() == 0 and
1493
                // must be matched by id, not looked up as an empty key name.
1494
6
                const JsonbValue* value = it->klen() == 0
1495
6
                                                  ? obj_value1->find_by_key_id(it->getKeyId())
1496
6
                                                  : obj_value1->find(it->getKeyStr(), it->klen());
1497
6
                if (value == nullptr || !value->contains(it->value())) {
1498
3
                    return false;
1499
3
                }
1500
6
            }
1501
3
            return true;
1502
6
        }
1503
1
        return false;
1504
7
    }
1505
0
    case JsonbType::T_Null: {
1506
0
        return rhs->isNull();
1507
7
    }
1508
0
    case JsonbType::T_True: {
1509
0
        return rhs->isTrue();
1510
7
    }
1511
0
    case JsonbType::T_False: {
1512
0
        return rhs->isFalse();
1513
7
    }
1514
0
    case JsonbType::NUM_TYPES:
1515
0
        break;
1516
64
    }
1517
1518
0
    throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
1519
0
                    static_cast<int32_t>(type));
1520
64
}
1521
1522
167
inline bool JsonbPath::seek(const char* key_path, size_t kp_len) {
1523
167
    while (kp_len > 0 && std::isspace(key_path[kp_len - 1])) {
1524
0
        --kp_len;
1525
0
    }
1526
1527
    //path invalid
1528
167
    if (!key_path || kp_len == 0) {
1529
0
        return false;
1530
0
    }
1531
167
    Stream stream(key_path, kp_len);
1532
167
    stream.skip_whitespace();
1533
167
    if (stream.exhausted() || stream.read() != SCOPE) {
1534
        //path invalid
1535
0
        return false;
1536
0
    }
1537
1538
343
    while (!stream.exhausted()) {
1539
179
        stream.skip_whitespace();
1540
179
        stream.clear_leg_ptr();
1541
179
        stream.clear_leg_len();
1542
179
        stream.set_has_escapes(false);
1543
1544
179
        if (!JsonbPath::parsePath(&stream, this)) {
1545
            //path invalid
1546
3
            return false;
1547
3
        }
1548
179
    }
1549
164
    return true;
1550
167
}
1551
1552
179
inline bool JsonbPath::parsePath(Stream* stream, JsonbPath* path) {
1553
    // $[0]
1554
179
    if (stream->peek() == BEGIN_ARRAY) {
1555
68
        return parse_array(stream, path);
1556
68
    }
1557
    // $.a or $.[0]
1558
111
    else if (stream->peek() == BEGIN_MEMBER) {
1559
        // advance past the .
1560
109
        stream->skip(1);
1561
1562
109
        if (stream->exhausted()) {
1563
2
            return false;
1564
2
        }
1565
1566
        // $.[0]
1567
107
        if (stream->peek() == BEGIN_ARRAY) {
1568
0
            return parse_array(stream, path);
1569
0
        }
1570
        // $.a
1571
107
        else {
1572
107
            return parse_member(stream, path);
1573
107
        }
1574
107
    } else if (stream->peek() == WILDCARD) {
1575
2
        stream->skip(1);
1576
2
        if (stream->exhausted()) {
1577
0
            return false;
1578
0
        }
1579
1580
        // $**
1581
2
        if (stream->peek() == WILDCARD) {
1582
2
            path->_is_supper_wildcard = true;
1583
2
        }
1584
1585
2
        stream->skip(1);
1586
2
        if (stream->exhausted()) {
1587
0
            return false;
1588
0
        }
1589
1590
2
        if (stream->peek() == BEGIN_ARRAY) {
1591
0
            return parse_array(stream, path);
1592
2
        } else if (stream->peek() == BEGIN_MEMBER) {
1593
            // advance past the .
1594
2
            stream->skip(1);
1595
1596
2
            if (stream->exhausted()) {
1597
0
                return false;
1598
0
            }
1599
1600
            // $.[0]
1601
2
            if (stream->peek() == BEGIN_ARRAY) {
1602
0
                return parse_array(stream, path);
1603
0
            }
1604
            // $.a
1605
2
            else {
1606
2
                return parse_member(stream, path);
1607
2
            }
1608
2
        }
1609
0
        return false;
1610
2
    } else {
1611
0
        return false; //invalid json path
1612
0
    }
1613
179
}
1614
1615
68
inline bool JsonbPath::parse_array(Stream* stream, JsonbPath* path) {
1616
68
    assert(stream->peek() == BEGIN_ARRAY);
1617
68
    stream->skip(1);
1618
68
    if (stream->exhausted()) {
1619
0
        return false;
1620
0
    }
1621
1622
68
    if (stream->peek() == WILDCARD) {
1623
        // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1624
        // using const_cast is acceptable.
1625
2
        stream->set_leg_ptr(const_cast<char*>(stream->position()));
1626
2
        stream->add_leg_len();
1627
2
        stream->skip(1);
1628
2
        if (stream->exhausted()) {
1629
0
            return false;
1630
0
        }
1631
1632
2
        if (stream->peek() == END_ARRAY) {
1633
2
            std::unique_ptr<leg_info> leg(
1634
2
                    new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, ARRAY_CODE));
1635
2
            leg->is_wildcard = true;
1636
2
            path->add_leg_to_leg_vector(std::move(leg));
1637
2
            stream->skip(1);
1638
2
            path->_is_wildcard = true;
1639
2
            return true;
1640
2
        } else {
1641
0
            return false;
1642
0
        }
1643
2
    }
1644
1645
    // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1646
    // using const_cast is acceptable.
1647
66
    stream->set_leg_ptr(const_cast<char*>(stream->position()));
1648
1649
132
    for (; !stream->exhausted() && stream->peek() != END_ARRAY; stream->advance()) {
1650
66
        stream->add_leg_len();
1651
66
    }
1652
1653
66
    if (stream->exhausted() || stream->peek() != END_ARRAY) {
1654
0
        return false;
1655
66
    } else {
1656
66
        stream->skip(1);
1657
66
    }
1658
1659
    //parse array index to int
1660
1661
66
    std::string_view idx_string(stream->get_leg_ptr(), stream->get_leg_len());
1662
66
    int index = 0;
1663
1664
66
    if (stream->get_leg_len() >= 4 &&
1665
66
        std::equal(LAST, LAST + 4, stream->get_leg_ptr(),
1666
0
                   [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); })) {
1667
0
        auto pos = idx_string.find(MINUS);
1668
1669
0
        if (pos != std::string::npos) {
1670
0
            for (size_t i = 4; i < pos; ++i) {
1671
0
                if (std::isspace(idx_string[i])) {
1672
0
                    continue;
1673
0
                } else {
1674
                    // leading zeroes are not allowed
1675
0
                    LOG(WARNING) << "Non-space char in idx_string: '" << idx_string << "'";
1676
0
                    return false;
1677
0
                }
1678
0
            }
1679
0
            idx_string = idx_string.substr(pos + 1);
1680
0
            idx_string = trim(idx_string);
1681
1682
0
            auto result = std::from_chars(idx_string.data(), idx_string.data() + idx_string.size(),
1683
0
                                          index);
1684
0
            if (result.ec != std::errc()) {
1685
0
                LOG(WARNING) << "Invalid index in JSON path: '" << idx_string << "'";
1686
0
                return false;
1687
0
            }
1688
1689
0
        } else if (stream->get_leg_len() > 4) {
1690
0
            return false;
1691
0
        }
1692
1693
0
        std::unique_ptr<leg_info> leg(new leg_info(nullptr, 0, -index - 1, ARRAY_CODE));
1694
0
        path->add_leg_to_leg_vector(std::move(leg));
1695
1696
0
        return true;
1697
0
    }
1698
1699
66
    auto result = std::from_chars(idx_string.data(), idx_string.data() + idx_string.size(), index);
1700
1701
66
    if (result.ec != std::errc()) {
1702
0
        return false;
1703
0
    }
1704
1705
66
    std::unique_ptr<leg_info> leg(new leg_info(nullptr, 0, index, ARRAY_CODE));
1706
66
    path->add_leg_to_leg_vector(std::move(leg));
1707
1708
66
    return true;
1709
66
}
1710
1711
109
inline bool JsonbPath::parse_member(Stream* stream, JsonbPath* path) {
1712
109
    if (stream->exhausted()) {
1713
0
        return false;
1714
0
    }
1715
1716
109
    if (stream->peek() == WILDCARD) {
1717
        // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1718
        // using const_cast is acceptable.
1719
6
        stream->set_leg_ptr(const_cast<char*>(stream->position()));
1720
6
        stream->add_leg_len();
1721
6
        stream->skip(1);
1722
6
        std::unique_ptr<leg_info> leg(
1723
6
                new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, MEMBER_CODE));
1724
6
        leg->is_wildcard = true;
1725
6
        path->add_leg_to_leg_vector(std::move(leg));
1726
6
        path->_is_wildcard = true;
1727
6
        return true;
1728
6
    }
1729
1730
    // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1731
    // using const_cast is acceptable.
1732
103
    stream->set_leg_ptr(const_cast<char*>(stream->position()));
1733
1734
103
    const char* left_quotation_marks = nullptr;
1735
103
    const char* right_quotation_marks = nullptr;
1736
1737
323
    for (; !stream->exhausted(); stream->advance()) {
1738
        // Only accept space characters quoted by double quotes.
1739
266
        if (std::isspace(stream->peek()) && left_quotation_marks == nullptr) {
1740
0
            return false;
1741
266
        } else if (stream->peek() == ESCAPE) {
1742
12
            stream->add_leg_len();
1743
12
            stream->skip(1);
1744
12
            stream->add_leg_len();
1745
12
            stream->set_has_escapes(true);
1746
12
            if (stream->exhausted()) {
1747
0
                return false;
1748
0
            }
1749
12
            continue;
1750
254
        } else if (stream->peek() == DOUBLE_QUOTE) {
1751
70
            if (left_quotation_marks == nullptr) {
1752
35
                left_quotation_marks = stream->position();
1753
                // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1754
                // using const_cast is acceptable.
1755
35
                stream->set_leg_ptr(const_cast<char*>(++left_quotation_marks));
1756
35
                continue;
1757
35
            } else {
1758
35
                right_quotation_marks = stream->position();
1759
35
                stream->skip(1);
1760
35
                break;
1761
35
            }
1762
184
        } else if (stream->peek() == BEGIN_MEMBER || stream->peek() == BEGIN_ARRAY) {
1763
17
            if (left_quotation_marks == nullptr) {
1764
11
                break;
1765
11
            }
1766
17
        }
1767
1768
173
        stream->add_leg_len();
1769
173
    }
1770
1771
    // An empty member name is only valid when it is written explicitly as `""`.
1772
103
    if ((left_quotation_marks != nullptr && right_quotation_marks == nullptr) ||
1773
103
        stream->get_leg_ptr() == nullptr ||
1774
103
        (left_quotation_marks == nullptr && stream->get_leg_len() == 0)) {
1775
1
        return false; //invalid json path
1776
1
    }
1777
1778
102
    if (stream->get_has_escapes()) {
1779
4
        stream->remove_escapes();
1780
4
    }
1781
1782
102
    std::unique_ptr<leg_info> leg(
1783
102
            new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, MEMBER_CODE));
1784
102
    path->add_leg_to_leg_vector(std::move(leg));
1785
1786
102
    return true;
1787
103
}
1788
1789
static_assert(is_pod_v<JsonbDocument>, "JsonbDocument must be standard layout and trivial");
1790
static_assert(is_pod_v<JsonbValue>, "JsonbValue must be standard layout and trivial");
1791
static_assert(is_pod_v<JsonbDecimal32>, "JsonbDecimal32 must be standard layout and trivial");
1792
static_assert(is_pod_v<JsonbDecimal64>, "JsonbDecimal64 must be standard layout and trivial");
1793
static_assert(is_pod_v<JsonbDecimal128>, "JsonbDecimal128 must be standard layout and trivial");
1794
static_assert(is_pod_v<JsonbDecimal256>, "JsonbDecimal256 must be standard layout and trivial");
1795
static_assert(is_pod_v<JsonbInt8Val>, "JsonbInt8Val must be standard layout and trivial");
1796
static_assert(is_pod_v<JsonbInt32Val>, "JsonbInt32Val must be standard layout and trivial");
1797
static_assert(is_pod_v<JsonbInt64Val>, "JsonbInt64Val must be standard layout and trivial");
1798
static_assert(is_pod_v<JsonbInt128Val>, "JsonbInt128Val must be standard layout and trivial");
1799
static_assert(is_pod_v<JsonbDoubleVal>, "JsonbDoubleVal must be standard layout and trivial");
1800
static_assert(is_pod_v<JsonbFloatVal>, "JsonbFloatVal must be standard layout and trivial");
1801
static_assert(is_pod_v<JsonbBinaryVal>, "JsonbBinaryVal must be standard layout and trivial");
1802
static_assert(is_pod_v<ContainerVal>, "ContainerVal must be standard layout and trivial");
1803
1804
#define ASSERT_DECIMAL_LAYOUT(type)                \
1805
    static_assert(offsetof(type, precision) == 0); \
1806
    static_assert(offsetof(type, scale) == 4);     \
1807
    static_assert(offsetof(type, value) == 8);
1808
1809
ASSERT_DECIMAL_LAYOUT(JsonbDecimal32)
1810
ASSERT_DECIMAL_LAYOUT(JsonbDecimal64)
1811
ASSERT_DECIMAL_LAYOUT(JsonbDecimal128)
1812
ASSERT_DECIMAL_LAYOUT(JsonbDecimal256)
1813
1814
#define ASSERT_NUMERIC_LAYOUT(type) static_assert(offsetof(type, num) == 0);
1815
1816
ASSERT_NUMERIC_LAYOUT(JsonbInt8Val)
1817
ASSERT_NUMERIC_LAYOUT(JsonbInt32Val)
1818
ASSERT_NUMERIC_LAYOUT(JsonbInt64Val)
1819
ASSERT_NUMERIC_LAYOUT(JsonbInt128Val)
1820
ASSERT_NUMERIC_LAYOUT(JsonbDoubleVal)
1821
1822
static_assert(offsetof(JsonbBinaryVal, size) == 0);
1823
static_assert(offsetof(JsonbBinaryVal, payload) == 4);
1824
1825
static_assert(offsetof(ContainerVal, size) == 0);
1826
static_assert(offsetof(ContainerVal, payload) == 4);
1827
1828
#pragma pack(pop)
1829
#if defined(__clang__)
1830
#pragma clang diagnostic pop
1831
#endif
1832
} // namespace doris
1833
1834
#endif // JSONB_JSONBDOCUMENT_H