Coverage Report

Created: 2026-10-17 01:05

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
209k
#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
121
    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
120
    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
2.40k
    size_t remaining() const {
273
2.40k
        assert(m_position <= m_end);
274
2.40k
        return m_end - m_position;
275
2.40k
    }
276
277
    /// Tells if the stream has been exhausted.
278
2.21k
    bool exhausted() const { return remaining() == 0; }
279
280
    /// Reads the next byte from the stream and moves the position forward.
281
113
    char read() {
282
113
        assert(!exhausted());
283
113
        return *m_position++;
284
113
    }
285
286
    /// Reads the next byte from the stream without moving the position forward.
287
1.21k
    char peek() const {
288
1.21k
        assert(!exhausted());
289
1.21k
        return *m_position;
290
1.21k
    }
291
292
    /// Moves the position to the next non-whitespace character.
293
420
    void skip_whitespace() {
294
420
        m_position = std::find_if_not(m_position, m_end, [](char c) { return std::isspace(c); });
295
420
    }
296
297
    /// Moves the position n bytes forward.
298
193
    void skip(size_t n) {
299
193
        assert(remaining() >= n);
300
193
        m_position += n;
301
193
        skip_whitespace();
302
193
    }
303
304
188
    void advance() { m_position++; }
305
306
239
    void clear_leg_ptr() { leg_ptr = nullptr; }
307
308
125
    void set_leg_ptr(char* ptr) {
309
125
        clear_leg_ptr();
310
125
        leg_ptr = ptr;
311
125
    }
312
313
167
    char* get_leg_ptr() { return leg_ptr; }
314
315
122
    void clear_leg_len() { leg_len = 0; }
316
317
273
    void add_leg_len() { leg_len++; }
318
319
236
    unsigned int get_leg_len() const { return leg_len; }
320
321
11
    void remove_escapes() {
322
11
        unsigned int new_len = 0;
323
82
        for (unsigned int i = 0; i < leg_len; ++i) {
324
72
            if (leg_ptr[i] != ESCAPE) {
325
43
                leg_ptr[new_len++] = leg_ptr[i];
326
43
                continue;
327
43
            }
328
329
29
            ++i;
330
29
            if (i >= leg_len) {
331
1
                break;
332
1
            }
333
334
28
            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
6
            default:
379
6
                leg_ptr[new_len++] = leg_ptr[i];
380
6
                break;
381
28
            }
382
28
        }
383
11
        leg_ptr[new_len] = '\0';
384
11
        leg_len = new_len;
385
11
    }
386
387
125
    void set_has_escapes(bool has) { has_escapes = has; }
388
389
53
    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
    // NOLINTNEXTLINE(readability-non-const-parameter): str is an output parameter.
422
7
    bool to_string(std::string* str) const {
423
7
        if (type == MEMBER_CODE) {
424
7
            str->push_back(BEGIN_MEMBER);
425
7
            bool contains_space = false;
426
7
            std::string tmp;
427
54
            for (auto* it = leg_ptr; it != (leg_ptr + leg_len); ++it) {
428
47
                auto c = static_cast<unsigned char>(*it);
429
47
                if (std::isspace(c)) {
430
9
                    contains_space = true;
431
9
                }
432
433
47
                switch (*it) {
434
2
                case '"':
435
2
                    tmp.append("\\\"");
436
2
                    break;
437
2
                case ESCAPE:
438
2
                    tmp.append("\\\\");
439
2
                    break;
440
2
                case '\b':
441
2
                    tmp.append("\\b");
442
2
                    break;
443
2
                case '\f':
444
2
                    tmp.append("\\f");
445
2
                    break;
446
3
                case '\n':
447
3
                    tmp.append("\\n");
448
3
                    break;
449
2
                case '\r':
450
2
                    tmp.append("\\r");
451
2
                    break;
452
2
                case '\t':
453
2
                    tmp.append("\\t");
454
2
                    break;
455
32
                default:
456
32
                    if (c < 0x20) {
457
6
                        constexpr char hex[] = "0123456789abcdef";
458
6
                        tmp.append("\\u00");
459
6
                        tmp.push_back(hex[c >> 4]);
460
6
                        tmp.push_back(hex[c & 0x0F]);
461
26
                    } else {
462
26
                        tmp.push_back(*it);
463
26
                    }
464
32
                    break;
465
47
                }
466
47
            }
467
7
            if (contains_space) {
468
5
                str->push_back(DOUBLE_QUOTE);
469
5
            }
470
7
            str->append(tmp);
471
7
            if (contains_space) {
472
5
                str->push_back(DOUBLE_QUOTE);
473
5
            }
474
7
            return true;
475
7
        } else if (type == ARRAY_CODE) {
476
0
            str->push_back(BEGIN_ARRAY);
477
0
            std::string int_str = std::to_string(array_index);
478
0
            str->append(int_str);
479
0
            str->push_back(END_ARRAY);
480
0
            return true;
481
0
        } else {
482
0
            return false;
483
0
        }
484
7
    }
485
};
486
487
class JsonbPath {
488
public:
489
    // parse json path
490
    static bool parsePath(Stream* stream, JsonbPath* path);
491
492
    static bool parse_array(Stream* stream, JsonbPath* path);
493
    static bool parse_member(Stream* stream, JsonbPath* path);
494
495
    //return true if json path valid else return false
496
    bool seek(const char* string, size_t length);
497
498
122
    void add_leg_to_leg_vector(std::unique_ptr<leg_info> leg) {
499
122
        leg_vector.emplace_back(leg.release());
500
122
    }
501
502
0
    void pop_leg_from_leg_vector() { leg_vector.pop_back(); }
503
504
    // NOLINTNEXTLINE(readability-non-const-parameter): res is an output parameter.
505
3
    bool to_string(std::string* res) const {
506
3
        res->push_back(SCOPE);
507
5
        for (const auto& leg : leg_vector) {
508
5
            auto valid = leg->to_string(res);
509
5
            if (!valid) {
510
0
                return false;
511
0
            }
512
5
        }
513
3
        return true;
514
3
    }
515
516
247
    size_t get_leg_vector_size() const { return leg_vector.size(); }
517
518
436
    leg_info* get_leg_from_leg_vector(size_t i) const { return leg_vector[i].get(); }
519
520
9
    bool is_wildcard() const { return _is_wildcard; }
521
118
    bool is_supper_wildcard() const { return _is_supper_wildcard; }
522
523
9
    void clean() { leg_vector.clear(); }
524
525
private:
526
    std::vector<std::unique_ptr<leg_info>> leg_vector;
527
    bool _is_wildcard = false;        // whether the path is a wildcard path
528
    bool _is_supper_wildcard = false; // supper wildcard likes '$**.a' or '$**[1]'
529
};
530
531
/*
532
 * JsonbFwdIteratorT implements JSONB's iterator template.
533
 *
534
 * Note: it is an FORWARD iterator only due to the design of JSONB format.
535
 */
536
template <class Iter_Type, class Cont_Type>
537
class JsonbFwdIteratorT {
538
public:
539
    using iterator = Iter_Type;
540
    using pointer = typename std::iterator_traits<Iter_Type>::pointer;
541
    using reference = typename std::iterator_traits<Iter_Type>::reference;
542
543
    explicit JsonbFwdIteratorT() : current_(nullptr) {}
544
22.4k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEC2ERKS3_
Line
Count
Source
544
22.0k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEC2ERKS3_
Line
Count
Source
544
371
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
545
546
    // allow non-const to const iterator conversion (same container type)
547
    template <class Iter_Ty>
548
    JsonbFwdIteratorT(const JsonbFwdIteratorT<Iter_Ty, Cont_Type>& rhs) : current_(rhs.base()) {}
549
550
22.9k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEeqERKS5_
Line
Count
Source
550
21.2k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEeqERKS5_
Line
Count
Source
550
1.73k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
551
552
21.5k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEneERKS5_
Line
Count
Source
552
19.9k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEneERKS5_
Line
Count
Source
552
1.59k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
553
554
2.96k
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEltERKS5_
Line
Count
Source
554
55
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEltERKS5_
Line
Count
Source
554
2.90k
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
555
556
    bool operator>(const JsonbFwdIteratorT& rhs) const { return !operator<(rhs); }
557
558
19.4k
    JsonbFwdIteratorT& operator++() {
559
19.4k
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
560
19.4k
        return *this;
561
19.4k
    }
_ZN5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEppEv
Line
Count
Source
558
754
    JsonbFwdIteratorT& operator++() {
559
754
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
560
754
        return *this;
561
754
    }
_ZN5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEppEv
Line
Count
Source
558
18.7k
    JsonbFwdIteratorT& operator++() {
559
18.7k
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
560
18.7k
        return *this;
561
18.7k
    }
562
563
    JsonbFwdIteratorT operator++(int) {
564
        auto tmp = *this;
565
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
566
        return tmp;
567
    }
568
569
728
    explicit operator pointer() { return current_; }
570
571
60
    reference operator*() const { return *current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEdeEv
Line
Count
Source
571
17
    reference operator*() const { return *current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEdeEv
Line
Count
Source
571
43
    reference operator*() const { return *current_; }
572
573
33.2k
    pointer operator->() const { return current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEptEv
Line
Count
Source
573
33.2k
    pointer operator->() const { return current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEptEv
Line
Count
Source
573
28
    pointer operator->() const { return current_; }
574
575
    iterator base() const { return current_; }
576
577
private:
578
    iterator current_;
579
};
580
using JsonbTypeUnder = std::underlying_type_t<JsonbType>;
581
582
#if defined(__clang__)
583
#pragma clang diagnostic push
584
#pragma clang diagnostic ignored "-Wzero-length-array"
585
#endif
586
#pragma pack(push, 1)
587
588
/*
589
 * JsonbDocument is the main object that accesses and queries JSONB packed
590
 * bytes. NOTE: JsonbDocument only allows object container as the top level
591
 * JSONB value. However, you can use the static method "createValue" to get any
592
 * JsonbValue object from the packed bytes.
593
 *
594
 * JsonbDocument object also dereferences to an object container value
595
 * (ObjectVal) once JSONB is loaded.
596
 *
597
 * ** Load **
598
 * JsonbDocument is usable after loading packed bytes (memory location) into
599
 * the object. We only need the header and first few bytes of the payload after
600
 * header to verify the JSONB.
601
 *
602
 * Note: creating an JsonbDocument (through createDocument) does not allocate
603
 * any memory. The document object is an efficient wrapper on the packed bytes
604
 * which is accessed directly.
605
 *
606
 * ** Query **
607
 * Query is through dereferencing into ObjectVal.
608
 */
609
class JsonbDocument {
610
public:
611
    // create an JsonbDocument object from JSONB packed bytes
612
    [[nodiscard]] static Status checkAndCreateDocument(const char* pb, size_t size,
613
                                                       const JsonbDocument** doc);
614
615
    // create an JsonbValue from JSONB packed bytes
616
    static const JsonbValue* createValue(const char* pb, size_t size);
617
618
0
    uint8_t version() const { return header_.ver_; }
619
620
27.2k
    const JsonbValue* getValue() const { return ((const JsonbValue*)payload_); }
621
622
    unsigned int numPackedBytes() const;
623
624
    const ObjectVal* operator->() const;
625
626
private:
627
    /*
628
   * JsonbHeader class defines JSONB header (internal to JsonbDocument).
629
   *
630
   * Currently it only contains version information (1-byte). We may expand the
631
   * header to include checksum of the JSONB binary for more security.
632
   */
633
    struct JsonbHeader {
634
        uint8_t ver_;
635
    } header_;
636
637
    char payload_[0];
638
};
639
640
/*
641
 * JsonbKeyValue class defines JSONB key type, as described below.
642
 *
643
 * key ::=
644
 *   0x00 int8    //1-byte dictionary id
645
 * | int8 (byte*) //int8 (>0) is the size of the key string
646
 *
647
 * value ::= primitive_value | container
648
 *
649
 * JsonbKeyValue can be either an id mapping to the key string in an external
650
 * dictionary, or it is the original key string. Whether to read an id or a
651
 * string is decided by the first byte (size).
652
 *
653
 * Note: a key object must be followed by a value object. Therefore, a key
654
 * object implicitly refers to a key-value pair, and you can get the value
655
 * object right after the key object. The function numPackedBytes hence
656
 * indicates the total size of the key-value pair, so that we will be able go
657
 * to next pair from the key.
658
 *
659
 * ** Dictionary size **
660
 * By default, the dictionary size is 255 (1-byte). Users can define
661
 * "USE_LARGE_DICT" to increase the dictionary size to 655535 (2-byte).
662
 */
663
class JsonbKeyValue {
664
public:
665
    // now we use sMaxKeyId to represent an empty key
666
    static const int sMaxKeyId = 65535;
667
    using keyid_type = uint16_t;
668
669
    static const uint8_t sMaxKeyLen = 64;
670
671
    // size of the key. 0 indicates it is stored as id
672
3.50k
    uint8_t klen() const { return size; }
673
674
    // get the key string. Note the string may not be null terminated.
675
1.81k
    const char* getKeyStr() const { return key.str_; }
676
677
9.33k
    keyid_type getKeyId() const { return key.id_; }
678
679
37.6k
    unsigned int keyPackedBytes() const {
680
37.6k
        return size ? (sizeof(size) + size) : (sizeof(size) + sizeof(keyid_type));
681
37.6k
    }
682
683
18.8k
    const JsonbValue* value() const {
684
18.8k
        return (const JsonbValue*)(((char*)this) + keyPackedBytes());
685
18.8k
    }
686
687
    // size of the total packed bytes (key+value)
688
    unsigned int numPackedBytes() const;
689
690
    uint8_t size;
691
692
    union key_ {
693
        keyid_type id_;
694
        char str_[1];
695
    } key;
696
};
697
698
struct JsonbFindResult {
699
    const JsonbValue* value = nullptr;   // found value
700
    std::unique_ptr<JsonbWriter> writer; // writer to write the value
701
    bool is_wildcard = false;            // whether the path is a wildcard path
702
};
703
704
/*
705
 * JsonbValue is the base class of all JSONB types. It contains only one member
706
 * variable - type info, which can be retrieved by member functions is[Type]()
707
 * or type().
708
 */
709
struct JsonbValue {
710
    static const uint32_t sMaxValueLen = 1 << 24; // 16M
711
712
4.33k
    bool isNull() const { return (type == JsonbType::T_Null); }
713
23
    bool isTrue() const { return (type == JsonbType::T_True); }
714
2
    bool isFalse() const { return (type == JsonbType::T_False); }
715
57
    bool isInt() const { return isInt8() || isInt16() || isInt32() || isInt64() || isInt128(); }
716
57
    bool isInt8() const { return (type == JsonbType::T_Int8); }
717
30
    bool isInt16() const { return (type == JsonbType::T_Int16); }
718
28
    bool isInt32() const { return (type == JsonbType::T_Int32); }
719
32
    bool isInt64() const { return (type == JsonbType::T_Int64); }
720
205
    bool isDouble() const { return (type == JsonbType::T_Double); }
721
168
    bool isFloat() const { return (type == JsonbType::T_Float); }
722
103
    bool isString() const { return (type == JsonbType::T_String); }
723
1.10k
    bool isBinary() const { return (type == JsonbType::T_Binary); }
724
109
    bool isObject() const { return (type == JsonbType::T_Object); }
725
40
    bool isArray() const { return (type == JsonbType::T_Array); }
726
31
    bool isInt128() const { return (type == JsonbType::T_Int128); }
727
80
    bool isDecimal() const {
728
80
        return (type == JsonbType::T_Decimal32 || type == JsonbType::T_Decimal64 ||
729
80
                type == JsonbType::T_Decimal128 || type == JsonbType::T_Decimal256);
730
80
    }
731
1
    bool isDecimal32() const { return (type == JsonbType::T_Decimal32); }
732
1
    bool isDecimal64() const { return (type == JsonbType::T_Decimal64); }
733
1
    bool isDecimal128() const { return (type == JsonbType::T_Decimal128); }
734
1
    bool isDecimal256() const { return (type == JsonbType::T_Decimal256); }
735
736
11
    PrimitiveType get_primitive_type() const { return get_primitive_type_from_json_type(type); }
737
738
0
    const char* typeName() const {
739
0
        switch (type) {
740
0
        case JsonbType::T_Null:
741
0
            return "null";
742
0
        case JsonbType::T_True:
743
0
        case JsonbType::T_False:
744
0
            return "bool";
745
0
        case JsonbType::T_Int8:
746
0
        case JsonbType::T_Int16:
747
0
        case JsonbType::T_Int32:
748
0
            return "int";
749
0
        case JsonbType::T_Int64:
750
0
            return "bigint";
751
0
        case JsonbType::T_Int128:
752
0
            return "largeint";
753
0
        case JsonbType::T_Double:
754
0
            return "double";
755
0
        case JsonbType::T_Float:
756
0
            return "float";
757
0
        case JsonbType::T_String:
758
0
            return "string";
759
0
        case JsonbType::T_Binary:
760
0
            return "binary";
761
0
        case JsonbType::T_Object:
762
0
            return "object";
763
0
        case JsonbType::T_Array:
764
0
            return "array";
765
0
        case JsonbType::T_Decimal32:
766
0
            return "Decimal32";
767
0
        case JsonbType::T_Decimal64:
768
0
            return "Decimal64";
769
0
        case JsonbType::T_Decimal128:
770
0
            return "Decimal128";
771
0
        case JsonbType::T_Decimal256:
772
0
            return "Decimal256";
773
0
        default:
774
0
            return "unknown";
775
0
        }
776
0
    }
777
778
    // size of the total packed bytes
779
    unsigned int numPackedBytes() const;
780
781
    // size of the value in bytes
782
    unsigned int size() const;
783
784
    //Get the number of jsonbvalue elements
785
    int numElements() const;
786
787
    //Whether to include the jsonbvalue rhs
788
    bool contains(const JsonbValue* rhs) const;
789
790
    // find the JSONB value by JsonbPath
791
    JsonbFindResult findValue(JsonbPath& path) const;
792
    friend class JsonbDocument;
793
794
    JsonbType type; // type info
795
796
    char payload[0]; // payload, which is the packed bytes of the value
797
798
    /**
799
    * @brief Unpacks the underlying Jsonb binary content as a pointer to type `T`.
800
    *
801
    * @tparam T A POD (Plain Old Data) type that must satisfy the `JsonbPodType` concept.
802
    *           This ensures that `T` is trivially copyable, standard-layout, and safe to
803
    *           reinterpret from raw bytes without invoking undefined behavior.
804
    *
805
    * @return A pointer to a `const T` object, interpreted from the internal buffer.
806
    *
807
    * @note The caller must ensure that the current JsonbValue actually contains data
808
    *       compatible with type `T`, otherwise the result is undefined.
809
    */
810
    template <JsonbPodType T>
811
55.9k
    const T* unpack() const {
812
55.9k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
55.9k
        return reinterpret_cast<const T*>(payload);
814
55.9k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_9ObjectValEEEPKT_v
Line
Count
Source
811
20.6k
    const T* unpack() const {
812
20.6k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
20.6k
        return reinterpret_cast<const T*>(payload);
814
20.6k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIaEEEEPKT_v
Line
Count
Source
811
1.23k
    const T* unpack() const {
812
1.23k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
1.23k
        return reinterpret_cast<const T*>(payload);
814
1.23k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIsEEEEPKT_v
Line
Count
Source
811
364
    const T* unpack() const {
812
364
        static_assert(is_pod_v<T>, "T must be a POD type");
813
364
        return reinterpret_cast<const T*>(payload);
814
364
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIiEEEEPKT_v
Line
Count
Source
811
3.48k
    const T* unpack() const {
812
3.48k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
3.48k
        return reinterpret_cast<const T*>(payload);
814
3.48k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIlEEEEPKT_v
Line
Count
Source
811
1.96k
    const T* unpack() const {
812
1.96k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
1.96k
        return reinterpret_cast<const T*>(payload);
814
1.96k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTInEEEEPKT_v
Line
Count
Source
811
4.17k
    const T* unpack() const {
812
4.17k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
4.17k
        return reinterpret_cast<const T*>(payload);
814
4.17k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIdEEEEPKT_v
Line
Count
Source
811
190
    const T* unpack() const {
812
190
        static_assert(is_pod_v<T>, "T must be a POD type");
813
190
        return reinterpret_cast<const T*>(payload);
814
190
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_10NumberValTIfEEEEPKT_v
Line
Count
Source
811
28
    const T* unpack() const {
812
28
        static_assert(is_pod_v<T>, "T must be a POD type");
813
28
        return reinterpret_cast<const T*>(payload);
814
28
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_7DecimalIiEEEEEEPKT_v
Line
Count
Source
811
26
    const T* unpack() const {
812
26
        static_assert(is_pod_v<T>, "T must be a POD type");
813
26
        return reinterpret_cast<const T*>(payload);
814
26
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_7DecimalIlEEEEEEPKT_v
Line
Count
Source
811
16
    const T* unpack() const {
812
16
        static_assert(is_pod_v<T>, "T must be a POD type");
813
16
        return reinterpret_cast<const T*>(payload);
814
16
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_12Decimal128V3EEEEEPKT_v
Line
Count
Source
811
31
    const T* unpack() const {
812
31
        static_assert(is_pod_v<T>, "T must be a POD type");
813
31
        return reinterpret_cast<const T*>(payload);
814
31
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_15JsonbDecimalValINS_7DecimalIN4wide7integerILm256EiEEEEEEEEPKT_v
Line
Count
Source
811
13
    const T* unpack() const {
812
13
        static_assert(is_pod_v<T>, "T must be a POD type");
813
13
        return reinterpret_cast<const T*>(payload);
814
13
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_14JsonbBinaryValEEEPKT_v
Line
Count
Source
811
20.0k
    const T* unpack() const {
812
20.0k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
20.0k
        return reinterpret_cast<const T*>(payload);
814
20.0k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_12ContainerValEEEPKT_v
Line
Count
Source
811
2.86k
    const T* unpack() const {
812
2.86k
        static_assert(is_pod_v<T>, "T must be a POD type");
813
2.86k
        return reinterpret_cast<const T*>(payload);
814
2.86k
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_8ArrayValEEEPKT_v
Line
Count
Source
811
217
    const T* unpack() const {
812
217
        static_assert(is_pod_v<T>, "T must be a POD type");
813
217
        return reinterpret_cast<const T*>(payload);
814
217
    }
_ZNK5doris10JsonbValue6unpackITkNS_12JsonbPodTypeENS_14JsonbStringValEEEPKT_v
Line
Count
Source
811
619
    const T* unpack() const {
812
619
        static_assert(is_pod_v<T>, "T must be a POD type");
813
619
        return reinterpret_cast<const T*>(payload);
814
619
    }
815
816
    // /**
817
    // * @brief Unpacks the underlying Jsonb binary content as a pointer to type `T`.
818
    // *
819
    // * @tparam T A POD (Plain Old Data) type that must satisfy the `JsonbPodType` concept.
820
    // *           This ensures that `T` is trivially copyable, standard-layout, and safe to
821
    // *           reinterpret from raw bytes without invoking undefined behavior.
822
    // *
823
    // * @return A pointer to a `T` object, interpreted from the internal buffer.
824
    // *
825
    // * @note The caller must ensure that the current JsonbValue actually contains data
826
    // *       compatible with type `T`, otherwise the result is undefined.
827
    // */
828
    // template <JsonbPodType T>
829
    // T* unpack() {
830
    //     static_assert(is_pod_v<T>, "T must be a POD type");
831
    //     return reinterpret_cast<T*>(payload);
832
    // }
833
834
    int128_t int_val() const;
835
};
836
837
// inline ObjectVal* JsonbDocument::operator->() {
838
//     return (((JsonbValue*)payload_)->unpack<ObjectVal>());
839
// }
840
841
19.2k
inline const ObjectVal* JsonbDocument::operator->() const {
842
19.2k
    return (((const JsonbValue*)payload_)->unpack<ObjectVal>());
843
19.2k
}
844
845
/*
846
 * NumerValT is the template class (derived from JsonbValue) of all number
847
 * types (integers and double).
848
 */
849
template <typename T>
850
    requires std::is_integral_v<T> || std::is_floating_point_v<T>
851
struct NumberValT {
852
public:
853
11.4k
    T val() const { return num; }
_ZNK5doris10NumberValTIaE3valEv
Line
Count
Source
853
1.23k
    T val() const { return num; }
_ZNK5doris10NumberValTIsE3valEv
Line
Count
Source
853
364
    T val() const { return num; }
_ZNK5doris10NumberValTIiE3valEv
Line
Count
Source
853
3.48k
    T val() const { return num; }
_ZNK5doris10NumberValTIlE3valEv
Line
Count
Source
853
1.96k
    T val() const { return num; }
_ZNK5doris10NumberValTInE3valEv
Line
Count
Source
853
4.17k
    T val() const { return num; }
_ZNK5doris10NumberValTIdE3valEv
Line
Count
Source
853
190
    T val() const { return num; }
_ZNK5doris10NumberValTIfE3valEv
Line
Count
Source
853
28
    T val() const { return num; }
854
855
    static unsigned int numPackedBytes() { return sizeof(JsonbValue) + sizeof(T); }
856
857
    T num;
858
};
859
860
56
inline int128_t JsonbValue::int_val() const {
861
56
    switch (type) {
862
48
    case JsonbType::T_Int8:
863
48
        return unpack<JsonbInt8Val>()->val();
864
1
    case JsonbType::T_Int16:
865
1
        return unpack<JsonbInt16Val>()->val();
866
0
    case JsonbType::T_Int32:
867
0
        return unpack<JsonbInt32Val>()->val();
868
4
    case JsonbType::T_Int64:
869
4
        return unpack<JsonbInt64Val>()->val();
870
3
    case JsonbType::T_Int128:
871
3
        return unpack<JsonbInt128Val>()->val();
872
0
    default:
873
0
        throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
874
0
                        static_cast<int32_t>(type));
875
56
    }
876
56
}
877
878
template <JsonbDecimalType T>
879
struct JsonbDecimalVal {
880
public:
881
    using NativeType = typename T::NativeType;
882
883
    // get the decimal value
884
54
    NativeType val() const {
885
        // to avoid memory alignment issues, we use memcpy to copy the value
886
54
        NativeType tmp;
887
54
        memcpy(&tmp, &value, sizeof(NativeType));
888
54
        return tmp;
889
54
    }
_ZNK5doris15JsonbDecimalValINS_7DecimalIiEEE3valEv
Line
Count
Source
884
17
    NativeType val() const {
885
        // to avoid memory alignment issues, we use memcpy to copy the value
886
17
        NativeType tmp;
887
17
        memcpy(&tmp, &value, sizeof(NativeType));
888
17
        return tmp;
889
17
    }
_ZNK5doris15JsonbDecimalValINS_7DecimalIlEEE3valEv
Line
Count
Source
884
9
    NativeType val() const {
885
        // to avoid memory alignment issues, we use memcpy to copy the value
886
9
        NativeType tmp;
887
9
        memcpy(&tmp, &value, sizeof(NativeType));
888
9
        return tmp;
889
9
    }
_ZNK5doris15JsonbDecimalValINS_12Decimal128V3EE3valEv
Line
Count
Source
884
22
    NativeType val() const {
885
        // to avoid memory alignment issues, we use memcpy to copy the value
886
22
        NativeType tmp;
887
22
        memcpy(&tmp, &value, sizeof(NativeType));
888
22
        return tmp;
889
22
    }
_ZNK5doris15JsonbDecimalValINS_7DecimalIN4wide7integerILm256EiEEEEE3valEv
Line
Count
Source
884
6
    NativeType val() const {
885
        // to avoid memory alignment issues, we use memcpy to copy the value
886
6
        NativeType tmp;
887
6
        memcpy(&tmp, &value, sizeof(NativeType));
888
6
        return tmp;
889
6
    }
890
891
128
    static constexpr int numPackedBytes() {
892
128
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
893
128
    }
_ZN5doris15JsonbDecimalValINS_7DecimalIiEEE14numPackedBytesEv
Line
Count
Source
891
45
    static constexpr int numPackedBytes() {
892
45
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
893
45
    }
_ZN5doris15JsonbDecimalValINS_7DecimalIlEEE14numPackedBytesEv
Line
Count
Source
891
33
    static constexpr int numPackedBytes() {
892
33
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
893
33
    }
_ZN5doris15JsonbDecimalValINS_12Decimal128V3EE14numPackedBytesEv
Line
Count
Source
891
44
    static constexpr int numPackedBytes() {
892
44
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
893
44
    }
_ZN5doris15JsonbDecimalValINS_7DecimalIN4wide7integerILm256EiEEEEE14numPackedBytesEv
Line
Count
Source
891
6
    static constexpr int numPackedBytes() {
892
6
        return sizeof(JsonbValue) + sizeof(precision) + sizeof(scale) + sizeof(value);
893
6
    }
894
895
    uint32_t precision;
896
    uint32_t scale;
897
    NativeType value;
898
};
899
900
/*
901
 * BlobVal is the base class (derived from JsonbValue) for string and binary
902
 * types. The size indicates the total bytes of the payload.
903
 */
904
struct JsonbBinaryVal {
905
public:
906
    // size of the blob payload only
907
2.48k
    unsigned int getBlobLen() const { return size; }
908
909
    // return the blob as byte array
910
4.77k
    const char* getBlob() const { return payload; }
911
912
    // size of the total packed bytes
913
15.6k
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(size) + size; }
914
    friend class JsonbDocument;
915
916
    uint32_t size;
917
    char payload[0];
918
};
919
920
/*
921
 * String type
922
 * Note: JSONB string may not be a c-string (NULL-terminated)
923
 */
924
struct JsonbStringVal : public JsonbBinaryVal {
925
public:
926
    /*
927
    This function return the actual size of a string. Since for
928
    a string, it can be null-terminated with null paddings or it
929
    can take all the space in the payload without null in the end.
930
    So we need to check it to get the true actual length of a string.
931
  */
932
7
    size_t length() const {
933
        // It's an empty string
934
7
        if (0 == size) {
935
0
            return size;
936
0
        }
937
        // The string stored takes all the spaces in payload
938
7
        if (payload[size - 1] != 0) {
939
7
            return size;
940
7
        }
941
        // It's shorter than the size of payload
942
0
        return strnlen(payload, size);
943
7
    }
944
};
945
946
/*
947
 * ContainerVal is the base class (derived from JsonbValue) for object and
948
 * array types. The size indicates the total bytes of the payload.
949
 */
950
struct ContainerVal {
951
    // size of the container payload only
952
0
    unsigned int getContainerSize() const { return size; }
953
954
    // return the container payload as byte array
955
0
    const char* getPayload() const { return payload; }
956
957
    // size of the total packed bytes
958
2.86k
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(size) + size; }
959
    friend class JsonbDocument;
960
961
    uint32_t size;
962
    char payload[0];
963
};
964
965
/*
966
 * Object type
967
 */
968
struct ObjectVal : public ContainerVal {
969
    using value_type = JsonbKeyValue;
970
    using pointer = value_type*;
971
    using const_pointer = const value_type*;
972
    using const_iterator = JsonbFwdIteratorT<const_pointer, ObjectVal>;
973
974
1
    const_iterator search(const char* key) const {
975
1
        if (!key) {
976
0
            return end();
977
0
        }
978
1
        return search(key, (unsigned int)strlen(key));
979
1
    }
980
981
53
    const_iterator search(const char* key, unsigned int klen) const {
982
53
        if (!key || !klen) {
983
0
            return end();
984
0
        }
985
53
        return internalSearch(key, klen);
986
53
    }
987
988
    // Get number of elements in object
989
58
    int numElem() const {
990
58
        const char* pch = payload;
991
58
        const char* fence = payload + size;
992
993
58
        unsigned int num = 0;
994
150
        while (pch < fence) {
995
92
            auto* pkey = (JsonbKeyValue*)(pch);
996
92
            ++num;
997
92
            pch += pkey->numPackedBytes();
998
92
        }
999
1000
58
        assert(pch == fence);
1001
1002
58
        return num;
1003
58
    }
1004
1005
    // find the JSONB value by a key string (null terminated)
1006
1
    const JsonbValue* find(const char* key) const {
1007
1
        if (!key) {
1008
0
            return nullptr;
1009
0
        }
1010
1
        return find(key, (unsigned int)strlen(key));
1011
1
    }
1012
1013
    // find the JSONB value by a key string (with length)
1014
51
    const JsonbValue* find(const char* key, unsigned int klen) const {
1015
51
        const_iterator kv = search(key, klen);
1016
51
        if (end() == kv) {
1017
7
            return nullptr;
1018
7
        }
1019
44
        return kv->value();
1020
51
    }
1021
1022
2.47k
    const_iterator begin() const { return const_iterator((pointer)payload); }
1023
1024
19.5k
    const_iterator end() const { return const_iterator((pointer)(payload + size)); }
1025
1026
    std::vector<std::pair<StringRef, const JsonbValue*>> get_ordered_key_value_pairs() const;
1027
1028
private:
1029
53
    const_iterator internalSearch(const char* key, unsigned int klen) const {
1030
53
        const char* pch = payload;
1031
53
        const char* fence = payload + size;
1032
1033
64
        while (pch < fence) {
1034
57
            const auto* pkey = (const JsonbKeyValue*)(pch);
1035
57
            if (klen == pkey->klen() && strncmp(key, pkey->getKeyStr(), klen) == 0) {
1036
46
                return const_iterator(pkey);
1037
46
            }
1038
11
            pch += pkey->numPackedBytes();
1039
11
        }
1040
1041
53
        assert(pch == fence);
1042
1043
7
        return end();
1044
7
    }
1045
};
1046
1047
/*
1048
 * Array type
1049
 */
1050
struct ArrayVal : public ContainerVal {
1051
    using value_type = JsonbValue;
1052
    using pointer = value_type*;
1053
    using const_pointer = const value_type*;
1054
    using const_iterator = JsonbFwdIteratorT<const_pointer, ArrayVal>;
1055
1056
    // get the JSONB value at index
1057
86
    const JsonbValue* get(int idx) const {
1058
86
        if (idx < 0) {
1059
0
            return nullptr;
1060
0
        }
1061
1062
86
        const char* pch = payload;
1063
86
        const char* fence = payload + size;
1064
1065
563
        while (pch < fence && idx-- > 0) {
1066
477
            pch += ((const JsonbValue*)pch)->numPackedBytes();
1067
477
        }
1068
86
        if (idx > 0 || pch == fence) {
1069
9
            return nullptr;
1070
9
        }
1071
1072
77
        return (const JsonbValue*)pch;
1073
86
    }
1074
1075
    // Get number of elements in array
1076
21
    int numElem() const {
1077
21
        const char* pch = payload;
1078
21
        const char* fence = payload + size;
1079
1080
21
        unsigned int num = 0;
1081
82
        while (pch < fence) {
1082
61
            ++num;
1083
61
            pch += ((const JsonbValue*)pch)->numPackedBytes();
1084
61
        }
1085
1086
21
        assert(pch == fence);
1087
1088
21
        return num;
1089
21
    }
1090
1091
173
    const_iterator begin() const { return const_iterator((pointer)payload); }
1092
1093
198
    const_iterator end() const { return const_iterator((pointer)(payload + size)); }
1094
};
1095
1096
namespace jsonb_detail {
1097
1098
struct JsonbScaledDecimal {
1099
    wide::Int256 value;
1100
    uint32_t scale;
1101
};
1102
1103
26
inline void validate_decimal_scale(uint32_t scale) {
1104
26
    if (scale > static_cast<uint32_t>(BeConsts::MAX_DECIMALV3_SCALE)) {
1105
2
        throw Exception(ErrorCode::INTERNAL_ERROR,
1106
2
                        "Invalid JSONB decimal scale: {}, max allowed scale: {}", scale,
1107
2
                        BeConsts::MAX_DECIMALV3_SCALE);
1108
2
    }
1109
26
}
1110
1111
42
inline bool is_numeric(const JsonbValue* value) {
1112
42
    return value->isInt() || value->isDouble() || value->isFloat() || value->isDecimal();
1113
42
}
1114
1115
10
inline double floating_value(const JsonbValue* value) {
1116
10
    if (value->isDouble()) {
1117
10
        return value->unpack<JsonbDoubleVal>()->val();
1118
10
    }
1119
0
    return value->unpack<JsonbFloatVal>()->val();
1120
10
}
1121
1122
20
inline JsonbScaledDecimal get_scaled_decimal(const JsonbValue* value) {
1123
20
    switch (value->type) {
1124
12
    case JsonbType::T_Decimal32: {
1125
12
        const auto* decimal = value->unpack<JsonbDecimal32>();
1126
12
        validate_decimal_scale(decimal->scale);
1127
12
        return {wide::Int256(decimal->val()), decimal->scale};
1128
0
    }
1129
2
    case JsonbType::T_Decimal64: {
1130
2
        const auto* decimal = value->unpack<JsonbDecimal64>();
1131
2
        validate_decimal_scale(decimal->scale);
1132
2
        return {wide::Int256(decimal->val()), decimal->scale};
1133
0
    }
1134
6
    case JsonbType::T_Decimal128: {
1135
6
        const auto* decimal = value->unpack<JsonbDecimal128>();
1136
6
        validate_decimal_scale(decimal->scale);
1137
6
        return {wide::Int256(decimal->val()), decimal->scale};
1138
0
    }
1139
0
    case JsonbType::T_Decimal256: {
1140
0
        const auto* decimal = value->unpack<JsonbDecimal256>();
1141
0
        validate_decimal_scale(decimal->scale);
1142
0
        return {decimal->val(), decimal->scale};
1143
0
    }
1144
0
    default:
1145
0
        throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB decimal value type: {}",
1146
0
                        static_cast<int32_t>(value->type));
1147
20
    }
1148
20
}
1149
1150
inline bool scaled_decimal_equal_decimal(const JsonbScaledDecimal& lhs,
1151
4
                                         const JsonbScaledDecimal& rhs) {
1152
4
    if (lhs.scale == rhs.scale) {
1153
0
        return lhs.value == rhs.value;
1154
0
    }
1155
1156
4
    if (lhs.scale < rhs.scale) {
1157
2
        const auto scale_multiplier = decimal_scale_multiplier<wide::Int256>(rhs.scale - lhs.scale);
1158
2
        return rhs.value % scale_multiplier == 0 && lhs.value == rhs.value / scale_multiplier;
1159
2
    }
1160
1161
2
    const auto scale_multiplier = decimal_scale_multiplier<wide::Int256>(lhs.scale - rhs.scale);
1162
2
    return lhs.value % scale_multiplier == 0 && lhs.value / scale_multiplier == rhs.value;
1163
4
}
1164
1165
4
inline bool scaled_decimal_equal_integer(const JsonbScaledDecimal& decimal, int128_t integer) {
1166
4
    const auto integer_value = wide::Int256(integer);
1167
4
    if (decimal.scale == 0) {
1168
0
        return decimal.value == integer_value;
1169
0
    }
1170
1171
4
    const auto scale_multiplier = decimal_scale_multiplier<wide::Int256>(decimal.scale);
1172
4
    return decimal.value % scale_multiplier == 0 &&
1173
4
           decimal.value / scale_multiplier == integer_value;
1174
4
}
1175
1176
inline constexpr auto kPowersOfFive = [] {
1177
    std::array<wide::Int256, BeConsts::MAX_DECIMALV3_SCALE + 1> powers {};
1178
    powers[0] = 1;
1179
    for (size_t i = 1; i < powers.size(); ++i) {
1180
        powers[i] = powers[i - 1] * 5;
1181
    }
1182
    return powers;
1183
}();
1184
1185
6
inline wide::Int256 power_of_five(uint32_t exponent) {
1186
6
    validate_decimal_scale(exponent);
1187
6
    return kPowersOfFive[exponent];
1188
6
}
1189
1190
6
inline bool scaled_binary_equal(wide::Int256 value, int exponent, wide::Int256 significand) {
1191
6
    if (exponent < 0) {
1192
4
        const int divisor_exponent = -exponent;
1193
4
        if (divisor_exponent >= std::numeric_limits<int64_t>::digits) {
1194
0
            return false;
1195
0
        }
1196
4
        const auto divisor = wide::Int256(1) << divisor_exponent;
1197
4
        return significand % divisor == 0 && value == significand / divisor;
1198
4
    }
1199
2
    constexpr int max_positive_int256_shift = std::numeric_limits<wide::Int256>::digits;
1200
    // wide::Int256 is signed, so shifting 1 by 255 reaches the sign bit.
1201
2
    if (exponent >= max_positive_int256_shift) {
1202
0
        return false;
1203
0
    }
1204
2
    const auto multiplier = wide::Int256(1) << exponent;
1205
2
    return value % multiplier == 0 && value / multiplier == significand;
1206
2
}
1207
1208
4
inline bool floating_equal_integer(const JsonbValue* floating, int128_t integer) {
1209
4
    const double value = floating_value(floating);
1210
4
    int exponent = 0;
1211
4
    std::frexp(value, &exponent);
1212
4
    if (!std::isfinite(value) || std::trunc(value) != value) {
1213
1
        return false;
1214
1
    }
1215
3
    if (exponent >= 128) {
1216
0
        return value == -std::ldexp(1.0, 127) && integer == std::numeric_limits<int128_t>::min();
1217
0
    }
1218
3
    if (exponent <= -1) {
1219
0
        return false;
1220
0
    }
1221
3
    return static_cast<int128_t>(value) == integer;
1222
3
}
1223
1224
6
inline bool floating_equal_decimal(const JsonbValue* floating, const JsonbScaledDecimal& decimal) {
1225
6
    const double value = floating_value(floating);
1226
6
    if (!std::isfinite(value)) {
1227
0
        return false;
1228
0
    }
1229
6
    if (value == 0) {
1230
0
        return decimal.value == 0;
1231
0
    }
1232
1233
6
    int exponent = 0;
1234
6
    const double significand_fraction = std::frexp(value, &exponent);
1235
6
    const double significand_double =
1236
6
            std::ldexp(significand_fraction, std::numeric_limits<double>::digits);
1237
6
    auto significand = wide::Int256(static_cast<int64_t>(significand_double));
1238
6
    exponent -= std::numeric_limits<double>::digits;
1239
1240
6
    const auto five_multiplier = power_of_five(decimal.scale);
1241
6
    if (decimal.value % five_multiplier != 0) {
1242
0
        return false;
1243
0
    }
1244
6
    const auto binary_scaled_decimal = decimal.value / five_multiplier;
1245
6
    return scaled_binary_equal(binary_scaled_decimal, exponent + decimal.scale, significand);
1246
6
}
1247
1248
42
inline bool numeric_equal(const JsonbValue* lhs, const JsonbValue* rhs) {
1249
42
    if (!is_numeric(rhs)) {
1250
2
        return false;
1251
2
    }
1252
1253
40
    if ((lhs->isDouble() || lhs->isFloat()) && rhs->isInt()) {
1254
1
        return floating_equal_integer(lhs, rhs->int_val());
1255
1
    }
1256
1257
39
    if ((rhs->isDouble() || rhs->isFloat()) && lhs->isInt()) {
1258
3
        return floating_equal_integer(rhs, lhs->int_val());
1259
3
    }
1260
1261
36
    if ((lhs->isDouble() || lhs->isFloat()) && rhs->isDecimal()) {
1262
4
        return floating_equal_decimal(lhs, get_scaled_decimal(rhs));
1263
4
    }
1264
1265
32
    if ((rhs->isDouble() || rhs->isFloat()) && lhs->isDecimal()) {
1266
4
        return floating_equal_decimal(rhs, get_scaled_decimal(lhs));
1267
4
    }
1268
1269
28
    if (lhs->isDouble() || lhs->isFloat()) {
1270
0
        return (rhs->isDouble() || rhs->isFloat()) && floating_value(lhs) == floating_value(rhs);
1271
0
    }
1272
1273
28
    if (lhs->isDecimal()) {
1274
6
        const auto lhs_decimal = get_scaled_decimal(lhs);
1275
6
        if (rhs->isDecimal()) {
1276
4
            return scaled_decimal_equal_decimal(lhs_decimal, get_scaled_decimal(rhs));
1277
4
        }
1278
2
        return scaled_decimal_equal_integer(lhs_decimal, rhs->int_val());
1279
6
    }
1280
1281
22
    if (rhs->isDecimal()) {
1282
2
        return scaled_decimal_equal_integer(get_scaled_decimal(rhs), lhs->int_val());
1283
2
    }
1284
1285
20
    return lhs->int_val() == rhs->int_val();
1286
22
}
1287
1288
17
inline bool array_contains_value(const ArrayVal* target_array, const JsonbValue* candidate) {
1289
30
    for (auto it = target_array->begin(); it < target_array->end(); ++it) {
1290
25
        if (it->contains(candidate)) {
1291
12
            return true;
1292
12
        }
1293
25
    }
1294
5
    return false;
1295
17
}
1296
1297
10
inline bool array_contains_array(const ArrayVal* target_array, const ArrayVal* candidate_array) {
1298
21
    for (auto it = candidate_array->begin(); it < candidate_array->end(); ++it) {
1299
15
        if (!array_contains_value(target_array, &*it)) {
1300
4
            return false;
1301
4
        }
1302
15
    }
1303
6
    return true;
1304
10
}
1305
1306
} // namespace jsonb_detail
1307
1308
23
inline const JsonbValue* JsonbDocument::createValue(const char* pb, size_t size) {
1309
23
    if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) {
1310
0
        return nullptr;
1311
0
    }
1312
1313
23
    auto* doc = (JsonbDocument*)pb;
1314
23
    if (doc->header_.ver_ != JSONB_VER) {
1315
0
        return nullptr;
1316
0
    }
1317
1318
23
    const auto* val = (const JsonbValue*)doc->payload_;
1319
23
    if (size != sizeof(JsonbHeader) + val->numPackedBytes()) {
1320
0
        return nullptr;
1321
0
    }
1322
1323
23
    return val;
1324
23
}
1325
1326
6
inline unsigned int JsonbDocument::numPackedBytes() const {
1327
6
    return ((const JsonbValue*)payload_)->numPackedBytes() + sizeof(header_);
1328
6
}
1329
1330
18.8k
inline unsigned int JsonbKeyValue::numPackedBytes() const {
1331
18.8k
    unsigned int ks = keyPackedBytes();
1332
18.8k
    const auto* val = (const JsonbValue*)(((char*)this) + ks);
1333
18.8k
    return ks + val->numPackedBytes();
1334
18.8k
}
1335
1336
// Poor man's "virtual" function JsonbValue::numPackedBytes
1337
73.9k
inline unsigned int JsonbValue::numPackedBytes() const {
1338
73.9k
    switch (type) {
1339
2.82k
    case JsonbType::T_Null:
1340
12.4k
    case JsonbType::T_True:
1341
13.0k
    case JsonbType::T_False: {
1342
13.0k
        return sizeof(type);
1343
12.4k
    }
1344
1345
1.37k
    case JsonbType::T_Int8: {
1346
1.37k
        return sizeof(type) + sizeof(int8_t);
1347
12.4k
    }
1348
412
    case JsonbType::T_Int16: {
1349
412
        return sizeof(type) + sizeof(int16_t);
1350
12.4k
    }
1351
3.54k
    case JsonbType::T_Int32: {
1352
3.54k
        return sizeof(type) + sizeof(int32_t);
1353
12.4k
    }
1354
12.2k
    case JsonbType::T_Int64: {
1355
12.2k
        return sizeof(type) + sizeof(int64_t);
1356
12.4k
    }
1357
10.7k
    case JsonbType::T_Double: {
1358
10.7k
        return sizeof(type) + sizeof(double);
1359
12.4k
    }
1360
44
    case JsonbType::T_Float: {
1361
44
        return sizeof(type) + sizeof(float);
1362
12.4k
    }
1363
14.0k
    case JsonbType::T_Int128: {
1364
14.0k
        return sizeof(type) + sizeof(int128_t);
1365
12.4k
    }
1366
11.1k
    case JsonbType::T_String:
1367
15.6k
    case JsonbType::T_Binary: {
1368
15.6k
        return unpack<JsonbBinaryVal>()->numPackedBytes();
1369
11.1k
    }
1370
1371
2.59k
    case JsonbType::T_Object:
1372
2.86k
    case JsonbType::T_Array: {
1373
2.86k
        return unpack<ContainerVal>()->numPackedBytes();
1374
2.59k
    }
1375
45
    case JsonbType::T_Decimal32: {
1376
45
        return JsonbDecimal32::numPackedBytes();
1377
2.59k
    }
1378
33
    case JsonbType::T_Decimal64: {
1379
33
        return JsonbDecimal64::numPackedBytes();
1380
2.59k
    }
1381
44
    case JsonbType::T_Decimal128: {
1382
44
        return JsonbDecimal128::numPackedBytes();
1383
2.59k
    }
1384
6
    case JsonbType::T_Decimal256: {
1385
6
        return JsonbDecimal256::numPackedBytes();
1386
2.59k
    }
1387
0
    case JsonbType::NUM_TYPES:
1388
0
        break;
1389
73.9k
    }
1390
1391
0
    throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
1392
0
                    static_cast<int32_t>(type));
1393
73.9k
}
1394
1395
11
inline int JsonbValue::numElements() const {
1396
11
    switch (type) {
1397
1
    case JsonbType::T_Int8:
1398
1
    case JsonbType::T_Int16:
1399
1
    case JsonbType::T_Int32:
1400
1
    case JsonbType::T_Int64:
1401
1
    case JsonbType::T_Double:
1402
1
    case JsonbType::T_Float:
1403
1
    case JsonbType::T_Int128:
1404
2
    case JsonbType::T_String:
1405
2
    case JsonbType::T_Binary:
1406
3
    case JsonbType::T_Null:
1407
3
    case JsonbType::T_True:
1408
3
    case JsonbType::T_False:
1409
3
    case JsonbType::T_Decimal32:
1410
3
    case JsonbType::T_Decimal64:
1411
3
    case JsonbType::T_Decimal128:
1412
3
    case JsonbType::T_Decimal256: {
1413
3
        return 1;
1414
3
    }
1415
0
    case JsonbType::T_Object: {
1416
0
        return unpack<ObjectVal>()->numElem();
1417
3
    }
1418
8
    case JsonbType::T_Array: {
1419
8
        return unpack<ArrayVal>()->numElem();
1420
3
    }
1421
0
    case JsonbType::NUM_TYPES:
1422
0
        break;
1423
11
    }
1424
0
    throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
1425
0
                    static_cast<int32_t>(type));
1426
11
}
1427
1428
58
inline bool JsonbValue::contains(const JsonbValue* rhs) const {
1429
58
    switch (type) {
1430
26
    case JsonbType::T_Int8:
1431
26
    case JsonbType::T_Int16:
1432
26
    case JsonbType::T_Int32:
1433
26
    case JsonbType::T_Int64:
1434
27
    case JsonbType::T_Int128:
1435
32
    case JsonbType::T_Double:
1436
32
    case JsonbType::T_Float:
1437
38
    case JsonbType::T_Decimal32:
1438
39
    case JsonbType::T_Decimal64:
1439
42
    case JsonbType::T_Decimal128:
1440
42
    case JsonbType::T_Decimal256: {
1441
42
        return jsonb_detail::numeric_equal(this, rhs);
1442
42
    }
1443
1
    case JsonbType::T_String:
1444
1
    case JsonbType::T_Binary: {
1445
1
        if (rhs->isString() || rhs->isBinary()) {
1446
1
            const auto* str_value1 = unpack<JsonbStringVal>();
1447
1
            const auto* str_value2 = rhs->unpack<JsonbStringVal>();
1448
1
            return str_value1->length() == str_value2->length() &&
1449
1
                   std::memcmp(str_value1->getBlob(), str_value2->getBlob(),
1450
1
                               str_value1->length()) == 0;
1451
1
        }
1452
0
        return false;
1453
1
    }
1454
12
    case JsonbType::T_Array: {
1455
12
        const auto* lhs_array = unpack<ArrayVal>();
1456
12
        if (rhs->isArray()) {
1457
10
            return jsonb_detail::array_contains_array(lhs_array, rhs->unpack<ArrayVal>());
1458
10
        }
1459
2
        return jsonb_detail::array_contains_value(lhs_array, rhs);
1460
12
    }
1461
3
    case JsonbType::T_Object: {
1462
3
        if (rhs->isObject()) {
1463
2
            const auto* obj_value1 = unpack<ObjectVal>();
1464
2
            const auto* obj_value2 = rhs->unpack<ObjectVal>();
1465
3
            for (auto it = obj_value2->begin(); it != obj_value2->end(); ++it) {
1466
2
                const JsonbValue* value = obj_value1->find(it->getKeyStr(), it->klen());
1467
2
                if (value == nullptr || !value->contains(it->value())) {
1468
1
                    return false;
1469
1
                }
1470
2
            }
1471
1
            return true;
1472
2
        }
1473
1
        return false;
1474
3
    }
1475
0
    case JsonbType::T_Null: {
1476
0
        return rhs->isNull();
1477
3
    }
1478
0
    case JsonbType::T_True: {
1479
0
        return rhs->isTrue();
1480
3
    }
1481
0
    case JsonbType::T_False: {
1482
0
        return rhs->isFalse();
1483
3
    }
1484
0
    case JsonbType::NUM_TYPES:
1485
0
        break;
1486
58
    }
1487
1488
0
    throw Exception(ErrorCode::INTERNAL_ERROR, "Invalid JSONB value type: {}",
1489
0
                    static_cast<int32_t>(type));
1490
58
}
1491
1492
113
inline bool JsonbPath::seek(const char* key_path, size_t kp_len) {
1493
113
    while (kp_len > 0 && std::isspace(key_path[kp_len - 1])) {
1494
0
        --kp_len;
1495
0
    }
1496
1497
    //path invalid
1498
113
    if (!key_path || kp_len == 0) {
1499
0
        return false;
1500
0
    }
1501
113
    Stream stream(key_path, kp_len);
1502
113
    stream.skip_whitespace();
1503
113
    if (stream.exhausted() || stream.read() != SCOPE) {
1504
        //path invalid
1505
0
        return false;
1506
0
    }
1507
1508
227
    while (!stream.exhausted()) {
1509
114
        stream.skip_whitespace();
1510
114
        stream.clear_leg_ptr();
1511
114
        stream.clear_leg_len();
1512
114
        stream.set_has_escapes(false);
1513
1514
114
        if (!JsonbPath::parsePath(&stream, this)) {
1515
            //path invalid
1516
0
            return false;
1517
0
        }
1518
114
    }
1519
113
    return true;
1520
113
}
1521
1522
114
inline bool JsonbPath::parsePath(Stream* stream, JsonbPath* path) {
1523
    // $[0]
1524
114
    if (stream->peek() == BEGIN_ARRAY) {
1525
61
        return parse_array(stream, path);
1526
61
    }
1527
    // $.a or $.[0]
1528
53
    else if (stream->peek() == BEGIN_MEMBER) {
1529
        // advance past the .
1530
51
        stream->skip(1);
1531
1532
51
        if (stream->exhausted()) {
1533
0
            return false;
1534
0
        }
1535
1536
        // $.[0]
1537
51
        if (stream->peek() == BEGIN_ARRAY) {
1538
0
            return parse_array(stream, path);
1539
0
        }
1540
        // $.a
1541
51
        else {
1542
51
            return parse_member(stream, path);
1543
51
        }
1544
51
    } else if (stream->peek() == WILDCARD) {
1545
2
        stream->skip(1);
1546
2
        if (stream->exhausted()) {
1547
0
            return false;
1548
0
        }
1549
1550
        // $**
1551
2
        if (stream->peek() == WILDCARD) {
1552
2
            path->_is_supper_wildcard = true;
1553
2
        }
1554
1555
2
        stream->skip(1);
1556
2
        if (stream->exhausted()) {
1557
0
            return false;
1558
0
        }
1559
1560
2
        if (stream->peek() == BEGIN_ARRAY) {
1561
0
            return parse_array(stream, path);
1562
2
        } else if (stream->peek() == BEGIN_MEMBER) {
1563
            // advance past the .
1564
2
            stream->skip(1);
1565
1566
2
            if (stream->exhausted()) {
1567
0
                return false;
1568
0
            }
1569
1570
            // $.[0]
1571
2
            if (stream->peek() == BEGIN_ARRAY) {
1572
0
                return parse_array(stream, path);
1573
0
            }
1574
            // $.a
1575
2
            else {
1576
2
                return parse_member(stream, path);
1577
2
            }
1578
2
        }
1579
0
        return false;
1580
2
    } else {
1581
0
        return false; //invalid json path
1582
0
    }
1583
114
}
1584
1585
61
inline bool JsonbPath::parse_array(Stream* stream, JsonbPath* path) {
1586
61
    assert(stream->peek() == BEGIN_ARRAY);
1587
61
    stream->skip(1);
1588
61
    if (stream->exhausted()) {
1589
0
        return false;
1590
0
    }
1591
1592
61
    if (stream->peek() == WILDCARD) {
1593
        // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1594
        // using const_cast is acceptable.
1595
0
        stream->set_leg_ptr(const_cast<char*>(stream->position()));
1596
0
        stream->add_leg_len();
1597
0
        stream->skip(1);
1598
0
        if (stream->exhausted()) {
1599
0
            return false;
1600
0
        }
1601
1602
0
        if (stream->peek() == END_ARRAY) {
1603
0
            std::unique_ptr<leg_info> leg(
1604
0
                    new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, ARRAY_CODE));
1605
0
            path->add_leg_to_leg_vector(std::move(leg));
1606
0
            stream->skip(1);
1607
0
            path->_is_wildcard = true;
1608
0
            return true;
1609
0
        } else {
1610
0
            return false;
1611
0
        }
1612
0
    }
1613
1614
    // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1615
    // using const_cast is acceptable.
1616
61
    stream->set_leg_ptr(const_cast<char*>(stream->position()));
1617
1618
122
    for (; !stream->exhausted() && stream->peek() != END_ARRAY; stream->advance()) {
1619
61
        stream->add_leg_len();
1620
61
    }
1621
1622
61
    if (stream->exhausted() || stream->peek() != END_ARRAY) {
1623
0
        return false;
1624
61
    } else {
1625
61
        stream->skip(1);
1626
61
    }
1627
1628
    //parse array index to int
1629
1630
61
    std::string_view idx_string(stream->get_leg_ptr(), stream->get_leg_len());
1631
61
    int index = 0;
1632
1633
61
    if (stream->get_leg_len() >= 4 &&
1634
61
        std::equal(LAST, LAST + 4, stream->get_leg_ptr(),
1635
0
                   [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); })) {
1636
0
        auto pos = idx_string.find(MINUS);
1637
1638
0
        if (pos != std::string::npos) {
1639
0
            for (size_t i = 4; i < pos; ++i) {
1640
0
                if (std::isspace(idx_string[i])) {
1641
0
                    continue;
1642
0
                } else {
1643
                    // leading zeroes are not allowed
1644
0
                    LOG(WARNING) << "Non-space char in idx_string: '" << idx_string << "'";
1645
0
                    return false;
1646
0
                }
1647
0
            }
1648
0
            idx_string = idx_string.substr(pos + 1);
1649
0
            idx_string = trim(idx_string);
1650
1651
0
            auto result = std::from_chars(idx_string.data(), idx_string.data() + idx_string.size(),
1652
0
                                          index);
1653
0
            if (result.ec != std::errc()) {
1654
0
                LOG(WARNING) << "Invalid index in JSON path: '" << idx_string << "'";
1655
0
                return false;
1656
0
            }
1657
1658
0
        } else if (stream->get_leg_len() > 4) {
1659
0
            return false;
1660
0
        }
1661
1662
0
        std::unique_ptr<leg_info> leg(new leg_info(nullptr, 0, -index - 1, ARRAY_CODE));
1663
0
        path->add_leg_to_leg_vector(std::move(leg));
1664
1665
0
        return true;
1666
0
    }
1667
1668
61
    auto result = std::from_chars(idx_string.data(), idx_string.data() + idx_string.size(), index);
1669
1670
61
    if (result.ec != std::errc()) {
1671
0
        return false;
1672
0
    }
1673
1674
61
    std::unique_ptr<leg_info> leg(new leg_info(nullptr, 0, index, ARRAY_CODE));
1675
61
    path->add_leg_to_leg_vector(std::move(leg));
1676
1677
61
    return true;
1678
61
}
1679
1680
53
inline bool JsonbPath::parse_member(Stream* stream, JsonbPath* path) {
1681
53
    if (stream->exhausted()) {
1682
0
        return false;
1683
0
    }
1684
1685
53
    if (stream->peek() == WILDCARD) {
1686
        // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1687
        // using const_cast is acceptable.
1688
0
        stream->set_leg_ptr(const_cast<char*>(stream->position()));
1689
0
        stream->add_leg_len();
1690
0
        stream->skip(1);
1691
0
        std::unique_ptr<leg_info> leg(
1692
0
                new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, MEMBER_CODE));
1693
0
        path->add_leg_to_leg_vector(std::move(leg));
1694
0
        path->_is_wildcard = true;
1695
0
        return true;
1696
0
    }
1697
1698
    // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1699
    // using const_cast is acceptable.
1700
53
    stream->set_leg_ptr(const_cast<char*>(stream->position()));
1701
1702
53
    const char* left_quotation_marks = nullptr;
1703
53
    const char* right_quotation_marks = nullptr;
1704
1705
180
    for (; !stream->exhausted(); stream->advance()) {
1706
        // Only accept space characters quoted by double quotes.
1707
136
        if (std::isspace(stream->peek()) && left_quotation_marks == nullptr) {
1708
0
            return false;
1709
136
        } else if (stream->peek() == ESCAPE) {
1710
11
            stream->add_leg_len();
1711
11
            stream->skip(1);
1712
11
            stream->add_leg_len();
1713
11
            stream->set_has_escapes(true);
1714
11
            if (stream->exhausted()) {
1715
0
                return false;
1716
0
            }
1717
11
            continue;
1718
125
        } else if (stream->peek() == DOUBLE_QUOTE) {
1719
6
            if (left_quotation_marks == nullptr) {
1720
3
                left_quotation_marks = stream->position();
1721
                // Called by function_jsonb.cpp, the variables passed in originate from a mutable block;
1722
                // using const_cast is acceptable.
1723
3
                stream->set_leg_ptr(const_cast<char*>(++left_quotation_marks));
1724
3
                continue;
1725
3
            } else {
1726
3
                right_quotation_marks = stream->position();
1727
3
                stream->skip(1);
1728
3
                break;
1729
3
            }
1730
119
        } else if (stream->peek() == BEGIN_MEMBER || stream->peek() == BEGIN_ARRAY) {
1731
6
            if (left_quotation_marks == nullptr) {
1732
6
                break;
1733
6
            }
1734
6
        }
1735
1736
113
        stream->add_leg_len();
1737
113
    }
1738
1739
53
    if ((left_quotation_marks != nullptr && right_quotation_marks == nullptr) ||
1740
53
        stream->get_leg_ptr() == nullptr || stream->get_leg_len() == 0) {
1741
0
        return false; //invalid json path
1742
0
    }
1743
1744
53
    if (stream->get_has_escapes()) {
1745
3
        stream->remove_escapes();
1746
3
    }
1747
1748
53
    std::unique_ptr<leg_info> leg(
1749
53
            new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, MEMBER_CODE));
1750
53
    path->add_leg_to_leg_vector(std::move(leg));
1751
1752
53
    return true;
1753
53
}
1754
1755
static_assert(is_pod_v<JsonbDocument>, "JsonbDocument must be standard layout and trivial");
1756
static_assert(is_pod_v<JsonbValue>, "JsonbValue must be standard layout and trivial");
1757
static_assert(is_pod_v<JsonbDecimal32>, "JsonbDecimal32 must be standard layout and trivial");
1758
static_assert(is_pod_v<JsonbDecimal64>, "JsonbDecimal64 must be standard layout and trivial");
1759
static_assert(is_pod_v<JsonbDecimal128>, "JsonbDecimal128 must be standard layout and trivial");
1760
static_assert(is_pod_v<JsonbDecimal256>, "JsonbDecimal256 must be standard layout and trivial");
1761
static_assert(is_pod_v<JsonbInt8Val>, "JsonbInt8Val must be standard layout and trivial");
1762
static_assert(is_pod_v<JsonbInt32Val>, "JsonbInt32Val must be standard layout and trivial");
1763
static_assert(is_pod_v<JsonbInt64Val>, "JsonbInt64Val must be standard layout and trivial");
1764
static_assert(is_pod_v<JsonbInt128Val>, "JsonbInt128Val must be standard layout and trivial");
1765
static_assert(is_pod_v<JsonbDoubleVal>, "JsonbDoubleVal must be standard layout and trivial");
1766
static_assert(is_pod_v<JsonbFloatVal>, "JsonbFloatVal must be standard layout and trivial");
1767
static_assert(is_pod_v<JsonbBinaryVal>, "JsonbBinaryVal must be standard layout and trivial");
1768
static_assert(is_pod_v<ContainerVal>, "ContainerVal must be standard layout and trivial");
1769
1770
#define ASSERT_DECIMAL_LAYOUT(type)                \
1771
    static_assert(offsetof(type, precision) == 0); \
1772
    static_assert(offsetof(type, scale) == 4);     \
1773
    static_assert(offsetof(type, value) == 8);
1774
1775
ASSERT_DECIMAL_LAYOUT(JsonbDecimal32)
1776
ASSERT_DECIMAL_LAYOUT(JsonbDecimal64)
1777
ASSERT_DECIMAL_LAYOUT(JsonbDecimal128)
1778
ASSERT_DECIMAL_LAYOUT(JsonbDecimal256)
1779
1780
#define ASSERT_NUMERIC_LAYOUT(type) static_assert(offsetof(type, num) == 0);
1781
1782
ASSERT_NUMERIC_LAYOUT(JsonbInt8Val)
1783
ASSERT_NUMERIC_LAYOUT(JsonbInt32Val)
1784
ASSERT_NUMERIC_LAYOUT(JsonbInt64Val)
1785
ASSERT_NUMERIC_LAYOUT(JsonbInt128Val)
1786
ASSERT_NUMERIC_LAYOUT(JsonbDoubleVal)
1787
1788
static_assert(offsetof(JsonbBinaryVal, size) == 0);
1789
static_assert(offsetof(JsonbBinaryVal, payload) == 4);
1790
1791
static_assert(offsetof(ContainerVal, size) == 0);
1792
static_assert(offsetof(ContainerVal, payload) == 4);
1793
1794
#pragma pack(pop)
1795
#if defined(__clang__)
1796
#pragma clang diagnostic pop
1797
#endif
1798
} // namespace doris
1799
1800
#endif // JSONB_JSONBDOCUMENT_H