Coverage Report

Created: 2025-09-12 18:53

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
95
    if (path.is_supper_wildcard()) {
36
0
        std::function<void(const JsonbValue*)> foreach_values;
37
0
        foreach_values = [&](const JsonbValue* val) {
38
0
            if (val->isObject()) {
39
0
                for (const auto& it : *val->unpack<ObjectVal>()) {
40
0
                    results.emplace_back(it.value());
41
0
                    foreach_values(it.value());
42
0
                }
43
0
            } else if (val->isArray()) {
44
0
                for (const auto& it : *val->unpack<ArrayVal>()) {
45
0
                    results.emplace_back(&it);
46
0
                    foreach_values(&it);
47
0
                }
48
0
            }
49
0
        };
50
0
        is_wildcard = true;
51
0
        foreach_values(this);
52
0
    }
53
54
185
    for (size_t i = 0; i < path.get_leg_vector_size(); ++i) {
55
90
        values = std::move(results);
56
90
        for (const auto* pval : values) {
57
89
            switch (path.get_leg_from_leg_vector(i)->type) {
58
31
            case MEMBER_CODE: {
59
31
                if (LIKELY(pval->type == JsonbType::T_Object)) {
60
5
                    if (path.get_leg_from_leg_vector(i)->leg_len == 1 &&
61
5
                        *path.get_leg_from_leg_vector(i)->leg_ptr == WILDCARD) {
62
0
                        is_wildcard = true;
63
0
                        for (const auto& it : *pval->unpack<ObjectVal>()) {
64
0
                            results.emplace_back(it.value());
65
0
                        }
66
0
                        continue;
67
0
                    }
68
69
5
                    pval = pval->unpack<ObjectVal>()->find(path.get_leg_from_leg_vector(i)->leg_ptr,
70
5
                                                           path.get_leg_from_leg_vector(i)->leg_len,
71
5
                                                           nullptr);
72
73
5
                    if (pval) {
74
3
                        results.emplace_back(pval);
75
3
                    }
76
5
                }
77
31
                continue;
78
31
            }
79
58
            case ARRAY_CODE: {
80
58
                if (path.get_leg_from_leg_vector(i)->leg_len == 1 &&
81
58
                    *path.get_leg_from_leg_vector(i)->leg_ptr == WILDCARD) {
82
0
                    if (LIKELY(pval->type == JsonbType::T_Array)) {
83
0
                        is_wildcard = true;
84
0
                        for (const auto& it : *pval->unpack<ArrayVal>()) {
85
0
                            results.emplace_back(&it);
86
0
                        }
87
0
                    }
88
0
                    continue;
89
0
                }
90
91
58
                if (pval->type != JsonbType::T_Array &&
92
58
                    path.get_leg_from_leg_vector(i)->array_index == 0) {
93
                    // Same as mysql and postgres
94
22
                    results.emplace_back(pval);
95
22
                    continue;
96
22
                }
97
98
36
                if (pval->type != JsonbType::T_Array ||
99
36
                    path.get_leg_from_leg_vector(i)->leg_ptr != nullptr ||
100
36
                    path.get_leg_from_leg_vector(i)->leg_len != 0) {
101
11
                    continue;
102
11
                }
103
104
25
                if (path.get_leg_from_leg_vector(i)->array_index >= 0) {
105
25
                    pval = pval->unpack<ArrayVal>()->get(
106
25
                            path.get_leg_from_leg_vector(i)->array_index);
107
25
                } else {
108
0
                    pval = pval->unpack<ArrayVal>()->get(
109
0
                            pval->unpack<ArrayVal>()->numElem() +
110
0
                            path.get_leg_from_leg_vector(i)->array_index);
111
0
                }
112
113
25
                if (pval) {
114
18
                    results.emplace_back(pval);
115
18
                }
116
25
                continue;
117
36
            }
118
89
            }
119
89
        }
120
90
    }
121
122
95
    if (is_wildcard) {
123
0
        result.is_wildcard = true;
124
0
        if (results.empty()) {
125
0
            result.value = nullptr; // No values found
126
0
        } else {
127
0
            result.writer = std::make_unique<JsonbWriter>();
128
0
            result.writer->writeStartArray();
129
0
            for (const auto* pval : results) {
130
0
                result.writer->writeValue(pval);
131
0
            }
132
0
            result.writer->writeEndArray();
133
134
0
            JsonbDocument* doc = nullptr;
135
0
            THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument(
136
0
                    result.writer->getOutput()->getBuffer(), result.writer->getOutput()->getSize(),
137
0
                    &doc));
138
0
            result.value = doc->getValue();
139
0
        }
140
95
    } else if (results.size() == 1) {
141
49
        result.value = results[0];
142
49
    }
143
144
95
    return result;
145
95
}
146
} // namespace doris