Coverage Report

Created: 2025-07-23 19:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/util/jsonb_document.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "jsonb_document.h"
19
20
#include <memory>
21
#include <vector>
22
23
#include "common/status.h"
24
#include "util/jsonb_writer.h"
25
26
namespace doris {
27
95
JsonbFindResult JsonbValue::findValue(JsonbPath& path) const {
28
95
    JsonbFindResult result;
29
95
    bool is_wildcard = false;
30
31
95
    std::vector<const JsonbValue*> values;
32
95
    std::vector<const JsonbValue*> results;
33
95
    results.emplace_back(this);
34
35
185
    for (size_t i = 0; i < path.get_leg_vector_size(); ++i) {
36
90
        values.assign(results.begin(), results.end());
37
90
        results.clear();
38
90
        for (const auto* pval : values) {
39
89
            switch (path.get_leg_from_leg_vector(i)->type) {
40
31
            case MEMBER_CODE: {
41
31
                if (LIKELY(pval->type == JsonbType::T_Object)) {
42
5
                    if (path.get_leg_from_leg_vector(i)->leg_len == 1 &&
43
5
                        *path.get_leg_from_leg_vector(i)->leg_ptr == WILDCARD) {
44
0
                        is_wildcard = true;
45
0
                        for (const auto& it : *pval->unpack<ObjectVal>()) {
46
0
                            results.emplace_back(it.value());
47
0
                        }
48
0
                        continue;
49
0
                    }
50
51
5
                    pval = pval->unpack<ObjectVal>()->find(path.get_leg_from_leg_vector(i)->leg_ptr,
52
5
                                                           path.get_leg_from_leg_vector(i)->leg_len,
53
5
                                                           nullptr);
54
55
5
                    if (pval) {
56
3
                        results.emplace_back(pval);
57
3
                    }
58
5
                }
59
31
                continue;
60
31
            }
61
58
            case ARRAY_CODE: {
62
58
                if (path.get_leg_from_leg_vector(i)->leg_len == 1 &&
63
58
                    *path.get_leg_from_leg_vector(i)->leg_ptr == WILDCARD) {
64
0
                    if (LIKELY(pval->type == JsonbType::T_Array)) {
65
0
                        is_wildcard = true;
66
0
                        for (const auto& it : *pval->unpack<ArrayVal>()) {
67
0
                            results.emplace_back(&it);
68
0
                        }
69
0
                    }
70
0
                    continue;
71
0
                }
72
73
58
                if (pval->type != JsonbType::T_Array &&
74
58
                    path.get_leg_from_leg_vector(i)->array_index == 0) {
75
                    // Same as mysql and postgres
76
22
                    results.emplace_back(pval);
77
22
                    continue;
78
22
                }
79
80
36
                if (pval->type != JsonbType::T_Array ||
81
36
                    path.get_leg_from_leg_vector(i)->leg_ptr != nullptr ||
82
36
                    path.get_leg_from_leg_vector(i)->leg_len != 0) {
83
11
                    continue;
84
11
                }
85
86
25
                if (path.get_leg_from_leg_vector(i)->array_index >= 0) {
87
25
                    pval = pval->unpack<ArrayVal>()->get(
88
25
                            path.get_leg_from_leg_vector(i)->array_index);
89
25
                } else {
90
0
                    pval = pval->unpack<ArrayVal>()->get(
91
0
                            pval->unpack<ArrayVal>()->numElem() +
92
0
                            path.get_leg_from_leg_vector(i)->array_index);
93
0
                }
94
95
25
                if (pval) {
96
18
                    results.emplace_back(pval);
97
18
                }
98
25
                continue;
99
36
            }
100
89
            }
101
89
        }
102
90
    }
103
104
95
    if (is_wildcard) {
105
0
        result.is_wildcard = true;
106
0
        if (results.empty()) {
107
0
            result.value = nullptr; // No values found
108
0
        } else {
109
0
            result.writer = std::make_unique<JsonbWriter>();
110
0
            result.writer->writeStartArray();
111
0
            for (const auto* pval : results) {
112
0
                result.writer->writeValue(pval);
113
0
            }
114
0
            result.writer->writeEndArray();
115
116
0
            JsonbDocument* doc = nullptr;
117
0
            THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument(
118
0
                    result.writer->getOutput()->getBuffer(), result.writer->getOutput()->getSize(),
119
0
                    &doc));
120
0
            result.value = doc->getValue();
121
0
        }
122
95
    } else if (results.size() == 1) {
123
49
        result.value = results[0];
124
49
    }
125
126
95
    return result;
127
95
}
128
} // namespace doris