Coverage Report

Created: 2026-07-28 13:11

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.61k
        : _num_short_key_columns(schema.num_short_key_columns()) {
34
2.61k
    if (mow) {
35
98
        _init_mow(schema);
36
2.51k
    } else {
37
2.51k
        _init_non_mow(schema);
38
2.51k
    }
39
2.61k
}
40
41
98
void RowKeyEncoder::_init_mow(const TabletSchema& schema) {
42
    // encode the sequence id into the primary key index
43
98
    if (schema.has_sequence_col()) {
44
42
        const auto& column = schema.column(schema.sequence_col_idx());
45
42
        _seq_coder = get_key_coder(column.type());
46
42
        _seq_col_length = column.length();
47
42
    }
48
49
98
    if (schema.cluster_key_uids().empty()) {
50
91
        _add_default_sort_key_columns(schema);
51
91
        return;
52
91
    }
53
54
47
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
55
40
        _primary_key_coders.push_back(get_key_coder(schema.column(cid).type()));
56
40
    }
57
7
    _rowid_coder = get_key_coder(FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT);
58
43
    for (auto uid : schema.cluster_key_uids()) {
59
43
        _add_sort_key_column(schema.column_by_uid(uid));
60
43
    }
61
7
}
62
63
2.51k
void RowKeyEncoder::_init_non_mow(const TabletSchema& schema) {
64
2.51k
    _add_default_sort_key_columns(schema);
65
2.51k
}
66
67
2.60k
void RowKeyEncoder::_add_default_sort_key_columns(const TabletSchema& schema) {
68
4.95k
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
69
2.34k
        _add_sort_key_column(schema.column(cid));
70
2.34k
    }
71
2.60k
}
72
73
2.39k
void RowKeyEncoder::_add_sort_key_column(const TabletColumn& column) {
74
2.39k
    _sort_key_coders.push_back(get_key_coder(column.type()));
75
2.39k
    _sort_key_index_size.push_back(cast_set<uint16_t>(column.index_length()));
76
2.39k
}
77
78
std::string RowKeyEncoder::full_encode(const std::vector<IOlapColumnDataAccessor*>& key_columns,
79
7.38k
                                       size_t pos) const {
80
7.38k
    assert(_sort_key_index_size.size() == _sort_key_coders.size());
81
7.38k
    assert(key_columns.size() == _sort_key_coders.size());
82
7.38k
    return _full_encode(_sort_key_coders, key_columns, pos);
83
7.38k
}
84
85
std::string RowKeyEncoder::full_encode_primary_keys(
86
118
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
87
118
    return _full_encode(_primary_key_coders, key_columns, pos);
88
118
}
89
90
namespace {
91
// Shared row-key encoding base: for each key column, write a null marker for
92
// a null value, otherwise a normal marker followed by whatever `encode_field`
93
// appends. `encode_field(cid, field, out)` is the only thing that differs between
94
// the full key encode and the short-key prefix encode.
95
template <typename EncodeField>
96
std::string encode_key_columns(const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos,
97
21.0k
                               EncodeField&& encode_field) {
98
21.0k
    std::string encoded_keys;
99
21.0k
    size_t cid = 0;
100
31.3k
    for (const auto& column : key_columns) {
101
31.3k
        const auto* field = column->get_data_at(pos);
102
31.3k
        if (UNLIKELY(!field)) {
103
292
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
104
292
            ++cid;
105
292
            continue;
106
292
        }
107
31.1k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
108
31.1k
        encode_field(cid, field, &encoded_keys);
109
31.1k
        ++cid;
110
31.1k
    }
111
21.0k
    return encoded_keys;
112
21.0k
}
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
97
7.49k
                               EncodeField&& encode_field) {
98
7.49k
    std::string encoded_keys;
99
7.49k
    size_t cid = 0;
100
14.9k
    for (const auto& column : key_columns) {
101
14.9k
        const auto* field = column->get_data_at(pos);
102
14.9k
        if (UNLIKELY(!field)) {
103
170
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
104
170
            ++cid;
105
170
            continue;
106
170
        }
107
14.7k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
108
14.7k
        encode_field(cid, field, &encoded_keys);
109
14.7k
        ++cid;
110
14.7k
    }
111
7.49k
    return encoded_keys;
112
7.49k
}
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNKS_13RowKeyEncoder17encode_short_keysB5cxx11ERKSt6vectorIPNS_23IOlapColumnDataAccessorESaIS5_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_mOT_
Line
Count
Source
97
13.5k
                               EncodeField&& encode_field) {
98
13.5k
    std::string encoded_keys;
99
13.5k
    size_t cid = 0;
100
16.4k
    for (const auto& column : key_columns) {
101
16.4k
        const auto* field = column->get_data_at(pos);
102
16.4k
        if (UNLIKELY(!field)) {
103
122
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
104
122
            ++cid;
105
122
            continue;
106
122
        }
107
16.3k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
108
16.3k
        encode_field(cid, field, &encoded_keys);
109
16.3k
        ++cid;
110
16.3k
    }
111
13.5k
    return encoded_keys;
112
13.5k
}
113
} // namespace
114
115
std::string RowKeyEncoder::_full_encode(const std::vector<const KeyCoder*>& key_coders,
116
                                        const std::vector<IOlapColumnDataAccessor*>& key_columns,
117
7.49k
                                        size_t pos) {
118
7.49k
    assert(key_columns.size() == key_coders.size());
119
7.49k
    return encode_key_columns(key_columns, pos,
120
14.7k
                              [&](size_t cid, const void* field, std::string* out) {
121
14.7k
                                  DCHECK(key_coders[cid] != nullptr);
122
14.7k
                                  key_coders[cid]->full_encode_ascending(field, out);
123
14.7k
                              });
124
7.49k
}
125
126
std::string RowKeyEncoder::encode_short_keys(
127
13.5k
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
128
13.5k
    assert(key_columns.size() == _num_short_key_columns);
129
13.5k
    assert(key_columns.size() <= _sort_key_coders.size());
130
13.5k
    return encode_key_columns(
131
16.3k
            key_columns, pos, [&](size_t cid, const void* field, std::string* out) {
132
16.3k
                _sort_key_coders[cid]->encode_ascending(field, _sort_key_index_size[cid], out);
133
16.3k
            });
134
13.5k
}
135
136
void RowKeyEncoder::append_seq_suffix(std::string* encoded_keys,
137
141
                                      const IOlapColumnDataAccessor* seq_column, size_t pos) const {
138
141
    const auto* field = seq_column->get_data_at(pos);
139
    // So the primary key index can still use it, encode a null seq column as
140
    // the smallest value of its length.
141
141
    if (UNLIKELY(!field)) {
142
12
        encoded_keys->push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
143
12
        encoded_keys->append(_seq_col_length, KeyConsts::KEY_MINIMAL_MARKER);
144
12
        return;
145
12
    }
146
129
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
147
129
    _seq_coder->full_encode_ascending(field, encoded_keys);
148
129
}
149
150
118
void RowKeyEncoder::append_rowid_suffix(std::string* encoded_keys, uint32_t rowid) const {
151
118
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
152
118
    _rowid_coder->full_encode_ascending(&rowid, encoded_keys);
153
118
}
154
155
} // namespace doris