Coverage Report

Created: 2025-03-11 17:58

/root/doris/be/src/util/jsonb_utils.h
Line
Count
Source (jump to first uncovered line)
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 <sstream>
25
26
#include "common/exception.h"
27
#include "jsonb_document.h"
28
#include "jsonb_stream.h"
29
#include "jsonb_writer.h"
30
31
namespace doris {
32
33
#define OUT_BUF_SIZE 1024
34
35
/*
36
 * JsonbToJson converts an JsonbValue object to a JSON string.
37
 */
38
class JsonbToJson {
39
public:
40
304
    JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {}
41
42
    // get json string
43
300
    const std::string to_json_string(const char* data, size_t size) {
44
300
        JsonbDocument* pdoc = doris::JsonbDocument::checkAndCreateDocument(data, size);
45
300
        if (!pdoc) {
46
0
            throw Exception(Status::FatalError("invalid json binary value: {}",
47
0
                                               std::string_view(data, size)));
48
0
        }
49
300
        return to_json_string(pdoc->getValue());
50
300
    }
51
52
326
    const std::string to_json_string(const JsonbValue* val) {
53
326
        os_.clear();
54
326
        os_.seekp(0);
55
56
326
        if (val) {
57
326
            intern_json(val);
58
326
        }
59
60
326
        os_.put(0);
61
62
326
        std::string json_string {os_.getBuffer()};
63
326
        return json_string;
64
326
    }
65
66
300
    static const std::string jsonb_to_json_string(const char* data, size_t size) {
67
300
        JsonbToJson jsonb_to_json;
68
300
        return jsonb_to_json.to_json_string(data, size);
69
300
    }
70
71
private:
72
    // recursively convert JsonbValue
73
743
    void intern_json(const JsonbValue* val) {
74
743
        switch (val->type()) {
75
33
        case JsonbType::T_Null: {
76
33
            os_.write("null", 4);
77
33
            break;
78
0
        }
79
35
        case JsonbType::T_True: {
80
35
            os_.write("true", 4);
81
35
            break;
82
0
        }
83
32
        case JsonbType::T_False: {
84
32
            os_.write("false", 5);
85
32
            break;
86
0
        }
87
99
        case JsonbType::T_Int8: {
88
99
            os_.write(((JsonbInt8Val*)val)->val());
89
99
            break;
90
0
        }
91
70
        case JsonbType::T_Int16: {
92
70
            os_.write(((JsonbInt16Val*)val)->val());
93
70
            break;
94
0
        }
95
18
        case JsonbType::T_Int32: {
96
18
            os_.write(((JsonbInt32Val*)val)->val());
97
18
            break;
98
0
        }
99
18
        case JsonbType::T_Int64: {
100
18
            os_.write(((JsonbInt64Val*)val)->val());
101
18
            break;
102
0
        }
103
81
        case JsonbType::T_Double: {
104
81
            os_.write(((JsonbDoubleVal*)val)->val());
105
81
            break;
106
0
        }
107
0
        case JsonbType::T_Float: {
108
0
            os_.write(((JsonbFloatVal*)val)->val());
109
0
            break;
110
0
        }
111
0
        case JsonbType::T_Int128: {
112
0
            os_.write(((JsonbInt128Val*)val)->val());
113
0
            break;
114
0
        }
115
149
        case JsonbType::T_String: {
116
149
            string_to_json(((JsonbStringVal*)val)->getBlob(), ((JsonbStringVal*)val)->length());
117
149
            break;
118
0
        }
119
0
        case JsonbType::T_Binary: {
120
0
            os_.write("\"<BINARY>", 9);
121
0
            os_.write(((JsonbBinaryVal*)val)->getBlob(), ((JsonbBinaryVal*)val)->getBlobLen());
122
0
            os_.write("<BINARY>\"", 9);
123
0
            break;
124
0
        }
125
115
        case JsonbType::T_Object: {
126
115
            object_to_json((ObjectVal*)val);
127
115
            break;
128
0
        }
129
93
        case JsonbType::T_Array: {
130
93
            array_to_json((ArrayVal*)val);
131
93
            break;
132
0
        }
133
0
        default:
134
0
            break;
135
743
        }
136
743
    }
137
138
301
    void string_to_json(const char* str, size_t len) {
139
301
        os_.put('"');
140
301
        if (nullptr == str) {
141
1
            os_.put('"');
142
1
            return;
143
1
        }
144
300
        char char_buffer[16];
145
1.00M
        for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) {
146
1.00M
            if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
147
1.00M
                os_.put(*ptr);
148
6
            else {
149
6
                os_.put('\\');
150
6
                unsigned char token;
151
6
                switch (token = *ptr) {
152
0
                case '\\':
153
0
                    os_.put('\\');
154
0
                    break;
155
1
                case '\"':
156
1
                    os_.put('\"');
157
1
                    break;
158
1
                case '\b':
159
1
                    os_.put('b');
160
1
                    break;
161
1
                case '\f':
162
1
                    os_.put('f');
163
1
                    break;
164
1
                case '\n':
165
1
                    os_.put('n');
166
1
                    break;
167
1
                case '\r':
168
1
                    os_.put('r');
169
1
                    break;
170
1
                case '\t':
171
1
                    os_.put('t');
172
1
                    break;
173
0
                default: {
174
0
                    int char_num = snprintf(char_buffer, sizeof(char_buffer), "u%04x", token);
175
0
                    os_.write(char_buffer, char_num);
176
0
                    break;
177
0
                }
178
6
                }
179
6
            }
180
1.00M
        }
181
300
        os_.put('"');
182
300
    }
183
184
    // convert object
185
115
    void object_to_json(const ObjectVal* val) {
186
115
        os_.put('{');
187
188
115
        auto iter = val->begin();
189
115
        auto iter_fence = val->end();
190
191
267
        while (iter < iter_fence) {
192
            // write key
193
152
            if (iter->klen()) {
194
151
                string_to_json(iter->getKeyStr(), iter->klen());
195
151
            } else {
196
                // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h
197
1
                if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) {
198
1
                    string_to_json(nullptr, 0);
199
1
                } else {
200
0
                    os_.write(iter->getKeyId());
201
0
                }
202
1
            }
203
152
            os_.put(':');
204
205
            // convert value
206
152
            intern_json(iter->value());
207
208
152
            ++iter;
209
152
            if (iter != iter_fence) {
210
59
                os_.put(',');
211
59
            }
212
152
        }
213
214
115
        assert(iter == iter_fence);
215
216
0
        os_.put('}');
217
115
    }
218
219
    // convert array to json
220
93
    void array_to_json(const ArrayVal* val) {
221
93
        os_.put('[');
222
223
93
        auto iter = val->begin();
224
93
        auto iter_fence = val->end();
225
226
358
        while (iter != iter_fence) {
227
            // convert value
228
265
            intern_json((const JsonbValue*)iter);
229
265
            ++iter;
230
265
            if (iter != iter_fence) {
231
187
                os_.put(',');
232
187
            }
233
265
        }
234
235
93
        assert(iter == iter_fence);
236
237
0
        os_.put(']');
238
93
    }
239
240
private:
241
    JsonbOutStream os_;
242
    char buffer_[OUT_BUF_SIZE];
243
};
244
245
// This class is a utility to create a JsonbValue.
246
template <class OS_TYPE>
247
class JsonbValueCreaterT {
248
public:
249
    JsonbValue* operator()(int32_t val) { return operator()((int64_t)val); }
250
251
    JsonbValue* operator()(int64_t val) {
252
        writer_.reset();
253
        writer_.writeStartArray();
254
        writer_.writeInt(val);
255
        writer_.writeEndArray();
256
        return extractValue();
257
    }
258
    JsonbValue* operator()(double val) {
259
        writer_.reset();
260
        writer_.writeStartArray();
261
        writer_.writeDouble(val);
262
        writer_.writeEndArray();
263
        return extractValue();
264
    }
265
    JsonbValue* operator()(const char* str) { return operator()(str, (unsigned int)strlen(str)); }
266
    JsonbValue* operator()(const char* str, unsigned int str_len) {
267
        writer_.reset();
268
        writer_.writeStartArray();
269
        writer_.writeStartString();
270
        writer_.writeString(str, str_len);
271
        writer_.writeEndString();
272
        writer_.writeEndArray();
273
        return extractValue();
274
    }
275
    JsonbValue* operator()(bool val) {
276
        writer_.reset();
277
        writer_.writeStartArray();
278
        writer_.writeBool(val);
279
        writer_.writeEndArray();
280
        return extractValue();
281
    }
282
    JsonbValue* operator()() {
283
        writer_.reset();
284
        writer_.writeStartArray();
285
        writer_.writeNull();
286
        writer_.writeEndArray();
287
        return extractValue();
288
    }
289
290
private:
291
    JsonbValue* extractValue() {
292
        return static_cast<ArrayVal*>(
293
                       JsonbDocument::createValue(writer_.getOutput()->getBuffer(),
294
                                                  (int)writer_.getOutput()->getSize()))
295
                ->get(0);
296
    }
297
    JsonbWriterT<OS_TYPE> writer_;
298
};
299
typedef JsonbValueCreaterT<JsonbOutStream> JsonbValueCreater;
300
} // namespace doris
301
302
#endif // JSONB_JSONBUTIL_H