Coverage Report

Created: 2026-09-11 03:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/jsonb_utils.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 file defines miscellaneous utility classes.
13
 *
14
 * @author Tian Xia <tianx@fb.com>
15
 *
16
 *  this file is copied from 
17
 * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonUtil.h
18
 * and modified by Doris
19
 */
20
21
#ifndef JSONB_JSONBUTIL_H
22
#define JSONB_JSONBUTIL_H
23
24
#include "common/status.h"
25
#include "util/jsonb_document.h"
26
#include "util/jsonb_stream.h"
27
28
namespace doris {
29
30
56.2k
#define OUT_BUF_SIZE 1024
31
32
/*
33
 * JsonbToJson converts an JsonbValue object to a JSON string.
34
 */
35
class JsonbToJson {
36
public:
37
56.2k
    JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {}
38
39
    // get json string
40
55.6k
    std::string to_json_string(const char* data, size_t size) {
41
55.6k
        const JsonbDocument* pdoc;
42
55.6k
        THROW_IF_ERROR(doris::JsonbDocument::checkAndCreateDocument(data, size, &pdoc));
43
55.6k
        return to_json_string(pdoc->getValue());
44
55.6k
    }
45
46
56.2k
    std::string to_json_string(const JsonbValue* val) {
47
56.2k
        os_.clear();
48
56.2k
        os_.seekp(0);
49
50
56.2k
        if (val) {
51
56.2k
            intern_json(val);
52
56.2k
        }
53
54
56.2k
        os_.put(0);
55
56
56.2k
        std::string json_string {os_.getBuffer()};
57
56.2k
        return json_string;
58
56.2k
    }
59
60
55.6k
    static std::string jsonb_to_json_string(const char* data, size_t size) {
61
55.6k
        JsonbToJson jsonb_to_json;
62
55.6k
        return jsonb_to_json.to_json_string(data, size);
63
55.6k
    }
64
65
private:
66
    // recursively convert JsonbValue
67
359k
    void intern_json(const JsonbValue* val) {
68
359k
        switch (val->type) {
69
616
        case JsonbType::T_Null: {
70
616
            os_.write("null", 4);
71
616
            break;
72
0
        }
73
25.9k
        case JsonbType::T_True: {
74
25.9k
            os_.write("true", 4);
75
25.9k
            break;
76
0
        }
77
5.51k
        case JsonbType::T_False: {
78
5.51k
            os_.write("false", 5);
79
5.51k
            break;
80
0
        }
81
9.63k
        case JsonbType::T_Int8: {
82
9.63k
            os_.write(val->unpack<JsonbInt8Val>()->val());
83
9.63k
            break;
84
0
        }
85
484
        case JsonbType::T_Int16: {
86
484
            os_.write(val->unpack<JsonbInt16Val>()->val());
87
484
            break;
88
0
        }
89
6.16k
        case JsonbType::T_Int32: {
90
6.16k
            os_.write(val->unpack<JsonbInt32Val>()->val());
91
6.16k
            break;
92
0
        }
93
16.9k
        case JsonbType::T_Int64: {
94
16.9k
            os_.write(val->unpack<JsonbInt64Val>()->val());
95
16.9k
            break;
96
0
        }
97
207
        case JsonbType::T_Double: {
98
207
            os_.write(val->unpack<JsonbDoubleVal>()->val());
99
207
            break;
100
0
        }
101
2
        case JsonbType::T_Float: {
102
2
            os_.write(val->unpack<JsonbFloatVal>()->val());
103
2
            break;
104
0
        }
105
10
        case JsonbType::T_Int128: {
106
10
            os_.write(val->unpack<JsonbInt128Val>()->val());
107
10
            break;
108
0
        }
109
202k
        case JsonbType::T_String: {
110
202k
            string_to_json(val->unpack<JsonbStringVal>()->getBlob(),
111
202k
                           val->unpack<JsonbStringVal>()->length());
112
202k
            break;
113
0
        }
114
0
        case JsonbType::T_Binary: {
115
0
            os_.write("\"<BINARY>", 9);
116
0
            os_.write(val->unpack<JsonbBinaryVal>()->getBlob(),
117
0
                      val->unpack<JsonbBinaryVal>()->getBlobLen());
118
0
            os_.write("<BINARY>\"", 9);
119
0
            break;
120
0
        }
121
69.0k
        case JsonbType::T_Object: {
122
69.0k
            object_to_json(val->unpack<ObjectVal>());
123
69.0k
            break;
124
0
        }
125
22.0k
        case JsonbType::T_Array: {
126
22.0k
            array_to_json(val->unpack<ArrayVal>());
127
22.0k
            break;
128
0
        }
129
28
        case JsonbType::T_Decimal32: {
130
28
            const auto* decimal_val = val->unpack<JsonbDecimal32>();
131
28
            decimal_to_json(Decimal32 {decimal_val->val()}, decimal_val->precision,
132
28
                            decimal_val->scale);
133
28
            break;
134
0
        }
135
3
        case JsonbType::T_Decimal64: {
136
3
            const auto* decimal_val = val->unpack<JsonbDecimal64>();
137
3
            decimal_to_json(Decimal64 {decimal_val->val()}, decimal_val->precision,
138
3
                            decimal_val->scale);
139
3
            break;
140
0
        }
141
28
        case JsonbType::T_Decimal128: {
142
28
            const auto* decimal_val = val->unpack<JsonbDecimal128>();
143
28
            decimal_to_json(Decimal128V3 {decimal_val->val()}, decimal_val->precision,
144
28
                            decimal_val->scale);
145
28
            break;
146
0
        }
147
1
        case JsonbType::T_Decimal256: {
148
1
            const auto* decimal_val = val->unpack<JsonbDecimal256>();
149
1
            decimal_to_json(Decimal256 {decimal_val->val()}, decimal_val->precision,
150
1
                            decimal_val->scale);
151
1
            break;
152
0
        }
153
0
        default:
154
0
            break;
155
359k
        }
156
359k
    }
157
158
464k
    void string_to_json(const char* str, size_t len) {
159
464k
        os_.put('"');
160
464k
        if (nullptr == str) {
161
3
            os_.put('"');
162
3
            return;
163
3
        }
164
464k
        char char_buffer[16];
165
13.3M
        for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) {
166
12.8M
            if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\') {
167
12.8M
                os_.put(*ptr);
168
12.8M
            } else {
169
31.3k
                os_.put('\\');
170
31.3k
                unsigned char token;
171
31.3k
                switch (token = *ptr) {
172
98
                case '\\':
173
98
                    os_.put('\\');
174
98
                    break;
175
3.35k
                case '\"':
176
3.35k
                    os_.put('\"');
177
3.35k
                    break;
178
1
                case '\b':
179
1
                    os_.put('b');
180
1
                    break;
181
1
                case '\f':
182
1
                    os_.put('f');
183
1
                    break;
184
27.4k
                case '\n':
185
27.4k
                    os_.put('n');
186
27.4k
                    break;
187
193
                case '\r':
188
193
                    os_.put('r');
189
193
                    break;
190
511
                case '\t':
191
511
                    os_.put('t');
192
511
                    break;
193
0
                default: {
194
0
                    int char_num = snprintf(char_buffer, sizeof(char_buffer), "u%04x", token);
195
0
                    os_.write(char_buffer, char_num);
196
0
                    break;
197
0
                }
198
31.3k
                }
199
31.3k
            }
200
12.8M
        }
201
464k
        os_.put('"');
202
464k
    }
203
204
    // convert object
205
69.0k
    void object_to_json(const ObjectVal* val) {
206
69.0k
        os_.put('{');
207
208
69.0k
        auto iter = val->begin();
209
69.0k
        auto iter_fence = val->end();
210
211
331k
        while (iter < iter_fence) {
212
            // write key
213
262k
            if (iter->klen()) {
214
262k
                string_to_json(iter->getKeyStr(), iter->klen());
215
262k
            } else {
216
                // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h
217
3
                if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) {
218
3
                    string_to_json(nullptr, 0);
219
18.4E
                } else {
220
18.4E
                    os_.write(iter->getKeyId());
221
18.4E
                }
222
2
            }
223
262k
            os_.put(':');
224
225
            // convert value
226
262k
            intern_json(iter->value());
227
228
262k
            ++iter;
229
262k
            if (iter != iter_fence) {
230
193k
                os_.put(',');
231
193k
            }
232
262k
        }
233
234
69.0k
        assert(iter == iter_fence);
235
236
69.0k
        os_.put('}');
237
69.0k
    }
238
239
    // convert array to json
240
22.0k
    void array_to_json(const ArrayVal* val) {
241
22.0k
        os_.put('[');
242
243
22.0k
        auto iter = val->begin();
244
22.0k
        auto iter_fence = val->end();
245
246
62.9k
        while (iter != iter_fence) {
247
            // convert value
248
40.9k
            intern_json((const JsonbValue*)iter);
249
40.9k
            ++iter;
250
40.9k
            if (iter != iter_fence) {
251
18.9k
                os_.put(',');
252
18.9k
            }
253
40.9k
        }
254
255
22.0k
        assert(iter == iter_fence);
256
257
22.0k
        os_.put(']');
258
22.0k
    }
259
260
    template <JsonbDecimalType T>
261
    void decimal_to_json(const T& value, const uint32_t precision, const uint32_t scale);
262
263
    JsonbOutStream os_;
264
    char buffer_[OUT_BUF_SIZE];
265
};
266
267
} // namespace doris
268
269
#endif // JSONB_JSONBUTIL_H