Coverage Report

Created: 2026-09-29 12:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/format/parquet/decoder.h
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
#pragma once
19
20
#include <gen_cpp/parquet_types.h>
21
#include <glog/logging.h>
22
23
#include <cstddef>
24
#include <cstdint>
25
#include <memory>
26
#include <ostream>
27
#include <vector>
28
29
#include "common/status.h"
30
#include "core/assert_cast.h"
31
#include "core/column/column.h"
32
#include "core/column/column_dictionary.h"
33
#include "core/column/column_vector.h"
34
#include "core/custom_allocator.h"
35
#include "core/data_type/data_type.h"
36
#include "core/data_type/data_type_decimal.h" // IWYU pragma: keep
37
#include "core/data_type/data_type_nullable.h"
38
#include "core/pod_array_fwd.h"
39
#include "core/types.h"
40
#include "format/parquet/parquet_common.h"
41
#include "util/slice.h"
42
43
namespace doris {
44
template <typename T>
45
class ColumnStr;
46
using ColumnString = ColumnStr<UInt32>;
47
template <typename T>
48
class RleBatchDecoder;
49
50
class Decoder {
51
public:
52
778
    Decoder() = default;
53
754
    virtual ~Decoder() = default;
54
55
    static Status get_decoder(tparquet::Type::type type, tparquet::Encoding::type encoding,
56
                              std::unique_ptr<Decoder>& decoder);
57
58
    // The type with fix length
59
540
    void set_type_length(int32_t type_length) { _type_length = type_length; }
60
61
    // Set the data to be decoded
62
268
    virtual Status set_data(Slice* data) {
63
268
        _data = data;
64
268
        _offset = 0;
65
268
        return Status::OK();
66
268
    }
67
68
    // Write the decoded values batch to doris's column
69
    virtual Status decode_values(MutableColumnPtr& doris_column, DataTypePtr& data_type,
70
                                 ColumnSelectVector& select_vector, bool is_dict_filter) = 0;
71
72
    virtual Status skip_values(size_t num_values) = 0;
73
74
    virtual Status set_dict(DorisUniqueBufferPtr<uint8_t>& dict, int32_t length,
75
0
                            size_t num_values) {
76
0
        return Status::NotSupported("set_dict is not supported");
77
0
    }
78
79
0
    virtual Status read_dict_values_to_column(MutableColumnPtr& doris_column) {
80
0
        return Status::NotSupported("read_dict_values_to_column is not supported");
81
0
    }
82
83
    virtual Result<MutableColumnPtr> convert_dict_column_to_string_column(
84
0
            const ColumnInt32* dict_column) {
85
0
        throw doris::Exception(ErrorCode::NOT_IMPLEMENTED_ERROR,
86
0
                               "Method convert_dict_column_to_string_column is not supported");
87
0
    }
88
89
protected:
90
    int32_t _type_length;
91
    Slice* _data = nullptr;
92
    uint32_t _offset = 0;
93
};
94
95
class BaseDictDecoder : public Decoder {
96
public:
97
    // Out-of-line: member unique_ptr<RleBatchDecoder<uint32_t>> only needs the
98
    // complete type where the ctor/dtor/set_data/skip_values are defined (decoder.cpp),
99
    // keeping the costly RLE template machinery out of every includer of this header.
100
    // The ctor counts: a defaulted-in-class one would be defined in every TU that
101
    // constructs a derived decoder, and it odr-uses the member's destructor.
102
    BaseDictDecoder();
103
    ~BaseDictDecoder() override;
104
105
    // Set the data to be decoded
106
    Status set_data(Slice* data) override;
107
108
protected:
109
    /**
110
     * Decode dictionary-coded values into doris_column, ensure that doris_column is ColumnDictI32 type,
111
     * and the coded values must be read into _indexes previously.
112
     */
113
    template <bool has_filter>
114
    Status _decode_dict_values(MutableColumnPtr& doris_column, ColumnSelectVector& select_vector,
115
32
                               bool is_dict_filter) {
116
32
        DCHECK(doris_column->is_column_dictionary() || is_dict_filter);
117
32
        size_t dict_index = 0;
118
32
        ColumnSelectVector::DataReadType read_type;
119
32
        PaddedPODArray<Int32>& column_data =
120
32
                doris_column->is_column_dictionary()
121
32
                        ? assert_cast<ColumnDictI32&>(*doris_column).get_data()
122
32
                        : assert_cast<ColumnInt32&>(*doris_column).get_data();
123
146
        while (size_t run_length = select_vector.get_next_run<has_filter>(&read_type)) {
124
114
            switch (read_type) {
125
64
            case ColumnSelectVector::CONTENT: {
126
64
                uint32_t* start_index = _indexes.data();
127
64
                column_data.insert(start_index + dict_index, start_index + dict_index + run_length);
128
64
                dict_index += run_length;
129
64
                break;
130
0
            }
131
18
            case ColumnSelectVector::NULL_DATA: {
132
18
                doris_column->insert_many_defaults(run_length);
133
18
                break;
134
0
            }
135
32
            case ColumnSelectVector::FILTERED_CONTENT: {
136
32
                dict_index += run_length;
137
32
                break;
138
0
            }
139
0
            case ColumnSelectVector::FILTERED_NULL: {
140
0
                break;
141
0
            }
142
114
            }
143
114
        }
144
32
        return Status::OK();
145
32
    }
_ZN5doris15BaseDictDecoder19_decode_dict_valuesILb1EEENS_6StatusERNS_3COWINS_7IColumnEE11mutable_ptrIS4_EERNS_18ColumnSelectVectorEb
Line
Count
Source
115
16
                               bool is_dict_filter) {
116
16
        DCHECK(doris_column->is_column_dictionary() || is_dict_filter);
117
16
        size_t dict_index = 0;
118
16
        ColumnSelectVector::DataReadType read_type;
119
16
        PaddedPODArray<Int32>& column_data =
120
16
                doris_column->is_column_dictionary()
121
16
                        ? assert_cast<ColumnDictI32&>(*doris_column).get_data()
122
16
                        : assert_cast<ColumnInt32&>(*doris_column).get_data();
123
112
        while (size_t run_length = select_vector.get_next_run<has_filter>(&read_type)) {
124
96
            switch (read_type) {
125
48
            case ColumnSelectVector::CONTENT: {
126
48
                uint32_t* start_index = _indexes.data();
127
48
                column_data.insert(start_index + dict_index, start_index + dict_index + run_length);
128
48
                dict_index += run_length;
129
48
                break;
130
0
            }
131
16
            case ColumnSelectVector::NULL_DATA: {
132
16
                doris_column->insert_many_defaults(run_length);
133
16
                break;
134
0
            }
135
32
            case ColumnSelectVector::FILTERED_CONTENT: {
136
32
                dict_index += run_length;
137
32
                break;
138
0
            }
139
0
            case ColumnSelectVector::FILTERED_NULL: {
140
0
                break;
141
0
            }
142
96
            }
143
96
        }
144
16
        return Status::OK();
145
16
    }
_ZN5doris15BaseDictDecoder19_decode_dict_valuesILb0EEENS_6StatusERNS_3COWINS_7IColumnEE11mutable_ptrIS4_EERNS_18ColumnSelectVectorEb
Line
Count
Source
115
16
                               bool is_dict_filter) {
116
16
        DCHECK(doris_column->is_column_dictionary() || is_dict_filter);
117
16
        size_t dict_index = 0;
118
16
        ColumnSelectVector::DataReadType read_type;
119
16
        PaddedPODArray<Int32>& column_data =
120
16
                doris_column->is_column_dictionary()
121
16
                        ? assert_cast<ColumnDictI32&>(*doris_column).get_data()
122
16
                        : assert_cast<ColumnInt32&>(*doris_column).get_data();
123
34
        while (size_t run_length = select_vector.get_next_run<has_filter>(&read_type)) {
124
18
            switch (read_type) {
125
16
            case ColumnSelectVector::CONTENT: {
126
16
                uint32_t* start_index = _indexes.data();
127
16
                column_data.insert(start_index + dict_index, start_index + dict_index + run_length);
128
16
                dict_index += run_length;
129
16
                break;
130
0
            }
131
2
            case ColumnSelectVector::NULL_DATA: {
132
2
                doris_column->insert_many_defaults(run_length);
133
2
                break;
134
0
            }
135
0
            case ColumnSelectVector::FILTERED_CONTENT: {
136
0
                dict_index += run_length;
137
0
                break;
138
0
            }
139
0
            case ColumnSelectVector::FILTERED_NULL: {
140
0
                break;
141
0
            }
142
18
            }
143
18
        }
144
16
        return Status::OK();
145
16
    }
146
147
    Status skip_values(size_t num_values) override;
148
149
    // For dictionary encoding
150
    DorisUniqueBufferPtr<uint8_t> _dict;
151
    std::unique_ptr<RleBatchDecoder<uint32_t>> _index_batch_decoder;
152
    std::vector<uint32_t> _indexes;
153
};
154
155
} // namespace doris