Coverage Report

Created: 2026-07-28 21:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/key/row_key_encoder.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 "storage/key/row_key_encoder.h"
19
20
#include <cassert>
21
22
#include "common/cast_set.h"
23
#include "common/compiler_util.h" // IWYU pragma: keep
24
#include "common/consts.h"
25
#include "common/logging.h"
26
#include "storage/iterator/olap_data_convertor.h"
27
#include "storage/key_coder.h"
28
#include "storage/tablet/tablet_schema.h"
29
30
namespace doris {
31
32
RowKeyEncoder::RowKeyEncoder(const TabletSchema& schema, bool mow)
33
2.65k
        : _num_short_key_columns(schema.num_short_key_columns()) {
34
2.65k
    if (mow) {
35
141
        _init_mow(schema);
36
2.51k
    } else {
37
2.51k
        _init_non_mow(schema);
38
2.51k
    }
39
2.65k
}
40
41
RowKeyEncoder::RowKeyEncoder(const TabletSchema& schema)
42
10
        : _num_short_key_columns(schema.num_short_key_columns()) {
43
10
    _init_seq_coder(schema);
44
10
    _add_default_sort_key_columns(schema);
45
10
}
46
47
151
void RowKeyEncoder::_init_seq_coder(const TabletSchema& schema) {
48
    // encode the sequence id into the primary key index
49
151
    if (schema.has_sequence_col()) {
50
61
        const auto& column = schema.column(schema.sequence_col_idx());
51
61
        _seq_coder = get_key_coder(column.type());
52
61
        _seq_col_length = column.length();
53
61
    }
54
151
}
55
56
141
void RowKeyEncoder::_init_mow(const TabletSchema& schema) {
57
141
    _init_seq_coder(schema);
58
59
141
    if (schema.cluster_key_uids().empty()) {
60
133
        _add_default_sort_key_columns(schema);
61
133
        return;
62
133
    }
63
64
49
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
65
41
        _primary_key_coders.push_back(get_key_coder(schema.column(cid).type()));
66
41
    }
67
8
    _rowid_coder = get_key_coder(FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT);
68
47
    for (auto uid : schema.cluster_key_uids()) {
69
47
        _add_sort_key_column(schema.column_by_uid(uid));
70
47
    }
71
8
}
72
73
2.51k
void RowKeyEncoder::_init_non_mow(const TabletSchema& schema) {
74
2.51k
    _add_default_sort_key_columns(schema);
75
2.51k
}
76
77
2.66k
void RowKeyEncoder::_add_default_sort_key_columns(const TabletSchema& schema) {
78
5.06k
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
79
2.40k
        _add_sort_key_column(schema.column(cid));
80
2.40k
    }
81
2.66k
}
82
83
2.45k
void RowKeyEncoder::_add_sort_key_column(const TabletColumn& column) {
84
2.45k
    _sort_key_coders.push_back(get_key_coder(column.type()));
85
2.45k
    _sort_key_index_size.push_back(cast_set<uint16_t>(column.index_length()));
86
2.45k
}
87
88
std::string RowKeyEncoder::full_encode(const std::vector<IOlapColumnDataAccessor*>& key_columns,
89
7.45k
                                       size_t pos) const {
90
7.45k
    assert(_sort_key_index_size.size() == _sort_key_coders.size());
91
7.45k
    assert(key_columns.size() == _sort_key_coders.size());
92
7.45k
    return _full_encode(_sort_key_coders, key_columns, pos);
93
7.45k
}
94
95
std::string RowKeyEncoder::full_encode_primary_keys(
96
120
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
97
120
    return _full_encode(_primary_key_coders, key_columns, pos);
98
120
}
99
100
namespace {
101
// Shared row-key encoding base: for each key column, write a null marker for
102
// a null value, otherwise a normal marker followed by whatever `encode_field`
103
// appends. `encode_field(cid, field, out)` is the only thing that differs between
104
// the full key encode and the short-key prefix encode.
105
template <typename EncodeField>
106
std::string encode_key_columns(const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos,
107
21.1k
                               EncodeField&& encode_field) {
108
21.1k
    std::string encoded_keys;
109
21.1k
    size_t cid = 0;
110
31.4k
    for (const auto& column : key_columns) {
111
31.4k
        const auto* field = column->get_data_at(pos);
112
31.4k
        if (UNLIKELY(!field)) {
113
292
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
114
292
            ++cid;
115
292
            continue;
116
292
        }
117
31.1k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
118
31.1k
        encode_field(cid, field, &encoded_keys);
119
31.1k
        ++cid;
120
31.1k
    }
121
21.1k
    return encoded_keys;
122
21.1k
}
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNS_13RowKeyEncoder12_full_encodeB5cxx11ERKSt6vectorIPKNS_8KeyCoderESaIS6_EERKS3_IPNS_23IOlapColumnDataAccessorESaISC_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESG_mOT_
Line
Count
Source
107
7.57k
                               EncodeField&& encode_field) {
108
7.57k
    std::string encoded_keys;
109
7.57k
    size_t cid = 0;
110
15.0k
    for (const auto& column : key_columns) {
111
15.0k
        const auto* field = column->get_data_at(pos);
112
15.0k
        if (UNLIKELY(!field)) {
113
170
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
114
170
            ++cid;
115
170
            continue;
116
170
        }
117
14.8k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
118
14.8k
        encode_field(cid, field, &encoded_keys);
119
14.8k
        ++cid;
120
14.8k
    }
121
7.57k
    return encoded_keys;
122
7.57k
}
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNKS_13RowKeyEncoder17encode_short_keysB5cxx11ERKSt6vectorIPNS_23IOlapColumnDataAccessorESaIS5_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_mOT_
Line
Count
Source
107
13.5k
                               EncodeField&& encode_field) {
108
13.5k
    std::string encoded_keys;
109
13.5k
    size_t cid = 0;
110
16.4k
    for (const auto& column : key_columns) {
111
16.4k
        const auto* field = column->get_data_at(pos);
112
16.4k
        if (UNLIKELY(!field)) {
113
122
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
114
122
            ++cid;
115
122
            continue;
116
122
        }
117
16.3k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
118
16.3k
        encode_field(cid, field, &encoded_keys);
119
16.3k
        ++cid;
120
16.3k
    }
121
13.5k
    return encoded_keys;
122
13.5k
}
123
} // namespace
124
125
std::string RowKeyEncoder::_full_encode(const std::vector<const KeyCoder*>& key_coders,
126
                                        const std::vector<IOlapColumnDataAccessor*>& key_columns,
127
7.57k
                                        size_t pos) {
128
7.57k
    assert(key_columns.size() == key_coders.size());
129
7.57k
    return encode_key_columns(key_columns, pos,
130
14.8k
                              [&](size_t cid, const void* field, std::string* out) {
131
14.8k
                                  DCHECK(key_coders[cid] != nullptr);
132
14.8k
                                  key_coders[cid]->full_encode_ascending(field, out);
133
14.8k
                              });
134
7.57k
}
135
136
std::string RowKeyEncoder::encode_short_keys(
137
13.5k
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
138
13.5k
    assert(key_columns.size() == _num_short_key_columns);
139
13.5k
    assert(key_columns.size() <= _sort_key_coders.size());
140
13.5k
    return encode_key_columns(
141
16.3k
            key_columns, pos, [&](size_t cid, const void* field, std::string* out) {
142
16.3k
                _sort_key_coders[cid]->encode_ascending(field, _sort_key_index_size[cid], out);
143
16.3k
            });
144
13.5k
}
145
146
void RowKeyEncoder::append_seq_suffix(std::string* encoded_keys,
147
164
                                      const IOlapColumnDataAccessor* seq_column, size_t pos) const {
148
164
    const auto* field = seq_column->get_data_at(pos);
149
    // So the primary key index can still use it, encode a null seq column as
150
    // the smallest value of its length.
151
164
    if (UNLIKELY(!field)) {
152
12
        encoded_keys->push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
153
12
        encoded_keys->append(_seq_col_length, KeyConsts::KEY_MINIMAL_MARKER);
154
12
        return;
155
12
    }
156
152
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
157
152
    _seq_coder->full_encode_ascending(field, encoded_keys);
158
152
}
159
160
118
void RowKeyEncoder::append_rowid_suffix(std::string* encoded_keys, uint32_t rowid) const {
161
118
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
162
118
    _rowid_coder->full_encode_ascending(&rowid, encoded_keys);
163
118
}
164
165
} // namespace doris