Coverage Report

Created: 2026-10-22 05:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/common/histogram_helpers.hpp
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 <rapidjson/document.h>
21
#include <rapidjson/prettywriter.h>
22
#include <rapidjson/stringbuffer.h>
23
24
#include <boost/dynamic_bitset.hpp>
25
26
#include "common/cast_set.h"
27
#include "core/data_type/data_type_decimal.h"
28
29
namespace doris {
30
template <typename T>
31
struct Bucket {
32
public:
33
    Bucket() = default;
34
    Bucket(T lower, T upper, size_t ndv, size_t count, size_t pre_sum)
35
468
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_7DecimalIiEEEC2ES2_S2_mmm
Line
Count
Source
35
25
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
Unexecuted instantiation: _ZN5doris6BucketINS_7DecimalIlEEEC2ES2_S2_mmm
Unexecuted instantiation: _ZN5doris6BucketINS_12Decimal128V3EEC2ES1_S1_mmm
Unexecuted instantiation: _ZN5doris6BucketINS_7DecimalIN4wide7integerILm256EiEEEEEC2ES5_S5_mmm
_ZN5doris6BucketINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2ES6_S6_mmm
Line
Count
Source
35
60
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_11DateV2ValueINS_15DateV2ValueTypeEEEEC2ES3_S3_mmm
Line
Count
Source
35
40
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEC2ES3_S3_mmm
Line
Count
Source
35
39
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
Unexecuted instantiation: _ZN5doris6BucketINS_16TimeStampNsValueEEC2ES1_S1_mmm
Unexecuted instantiation: _ZN5doris6BucketINS_16TimestampTzValueEEC2ES1_S1_mmm
_ZN5doris6BucketIhEC2Ehhmmm
Line
Count
Source
35
2
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIaEC2Eaammm
Line
Count
Source
35
21
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIsEC2Essmmm
Line
Count
Source
35
24
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIiEC2Eiimmm
Line
Count
Source
35
60
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIlEC2Ellmmm
Line
Count
Source
35
104
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketInEC2Ennmmm
Line
Count
Source
35
33
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIfEC2Effmmm
Line
Count
Source
35
20
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIdEC2Eddmmm
Line
Count
Source
35
20
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIoEC2Eoommm
Line
Count
Source
35
20
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
36
37
    T lower;
38
    T upper;
39
    size_t ndv;
40
    size_t count;
41
    size_t pre_sum;
42
};
43
44
/**
45
 * Checks if it is possible to assign the provided value_map to the given
46
 * number of buckets such that no bucket has a size larger than max_bucket_size.
47
 *
48
 * @param value_map A mapping of values to their counts.
49
 * @param max_bucket_size The maximum size that any bucket is allowed to have.
50
 * @param num_buckets The number of buckets that we want to assign values to.
51
 *
52
 * @return true if the values can be assigned to the buckets, false otherwise.
53
 */
54
template <typename T>
55
bool can_assign_into_buckets(const std::map<T, size_t>& value_map, const size_t max_bucket_size,
56
519
                             const size_t num_buckets) {
57
519
    if (value_map.empty()) {
58
1
        return false;
59
518
    };
60
61
518
    size_t used_buckets = 1;
62
518
    size_t current_bucket_size = 0;
63
64
30.1k
    for (const auto& [value, count] : value_map) {
65
30.1k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
30.1k
        if (current_bucket_size > max_bucket_size) {
70
1.15k
            ++used_buckets;
71
1.15k
            current_bucket_size = count;
72
1.15k
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
30.1k
        if (used_buckets > num_buckets) {
76
222
            return false;
77
222
        }
78
30.1k
    }
79
80
296
    return true;
81
518
}
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsIhEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
_ZN5doris23can_assign_into_bucketsIaEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
27
                             const size_t num_buckets) {
57
27
    if (value_map.empty()) {
58
0
        return false;
59
27
    };
60
61
27
    size_t used_buckets = 1;
62
27
    size_t current_bucket_size = 0;
63
64
1.24k
    for (const auto& [value, count] : value_map) {
65
1.24k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.24k
        if (current_bucket_size > max_bucket_size) {
70
70
            ++used_buckets;
71
70
            current_bucket_size = count;
72
70
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.24k
        if (used_buckets > num_buckets) {
76
11
            return false;
77
11
        }
78
1.24k
    }
79
80
16
    return true;
81
27
}
_ZN5doris23can_assign_into_bucketsIsEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
40
                             const size_t num_buckets) {
57
40
    if (value_map.empty()) {
58
0
        return false;
59
40
    };
60
61
40
    size_t used_buckets = 1;
62
40
    size_t current_bucket_size = 0;
63
64
1.34k
    for (const auto& [value, count] : value_map) {
65
1.34k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.34k
        if (current_bucket_size > max_bucket_size) {
70
88
            ++used_buckets;
71
88
            current_bucket_size = count;
72
88
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.34k
        if (used_buckets > num_buckets) {
76
18
            return false;
77
18
        }
78
1.34k
    }
79
80
22
    return true;
81
40
}
_ZN5doris23can_assign_into_bucketsIiEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
83
                             const size_t num_buckets) {
57
83
    if (value_map.empty()) {
58
1
        return false;
59
82
    };
60
61
82
    size_t used_buckets = 1;
62
82
    size_t current_bucket_size = 0;
63
64
1.42k
    for (const auto& [value, count] : value_map) {
65
1.42k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.42k
        if (current_bucket_size > max_bucket_size) {
70
171
            ++used_buckets;
71
171
            current_bucket_size = count;
72
171
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.42k
        if (used_buckets > num_buckets) {
76
30
            return false;
77
30
        }
78
1.42k
    }
79
80
52
    return true;
81
82
}
_ZN5doris23can_assign_into_bucketsIlEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
34
                             const size_t num_buckets) {
57
34
    if (value_map.empty()) {
58
0
        return false;
59
34
    };
60
61
34
    size_t used_buckets = 1;
62
34
    size_t current_bucket_size = 0;
63
64
1.29k
    for (const auto& [value, count] : value_map) {
65
1.29k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.29k
        if (current_bucket_size > max_bucket_size) {
70
90
            ++used_buckets;
71
90
            current_bucket_size = count;
72
90
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.29k
        if (used_buckets > num_buckets) {
76
17
            return false;
77
17
        }
78
1.29k
    }
79
80
17
    return true;
81
34
}
_ZN5doris23can_assign_into_bucketsInEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
32
                             const size_t num_buckets) {
57
32
    if (value_map.empty()) {
58
0
        return false;
59
32
    };
60
61
32
    size_t used_buckets = 1;
62
32
    size_t current_bucket_size = 0;
63
64
1.28k
    for (const auto& [value, count] : value_map) {
65
1.28k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.28k
        if (current_bucket_size > max_bucket_size) {
70
96
            ++used_buckets;
71
96
            current_bucket_size = count;
72
96
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.28k
        if (used_buckets > num_buckets) {
76
15
            return false;
77
15
        }
78
1.28k
    }
79
80
17
    return true;
81
32
}
_ZN5doris23can_assign_into_bucketsIfEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
31
                             const size_t num_buckets) {
57
31
    if (value_map.empty()) {
58
0
        return false;
59
31
    };
60
61
31
    size_t used_buckets = 1;
62
31
    size_t current_bucket_size = 0;
63
64
1.25k
    for (const auto& [value, count] : value_map) {
65
1.25k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.25k
        if (current_bucket_size > max_bucket_size) {
70
78
            ++used_buckets;
71
78
            current_bucket_size = count;
72
78
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.25k
        if (used_buckets > num_buckets) {
76
15
            return false;
77
15
        }
78
1.25k
    }
79
80
16
    return true;
81
31
}
_ZN5doris23can_assign_into_bucketsIdEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
31
                             const size_t num_buckets) {
57
31
    if (value_map.empty()) {
58
0
        return false;
59
31
    };
60
61
31
    size_t used_buckets = 1;
62
31
    size_t current_bucket_size = 0;
63
64
1.25k
    for (const auto& [value, count] : value_map) {
65
1.25k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.25k
        if (current_bucket_size > max_bucket_size) {
70
78
            ++used_buckets;
71
78
            current_bucket_size = count;
72
78
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.25k
        if (used_buckets > num_buckets) {
76
15
            return false;
77
15
        }
78
1.25k
    }
79
80
16
    return true;
81
31
}
_ZN5doris23can_assign_into_bucketsINS_7DecimalIiEEEEbRKSt3mapIT_mSt4lessIS4_ESaISt4pairIKS4_mEEEmm
Line
Count
Source
56
39
                             const size_t num_buckets) {
57
39
    if (value_map.empty()) {
58
0
        return false;
59
39
    };
60
61
39
    size_t used_buckets = 1;
62
39
    size_t current_bucket_size = 0;
63
64
161
    for (const auto& [value, count] : value_map) {
65
161
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
161
        if (current_bucket_size > max_bucket_size) {
70
54
            ++used_buckets;
71
54
            current_bucket_size = count;
72
54
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
161
        if (used_buckets > num_buckets) {
76
17
            return false;
77
17
        }
78
161
    }
79
80
22
    return true;
81
39
}
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_7DecimalIlEEEEbRKSt3mapIT_mSt4lessIS4_ESaISt4pairIKS4_mEEEmm
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_12Decimal128V3EEEbRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEmm
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_7DecimalIN4wide7integerILm256EiEEEEEEbRKSt3mapIT_mSt4lessIS7_ESaISt4pairIKS7_mEEEmm
_ZN5doris23can_assign_into_bucketsINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKSt3mapIT_mSt4lessIS8_ESaISt4pairIKS8_mEEEmm
Line
Count
Source
56
100
                             const size_t num_buckets) {
57
100
    if (value_map.empty()) {
58
0
        return false;
59
100
    };
60
61
100
    size_t used_buckets = 1;
62
100
    size_t current_bucket_size = 0;
63
64
18.3k
    for (const auto& [value, count] : value_map) {
65
18.3k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
18.3k
        if (current_bucket_size > max_bucket_size) {
70
197
            ++used_buckets;
71
197
            current_bucket_size = count;
72
197
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
18.3k
        if (used_buckets > num_buckets) {
76
38
            return false;
77
38
        }
78
18.3k
    }
79
80
62
    return true;
81
100
}
_ZN5doris23can_assign_into_bucketsINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEmm
Line
Count
Source
56
51
                             const size_t num_buckets) {
57
51
    if (value_map.empty()) {
58
0
        return false;
59
51
    };
60
61
51
    size_t used_buckets = 1;
62
51
    size_t current_bucket_size = 0;
63
64
1.31k
    for (const auto& [value, count] : value_map) {
65
1.31k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.31k
        if (current_bucket_size > max_bucket_size) {
70
114
            ++used_buckets;
71
114
            current_bucket_size = count;
72
114
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.31k
        if (used_buckets > num_buckets) {
76
23
            return false;
77
23
        }
78
1.31k
    }
79
80
28
    return true;
81
51
}
_ZN5doris23can_assign_into_bucketsINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEmm
Line
Count
Source
56
51
                             const size_t num_buckets) {
57
51
    if (value_map.empty()) {
58
0
        return false;
59
51
    };
60
61
51
    size_t used_buckets = 1;
62
51
    size_t current_bucket_size = 0;
63
64
1.31k
    for (const auto& [value, count] : value_map) {
65
1.31k
        current_bucket_size += count;
66
67
        // If adding the current value to the current bucket would exceed max_bucket_size,
68
        // then we start a new bucket.
69
1.31k
        if (current_bucket_size > max_bucket_size) {
70
115
            ++used_buckets;
71
115
            current_bucket_size = count;
72
115
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
1.31k
        if (used_buckets > num_buckets) {
76
23
            return false;
77
23
        }
78
1.31k
    }
79
80
28
    return true;
81
51
}
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_16TimeStampNsValueEEEbRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEmm
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_16TimestampTzValueEEEbRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEmm
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsIoEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
82
83
/**
84
 * Calculates the maximum number of values that can fit into each bucket given a set of values
85
 * and the desired number of buckets.
86
 *
87
 * @tparam T the type of the values in the value map
88
 * @param value_map the map of values and their counts
89
 * @param num_buckets the desired number of buckets
90
 * @return the maximum number of values that can fit into each bucket
91
 */
92
template <typename T>
93
178
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
178
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
178
    size_t total_values = 0;
99
4.37k
    for (const auto& [value, count] : value_map) {
100
4.37k
        total_values += count;
101
4.37k
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
178
    if (num_buckets == 1) {
105
18
        return total_values;
106
18
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
160
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
160
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
160
    int search_step = 0;
119
160
    const int max_search_steps =
120
160
            10; // Limit the number of search steps to avoid excessive iteration
121
122
665
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
505
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
505
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
289
            upper_bucket_values = bucket_values;
130
289
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
216
            lower_bucket_values = bucket_values;
133
216
        }
134
        // Increment the search step counter
135
505
        ++search_step;
136
505
    }
137
138
160
    return upper_bucket_values;
139
178
}
_ZN5doris27calculate_bucket_max_valuesIhEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
1
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
1
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
1
    size_t total_values = 0;
99
2
    for (const auto& [value, count] : value_map) {
100
2
        total_values += count;
101
2
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
1
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
1
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
1
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
1
    int search_step = 0;
119
1
    const int max_search_steps =
120
1
            10; // Limit the number of search steps to avoid excessive iteration
121
122
1
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
0
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
0
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
0
            upper_bucket_values = bucket_values;
130
0
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
0
            lower_bucket_values = bucket_values;
133
0
        }
134
        // Increment the search step counter
135
0
        ++search_step;
136
0
    }
137
138
1
    return upper_bucket_values;
139
1
}
_ZN5doris27calculate_bucket_max_valuesIaEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
8
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
8
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
8
    size_t total_values = 0;
99
232
    for (const auto& [value, count] : value_map) {
100
232
        total_values += count;
101
232
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
8
    if (num_buckets == 1) {
105
1
        return total_values;
106
1
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
7
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
7
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
7
    int search_step = 0;
119
7
    const int max_search_steps =
120
7
            10; // Limit the number of search steps to avoid excessive iteration
121
122
34
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
27
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
27
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
16
            upper_bucket_values = bucket_values;
130
16
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
11
            lower_bucket_values = bucket_values;
133
11
        }
134
        // Increment the search step counter
135
27
        ++search_step;
136
27
    }
137
138
7
    return upper_bucket_values;
139
8
}
_ZN5doris27calculate_bucket_max_valuesIsEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
9
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
9
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
9
    size_t total_values = 0;
99
241
    for (const auto& [value, count] : value_map) {
100
241
        total_values += count;
101
241
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
9
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
9
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
9
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
9
    int search_step = 0;
119
9
    const int max_search_steps =
120
9
            10; // Limit the number of search steps to avoid excessive iteration
121
122
49
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
40
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
40
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
22
            upper_bucket_values = bucket_values;
130
22
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
18
            lower_bucket_values = bucket_values;
133
18
        }
134
        // Increment the search step counter
135
40
        ++search_step;
136
40
    }
137
138
9
    return upper_bucket_values;
139
9
}
_ZN5doris27calculate_bucket_max_valuesIiEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
46
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
46
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
46
    size_t total_values = 0;
99
272
    for (const auto& [value, count] : value_map) {
100
272
        total_values += count;
101
272
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
46
    if (num_buckets == 1) {
105
17
        return total_values;
106
17
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
29
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
29
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
29
    int search_step = 0;
119
29
    const int max_search_steps =
120
29
            10; // Limit the number of search steps to avoid excessive iteration
121
122
98
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
69
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
69
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
45
            upper_bucket_values = bucket_values;
130
45
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
24
            lower_bucket_values = bucket_values;
133
24
        }
134
        // Increment the search step counter
135
69
        ++search_step;
136
69
    }
137
138
29
    return upper_bucket_values;
139
46
}
_ZN5doris27calculate_bucket_max_valuesIlEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
25
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
25
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
25
    size_t total_values = 0;
99
310
    for (const auto& [value, count] : value_map) {
100
310
        total_values += count;
101
310
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
25
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
25
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
25
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
25
    int search_step = 0;
119
25
    const int max_search_steps =
120
25
            10; // Limit the number of search steps to avoid excessive iteration
121
122
59
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
34
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
34
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
17
            upper_bucket_values = bucket_values;
130
17
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
17
            lower_bucket_values = bucket_values;
133
17
        }
134
        // Increment the search step counter
135
34
        ++search_step;
136
34
    }
137
138
25
    return upper_bucket_values;
139
25
}
_ZN5doris27calculate_bucket_max_valuesInEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
8
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
8
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
8
    size_t total_values = 0;
99
235
    for (const auto& [value, count] : value_map) {
100
235
        total_values += count;
101
235
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
8
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
8
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
8
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
8
    int search_step = 0;
119
8
    const int max_search_steps =
120
8
            10; // Limit the number of search steps to avoid excessive iteration
121
122
40
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
32
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
32
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
17
            upper_bucket_values = bucket_values;
130
17
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
15
            lower_bucket_values = bucket_values;
133
15
        }
134
        // Increment the search step counter
135
32
        ++search_step;
136
32
    }
137
138
8
    return upper_bucket_values;
139
8
}
_ZN5doris27calculate_bucket_max_valuesIfEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
7
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
7
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
7
    size_t total_values = 0;
99
220
    for (const auto& [value, count] : value_map) {
100
220
        total_values += count;
101
220
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
7
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
7
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
7
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
7
    int search_step = 0;
119
7
    const int max_search_steps =
120
7
            10; // Limit the number of search steps to avoid excessive iteration
121
122
38
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
31
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
31
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
16
            upper_bucket_values = bucket_values;
130
16
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
15
            lower_bucket_values = bucket_values;
133
15
        }
134
        // Increment the search step counter
135
31
        ++search_step;
136
31
    }
137
138
7
    return upper_bucket_values;
139
7
}
_ZN5doris27calculate_bucket_max_valuesIdEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
7
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
7
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
7
    size_t total_values = 0;
99
220
    for (const auto& [value, count] : value_map) {
100
220
        total_values += count;
101
220
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
7
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
7
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
7
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
7
    int search_step = 0;
119
7
    const int max_search_steps =
120
7
            10; // Limit the number of search steps to avoid excessive iteration
121
122
38
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
31
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
31
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
16
            upper_bucket_values = bucket_values;
130
16
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
15
            lower_bucket_values = bucket_values;
133
15
        }
134
        // Increment the search step counter
135
31
        ++search_step;
136
31
    }
137
138
7
    return upper_bucket_values;
139
7
}
_ZN5doris27calculate_bucket_max_valuesINS_7DecimalIiEEEEmRKSt3mapIT_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Line
Count
Source
93
11
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
11
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
11
    size_t total_values = 0;
99
53
    for (const auto& [value, count] : value_map) {
100
53
        total_values += count;
101
53
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
11
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
11
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
11
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
11
    int search_step = 0;
119
11
    const int max_search_steps =
120
11
            10; // Limit the number of search steps to avoid excessive iteration
121
122
50
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
39
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
39
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
22
            upper_bucket_values = bucket_values;
130
22
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
17
            lower_bucket_values = bucket_values;
133
17
        }
134
        // Increment the search step counter
135
39
        ++search_step;
136
39
    }
137
138
11
    return upper_bucket_values;
139
11
}
Unexecuted instantiation: _ZN5doris27calculate_bucket_max_valuesINS_7DecimalIlEEEEmRKSt3mapIT_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Unexecuted instantiation: _ZN5doris27calculate_bucket_max_valuesINS_12Decimal128V3EEEmRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Unexecuted instantiation: _ZN5doris27calculate_bucket_max_valuesINS_7DecimalIN4wide7integerILm256EiEEEEEEmRKSt3mapIT_mSt4lessIS7_ESaISt4pairIKS7_mEEEm
_ZN5doris27calculate_bucket_max_valuesINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEmRKSt3mapIT_mSt4lessIS8_ESaISt4pairIKS8_mEEEm
Line
Count
Source
93
26
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
26
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
26
    size_t total_values = 0;
99
2.08k
    for (const auto& [value, count] : value_map) {
100
2.08k
        total_values += count;
101
2.08k
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
26
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
26
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
26
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
26
    int search_step = 0;
119
26
    const int max_search_steps =
120
26
            10; // Limit the number of search steps to avoid excessive iteration
121
122
126
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
100
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
100
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
62
            upper_bucket_values = bucket_values;
130
62
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
38
            lower_bucket_values = bucket_values;
133
38
        }
134
        // Increment the search step counter
135
100
        ++search_step;
136
100
    }
137
138
26
    return upper_bucket_values;
139
26
}
_ZN5doris27calculate_bucket_max_valuesINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEmRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Line
Count
Source
93
13
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
13
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
13
    size_t total_values = 0;
99
242
    for (const auto& [value, count] : value_map) {
100
242
        total_values += count;
101
242
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
13
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
13
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
13
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
13
    int search_step = 0;
119
13
    const int max_search_steps =
120
13
            10; // Limit the number of search steps to avoid excessive iteration
121
122
64
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
51
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
51
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
28
            upper_bucket_values = bucket_values;
130
28
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
23
            lower_bucket_values = bucket_values;
133
23
        }
134
        // Increment the search step counter
135
51
        ++search_step;
136
51
    }
137
138
13
    return upper_bucket_values;
139
13
}
_ZN5doris27calculate_bucket_max_valuesINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEmRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Line
Count
Source
93
13
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
13
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
13
    size_t total_values = 0;
99
241
    for (const auto& [value, count] : value_map) {
100
241
        total_values += count;
101
241
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
13
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
13
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
13
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
13
    int search_step = 0;
119
13
    const int max_search_steps =
120
13
            10; // Limit the number of search steps to avoid excessive iteration
121
122
64
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
51
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
51
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
28
            upper_bucket_values = bucket_values;
130
28
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
23
            lower_bucket_values = bucket_values;
133
23
        }
134
        // Increment the search step counter
135
51
        ++search_step;
136
51
    }
137
138
13
    return upper_bucket_values;
139
13
}
Unexecuted instantiation: _ZN5doris27calculate_bucket_max_valuesINS_16TimeStampNsValueEEEmRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Unexecuted instantiation: _ZN5doris27calculate_bucket_max_valuesINS_16TimestampTzValueEEEmRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
_ZN5doris27calculate_bucket_max_valuesIoEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
4
size_t calculate_bucket_max_values(const std::map<T, size_t>& value_map, const size_t num_buckets) {
94
    // Ensure that the value map is not empty
95
4
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
4
    size_t total_values = 0;
99
20
    for (const auto& [value, count] : value_map) {
100
20
        total_values += count;
101
20
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
4
    if (num_buckets == 1) {
105
0
        return total_values;
106
0
    }
107
108
    // To calculate the maximum value count in each bucket, we first calculate a conservative upper
109
    // bound, which is equal to 2 * total_values / (max_buckets - 1) + 1. This upper bound may exceed
110
    // the actual maximum value count, but it does not underestimate it. The subsequent binary search
111
    // algorithm will approach the actual maximum value count.
112
4
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
4
    size_t lower_bucket_values = 0;
116
117
    // Perform a binary search to find the maximum number of values that can fit into each bucket
118
4
    int search_step = 0;
119
4
    const int max_search_steps =
120
4
            10; // Limit the number of search steps to avoid excessive iteration
121
122
4
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
0
        const size_t bucket_values = (upper_bucket_values + lower_bucket_values) / 2;
125
126
        // Check if the given number of values can be assigned to the desired number of buckets
127
0
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
0
            upper_bucket_values = bucket_values;
130
0
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
0
            lower_bucket_values = bucket_values;
133
0
        }
134
        // Increment the search step counter
135
0
        ++search_step;
136
0
    }
137
138
4
    return upper_bucket_values;
139
4
}
140
141
/**
142
 * Greedy equi-height histogram construction algorithm, inspired by the MySQL
143
 * equi_height implementation(https://dev.mysql.com/doc/dev/mysql-server/latest/equi__height_8h.html).
144
 *
145
 * Given an ordered collection of [value, count] pairs and a maximum bucket
146
 * size, construct a histogram by inserting values into a bucket while keeping
147
 * track of its size. If the insertion of a value into a non-empty bucket
148
 * causes the bucket to exceed the maximum size, create a new empty bucket and
149
 * continue.
150
 *
151
 * The algorithm guarantees a selectivity estimation error of at most ~2 *
152
 * #values / #buckets, often less. Values with a higher relative frequency are
153
 * guaranteed to be placed in singleton buckets.
154
 *
155
 * The minimum composite bucket size is used to minimize the worst case
156
 * selectivity estimation error. In general, the algorithm will adapt to the
157
 * data distribution to minimize the size of composite buckets. The heavy values
158
 * can be placed in singleton buckets and the remaining values will be evenly
159
 * spread across the remaining buckets, leading to a lower composite bucket size.
160
 *
161
 * Note: The term "value" refers to an entry in a column and the actual value
162
 * of an entry. The ordered_map is an ordered collection of [distinct value,
163
 * value count] pairs. For example, a Value_map<String> could contain the pairs ["a", 1], ["b", 2]
164
 * to represent one "a" value and two "b" values.
165
 *
166
 * @param buckets A vector of empty buckets that will be populated with data.
167
 * @param ordered_map An ordered map of distinct values and their counts.
168
 * @param max_num_buckets The maximum number of buckets that can be used.
169
 *
170
 * @return True if the buckets were successfully built, false otherwise.
171
 */
172
template <typename T>
173
bool build_histogram(std::vector<Bucket<T>>& buckets, const std::map<T, size_t>& ordered_map,
174
204
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
204
    if (ordered_map.empty()) {
177
32
        return false;
178
32
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
172
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
172
    buckets.clear();
186
172
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
172
    size_t distinct_values_count = 0;
190
172
    size_t values_count = 0;
191
172
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
172
    auto remaining_distinct_values = ordered_map.size();
195
196
172
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
172
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
4.53k
    for (; it != ordered_map.end(); ++it) {
203
4.36k
        const auto count = it->second;
204
4.36k
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
4.36k
        distinct_values_count++;
208
4.36k
        remaining_distinct_values--;
209
4.36k
        values_count += count;
210
4.36k
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
4.36k
        auto next = std::next(it);
214
4.36k
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
4.36k
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
4.36k
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
3.89k
            continue;
222
3.89k
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
466
        auto pre_sum = cumulative_values - values_count;
226
227
466
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
466
                             pre_sum);
229
466
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
466
        if (next != ordered_map.end()) {
233
294
            lower_value = &next->first;
234
294
        }
235
466
        values_count = 0;
236
466
        distinct_values_count = 0;
237
466
    }
238
239
172
    return true;
240
204
}
_ZN5doris15build_histogramIhEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
2
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
2
    if (ordered_map.empty()) {
177
1
        return false;
178
1
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
1
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
1
    buckets.clear();
186
1
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
1
    size_t distinct_values_count = 0;
190
1
    size_t values_count = 0;
191
1
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
1
    auto remaining_distinct_values = ordered_map.size();
195
196
1
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
1
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
3
    for (; it != ordered_map.end(); ++it) {
203
2
        const auto count = it->second;
204
2
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
2
        distinct_values_count++;
208
2
        remaining_distinct_values--;
209
2
        values_count += count;
210
2
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
2
        auto next = std::next(it);
214
2
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
2
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
2
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
0
            continue;
222
0
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
2
        auto pre_sum = cumulative_values - values_count;
226
227
2
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
2
                             pre_sum);
229
2
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
2
        if (next != ordered_map.end()) {
233
1
            lower_value = &next->first;
234
1
        }
235
2
        values_count = 0;
236
2
        distinct_values_count = 0;
237
2
    }
238
239
1
    return true;
240
2
}
_ZN5doris15build_histogramIaEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
11
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
11
    if (ordered_map.empty()) {
177
3
        return false;
178
3
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
8
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
8
    buckets.clear();
186
8
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
8
    size_t distinct_values_count = 0;
190
8
    size_t values_count = 0;
191
8
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
8
    auto remaining_distinct_values = ordered_map.size();
195
196
8
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
8
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
240
    for (; it != ordered_map.end(); ++it) {
203
232
        const auto count = it->second;
204
232
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
232
        distinct_values_count++;
208
232
        remaining_distinct_values--;
209
232
        values_count += count;
210
232
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
232
        auto next = std::next(it);
214
232
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
232
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
232
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
211
            continue;
222
211
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
21
        auto pre_sum = cumulative_values - values_count;
226
227
21
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
21
                             pre_sum);
229
21
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
21
        if (next != ordered_map.end()) {
233
13
            lower_value = &next->first;
234
13
        }
235
21
        values_count = 0;
236
21
        distinct_values_count = 0;
237
21
    }
238
239
8
    return true;
240
11
}
_ZN5doris15build_histogramIsEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
11
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
11
    if (ordered_map.empty()) {
177
2
        return false;
178
2
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
9
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
9
    buckets.clear();
186
9
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
9
    size_t distinct_values_count = 0;
190
9
    size_t values_count = 0;
191
9
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
9
    auto remaining_distinct_values = ordered_map.size();
195
196
9
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
9
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
250
    for (; it != ordered_map.end(); ++it) {
203
241
        const auto count = it->second;
204
241
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
241
        distinct_values_count++;
208
241
        remaining_distinct_values--;
209
241
        values_count += count;
210
241
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
241
        auto next = std::next(it);
214
241
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
241
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
241
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
217
            continue;
222
217
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
24
        auto pre_sum = cumulative_values - values_count;
226
227
24
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
24
                             pre_sum);
229
24
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
24
        if (next != ordered_map.end()) {
233
15
            lower_value = &next->first;
234
15
        }
235
24
        values_count = 0;
236
24
        distinct_values_count = 0;
237
24
    }
238
239
9
    return true;
240
11
}
_ZN5doris15build_histogramIiEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
46
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
46
    if (ordered_map.empty()) {
177
6
        return false;
178
6
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
40
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
40
    buckets.clear();
186
40
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
40
    size_t distinct_values_count = 0;
190
40
    size_t values_count = 0;
191
40
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
40
    auto remaining_distinct_values = ordered_map.size();
195
196
40
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
40
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
300
    for (; it != ordered_map.end(); ++it) {
203
260
        const auto count = it->second;
204
260
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
260
        distinct_values_count++;
208
260
        remaining_distinct_values--;
209
260
        values_count += count;
210
260
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
260
        auto next = std::next(it);
214
260
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
260
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
260
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
202
            continue;
222
202
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
58
        auto pre_sum = cumulative_values - values_count;
226
227
58
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
58
                             pre_sum);
229
58
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
58
        if (next != ordered_map.end()) {
233
18
            lower_value = &next->first;
234
18
        }
235
58
        values_count = 0;
236
58
        distinct_values_count = 0;
237
58
    }
238
239
40
    return true;
240
46
}
_ZN5doris15build_histogramIlEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
28
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
28
    if (ordered_map.empty()) {
177
3
        return false;
178
3
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
25
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
25
    buckets.clear();
186
25
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
25
    size_t distinct_values_count = 0;
190
25
    size_t values_count = 0;
191
25
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
25
    auto remaining_distinct_values = ordered_map.size();
195
196
25
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
25
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
335
    for (; it != ordered_map.end(); ++it) {
203
310
        const auto count = it->second;
204
310
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
310
        distinct_values_count++;
208
310
        remaining_distinct_values--;
209
310
        values_count += count;
210
310
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
310
        auto next = std::next(it);
214
310
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
310
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
310
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
206
            continue;
222
206
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
104
        auto pre_sum = cumulative_values - values_count;
226
227
104
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
104
                             pre_sum);
229
104
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
104
        if (next != ordered_map.end()) {
233
79
            lower_value = &next->first;
234
79
        }
235
104
        values_count = 0;
236
104
        distinct_values_count = 0;
237
104
    }
238
239
25
    return true;
240
28
}
_ZN5doris15build_histogramInEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
11
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
11
    if (ordered_map.empty()) {
177
3
        return false;
178
3
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
8
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
8
    buckets.clear();
186
8
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
8
    size_t distinct_values_count = 0;
190
8
    size_t values_count = 0;
191
8
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
8
    auto remaining_distinct_values = ordered_map.size();
195
196
8
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
8
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
243
    for (; it != ordered_map.end(); ++it) {
203
235
        const auto count = it->second;
204
235
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
235
        distinct_values_count++;
208
235
        remaining_distinct_values--;
209
235
        values_count += count;
210
235
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
235
        auto next = std::next(it);
214
235
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
235
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
235
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
202
            continue;
222
202
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
33
        auto pre_sum = cumulative_values - values_count;
226
227
33
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
33
                             pre_sum);
229
33
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
33
        if (next != ordered_map.end()) {
233
25
            lower_value = &next->first;
234
25
        }
235
33
        values_count = 0;
236
33
        distinct_values_count = 0;
237
33
    }
238
239
8
    return true;
240
11
}
_ZN5doris15build_histogramIfEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
9
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
9
    if (ordered_map.empty()) {
177
2
        return false;
178
2
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
7
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
7
    buckets.clear();
186
7
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
7
    size_t distinct_values_count = 0;
190
7
    size_t values_count = 0;
191
7
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
7
    auto remaining_distinct_values = ordered_map.size();
195
196
7
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
7
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
227
    for (; it != ordered_map.end(); ++it) {
203
220
        const auto count = it->second;
204
220
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
220
        distinct_values_count++;
208
220
        remaining_distinct_values--;
209
220
        values_count += count;
210
220
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
220
        auto next = std::next(it);
214
220
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
220
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
220
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
200
            continue;
222
200
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
20
        auto pre_sum = cumulative_values - values_count;
226
227
20
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
20
                             pre_sum);
229
20
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
20
        if (next != ordered_map.end()) {
233
13
            lower_value = &next->first;
234
13
        }
235
20
        values_count = 0;
236
20
        distinct_values_count = 0;
237
20
    }
238
239
7
    return true;
240
9
}
_ZN5doris15build_histogramIdEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
9
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
9
    if (ordered_map.empty()) {
177
2
        return false;
178
2
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
7
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
7
    buckets.clear();
186
7
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
7
    size_t distinct_values_count = 0;
190
7
    size_t values_count = 0;
191
7
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
7
    auto remaining_distinct_values = ordered_map.size();
195
196
7
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
7
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
227
    for (; it != ordered_map.end(); ++it) {
203
220
        const auto count = it->second;
204
220
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
220
        distinct_values_count++;
208
220
        remaining_distinct_values--;
209
220
        values_count += count;
210
220
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
220
        auto next = std::next(it);
214
220
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
220
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
220
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
200
            continue;
222
200
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
20
        auto pre_sum = cumulative_values - values_count;
226
227
20
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
20
                             pre_sum);
229
20
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
20
        if (next != ordered_map.end()) {
233
13
            lower_value = &next->first;
234
13
        }
235
20
        values_count = 0;
236
20
        distinct_values_count = 0;
237
20
    }
238
239
7
    return true;
240
9
}
_ZN5doris15build_histogramINS_7DecimalIiEEEEbRSt6vectorINS_6BucketIT_EESaIS6_EERKSt3mapIS5_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Line
Count
Source
174
12
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
12
    if (ordered_map.empty()) {
177
1
        return false;
178
1
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
11
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
11
    buckets.clear();
186
11
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
11
    size_t distinct_values_count = 0;
190
11
    size_t values_count = 0;
191
11
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
11
    auto remaining_distinct_values = ordered_map.size();
195
196
11
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
11
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
64
    for (; it != ordered_map.end(); ++it) {
203
53
        const auto count = it->second;
204
53
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
53
        distinct_values_count++;
208
53
        remaining_distinct_values--;
209
53
        values_count += count;
210
53
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
53
        auto next = std::next(it);
214
53
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
53
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
53
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
28
            continue;
222
28
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
25
        auto pre_sum = cumulative_values - values_count;
226
227
25
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
25
                             pre_sum);
229
25
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
25
        if (next != ordered_map.end()) {
233
14
            lower_value = &next->first;
234
14
        }
235
25
        values_count = 0;
236
25
        distinct_values_count = 0;
237
25
    }
238
239
11
    return true;
240
12
}
Unexecuted instantiation: _ZN5doris15build_histogramINS_7DecimalIlEEEEbRSt6vectorINS_6BucketIT_EESaIS6_EERKSt3mapIS5_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Unexecuted instantiation: _ZN5doris15build_histogramINS_12Decimal128V3EEEbRSt6vectorINS_6BucketIT_EESaIS5_EERKSt3mapIS4_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Unexecuted instantiation: _ZN5doris15build_histogramINS_7DecimalIN4wide7integerILm256EiEEEEEEbRSt6vectorINS_6BucketIT_EESaIS9_EERKSt3mapIS8_mSt4lessIS8_ESaISt4pairIKS8_mEEEm
_ZN5doris15build_histogramINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRSt6vectorINS_6BucketIT_EESaISA_EERKSt3mapIS9_mSt4lessIS9_ESaISt4pairIKS9_mEEEm
Line
Count
Source
174
31
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
31
    if (ordered_map.empty()) {
177
5
        return false;
178
5
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
26
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
26
    buckets.clear();
186
26
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
26
    size_t distinct_values_count = 0;
190
26
    size_t values_count = 0;
191
26
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
26
    auto remaining_distinct_values = ordered_map.size();
195
196
26
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
26
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
2.11k
    for (; it != ordered_map.end(); ++it) {
203
2.08k
        const auto count = it->second;
204
2.08k
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
2.08k
        distinct_values_count++;
208
2.08k
        remaining_distinct_values--;
209
2.08k
        values_count += count;
210
2.08k
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
2.08k
        auto next = std::next(it);
214
2.08k
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
2.08k
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
2.08k
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
2.02k
            continue;
222
2.02k
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
60
        auto pre_sum = cumulative_values - values_count;
226
227
60
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
60
                             pre_sum);
229
60
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
60
        if (next != ordered_map.end()) {
233
34
            lower_value = &next->first;
234
34
        }
235
60
        values_count = 0;
236
60
        distinct_values_count = 0;
237
60
    }
238
239
26
    return true;
240
31
}
_ZN5doris15build_histogramINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRSt6vectorINS_6BucketIT_EESaIS7_EERKSt3mapIS6_mSt4lessIS6_ESaISt4pairIKS6_mEEEm
Line
Count
Source
174
14
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
14
    if (ordered_map.empty()) {
177
1
        return false;
178
1
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
13
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
13
    buckets.clear();
186
13
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
13
    size_t distinct_values_count = 0;
190
13
    size_t values_count = 0;
191
13
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
13
    auto remaining_distinct_values = ordered_map.size();
195
196
13
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
13
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
255
    for (; it != ordered_map.end(); ++it) {
203
242
        const auto count = it->second;
204
242
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
242
        distinct_values_count++;
208
242
        remaining_distinct_values--;
209
242
        values_count += count;
210
242
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
242
        auto next = std::next(it);
214
242
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
242
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
242
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
202
            continue;
222
202
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
40
        auto pre_sum = cumulative_values - values_count;
226
227
40
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
40
                             pre_sum);
229
40
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
40
        if (next != ordered_map.end()) {
233
27
            lower_value = &next->first;
234
27
        }
235
40
        values_count = 0;
236
40
        distinct_values_count = 0;
237
40
    }
238
239
13
    return true;
240
14
}
_ZN5doris15build_histogramINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRSt6vectorINS_6BucketIT_EESaIS7_EERKSt3mapIS6_mSt4lessIS6_ESaISt4pairIKS6_mEEEm
Line
Count
Source
174
14
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
14
    if (ordered_map.empty()) {
177
1
        return false;
178
1
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
13
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
13
    buckets.clear();
186
13
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
13
    size_t distinct_values_count = 0;
190
13
    size_t values_count = 0;
191
13
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
13
    auto remaining_distinct_values = ordered_map.size();
195
196
13
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
13
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
254
    for (; it != ordered_map.end(); ++it) {
203
241
        const auto count = it->second;
204
241
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
241
        distinct_values_count++;
208
241
        remaining_distinct_values--;
209
241
        values_count += count;
210
241
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
241
        auto next = std::next(it);
214
241
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
241
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
241
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
202
            continue;
222
202
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
39
        auto pre_sum = cumulative_values - values_count;
226
227
39
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
39
                             pre_sum);
229
39
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
39
        if (next != ordered_map.end()) {
233
26
            lower_value = &next->first;
234
26
        }
235
39
        values_count = 0;
236
39
        distinct_values_count = 0;
237
39
    }
238
239
13
    return true;
240
14
}
Unexecuted instantiation: _ZN5doris15build_histogramINS_16TimeStampNsValueEEEbRSt6vectorINS_6BucketIT_EESaIS5_EERKSt3mapIS4_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Unexecuted instantiation: _ZN5doris15build_histogramINS_16TimestampTzValueEEEbRSt6vectorINS_6BucketIT_EESaIS5_EERKSt3mapIS4_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
_ZN5doris15build_histogramIoEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
6
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
6
    if (ordered_map.empty()) {
177
2
        return false;
178
2
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
4
    auto bucket_max_values = calculate_bucket_max_values(ordered_map, max_num_buckets);
182
183
    // Ensure that the capacity is at least max_num_buckets in order to avoid the overhead of additional
184
    // allocations when inserting buckets.
185
4
    buckets.clear();
186
4
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
4
    size_t distinct_values_count = 0;
190
4
    size_t values_count = 0;
191
4
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
4
    auto remaining_distinct_values = ordered_map.size();
195
196
4
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
4
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
24
    for (; it != ordered_map.end(); ++it) {
203
20
        const auto count = it->second;
204
20
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
20
        distinct_values_count++;
208
20
        remaining_distinct_values--;
209
20
        values_count += count;
210
20
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
20
        auto next = std::next(it);
214
20
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
20
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
20
            values_count + next->second <= bucket_max_values) {
218
            // If the current value is the last in the input map and there are more remaining
219
            // distinct values than empty buckets and adding the value does not cause the bucket
220
            // to exceed its max size, skip adding the value to the current bucket.
221
0
            continue;
222
0
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
20
        auto pre_sum = cumulative_values - values_count;
226
227
20
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
20
                             pre_sum);
229
20
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
20
        if (next != ordered_map.end()) {
233
16
            lower_value = &next->first;
234
16
        }
235
20
        values_count = 0;
236
20
        distinct_values_count = 0;
237
20
    }
238
239
4
    return true;
240
6
}
241
242
template <typename T>
243
bool histogram_to_json(rapidjson::StringBuffer& buffer, const std::vector<Bucket<T>>& buckets,
244
199
                       const DataTypePtr& data_type) {
245
199
    rapidjson::Document doc;
246
199
    doc.SetObject();
247
199
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
199
    int num_buckets = cast_set<int>(buckets.size());
250
199
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
199
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
199
    bucket_arr.Reserve(num_buckets, allocator);
254
255
199
    std::stringstream ss1;
256
199
    std::stringstream ss2;
257
258
199
    rapidjson::Value lower_val;
259
199
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
199
    MutableColumnPtr lower_column = data_type->create_column();
263
199
    MutableColumnPtr upper_column = data_type->create_column();
264
454
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
454
        if constexpr (!std::is_same_v<T, std::string>) {
268
394
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
394
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
394
        }
271
454
    }
272
199
    size_t row_num = 0;
273
274
199
    auto format_options = DataTypeSerDe::get_default_format_options();
275
199
    auto time_zone = cctz::utc_time_zone();
276
199
    format_options.timezone = &time_zone;
277
278
454
    for (const auto& bucket : buckets) {
279
454
        if constexpr (std::is_same_v<T, std::string>) {
280
60
            lower_val.SetString(bucket.lower.data(),
281
60
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
60
            upper_val.SetString(bucket.upper.data(),
283
60
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
394
        } else {
285
394
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
394
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
394
            ++row_num;
288
394
            lower_val.SetString(lower_str.data(),
289
394
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
394
            upper_val.SetString(upper_str.data(),
291
394
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
394
        }
293
454
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
454
        bucket_json.AddMember("lower", lower_val, allocator);
295
454
        bucket_json.AddMember("upper", upper_val, allocator);
296
454
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
454
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
454
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
454
        bucket_arr.PushBack(bucket_json, allocator);
301
454
    }
302
303
199
    doc.AddMember("buckets", bucket_arr, allocator);
304
199
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
199
    doc.Accept(writer);
306
307
199
    return !buckets.empty() && buffer.GetSize() > 0;
308
199
}
_ZN5doris17histogram_to_jsonIhEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
2
                       const DataTypePtr& data_type) {
245
2
    rapidjson::Document doc;
246
2
    doc.SetObject();
247
2
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
2
    int num_buckets = cast_set<int>(buckets.size());
250
2
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
2
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
2
    bucket_arr.Reserve(num_buckets, allocator);
254
255
2
    std::stringstream ss1;
256
2
    std::stringstream ss2;
257
258
2
    rapidjson::Value lower_val;
259
2
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
2
    MutableColumnPtr lower_column = data_type->create_column();
263
2
    MutableColumnPtr upper_column = data_type->create_column();
264
2
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
2
        if constexpr (!std::is_same_v<T, std::string>) {
268
2
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
2
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
2
        }
271
2
    }
272
2
    size_t row_num = 0;
273
274
2
    auto format_options = DataTypeSerDe::get_default_format_options();
275
2
    auto time_zone = cctz::utc_time_zone();
276
2
    format_options.timezone = &time_zone;
277
278
2
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
2
        } else {
285
2
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
2
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
2
            ++row_num;
288
2
            lower_val.SetString(lower_str.data(),
289
2
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
2
            upper_val.SetString(upper_str.data(),
291
2
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
2
        }
293
2
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
2
        bucket_json.AddMember("lower", lower_val, allocator);
295
2
        bucket_json.AddMember("upper", upper_val, allocator);
296
2
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
2
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
2
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
2
        bucket_arr.PushBack(bucket_json, allocator);
301
2
    }
302
303
2
    doc.AddMember("buckets", bucket_arr, allocator);
304
2
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
2
    doc.Accept(writer);
306
307
2
    return !buckets.empty() && buffer.GetSize() > 0;
308
2
}
_ZN5doris17histogram_to_jsonIaEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
11
                       const DataTypePtr& data_type) {
245
11
    rapidjson::Document doc;
246
11
    doc.SetObject();
247
11
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
11
    int num_buckets = cast_set<int>(buckets.size());
250
11
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
11
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
11
    bucket_arr.Reserve(num_buckets, allocator);
254
255
11
    std::stringstream ss1;
256
11
    std::stringstream ss2;
257
258
11
    rapidjson::Value lower_val;
259
11
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
11
    MutableColumnPtr lower_column = data_type->create_column();
263
11
    MutableColumnPtr upper_column = data_type->create_column();
264
21
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
21
        if constexpr (!std::is_same_v<T, std::string>) {
268
21
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
21
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
21
        }
271
21
    }
272
11
    size_t row_num = 0;
273
274
11
    auto format_options = DataTypeSerDe::get_default_format_options();
275
11
    auto time_zone = cctz::utc_time_zone();
276
11
    format_options.timezone = &time_zone;
277
278
21
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
21
        } else {
285
21
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
21
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
21
            ++row_num;
288
21
            lower_val.SetString(lower_str.data(),
289
21
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
21
            upper_val.SetString(upper_str.data(),
291
21
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
21
        }
293
21
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
21
        bucket_json.AddMember("lower", lower_val, allocator);
295
21
        bucket_json.AddMember("upper", upper_val, allocator);
296
21
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
21
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
21
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
21
        bucket_arr.PushBack(bucket_json, allocator);
301
21
    }
302
303
11
    doc.AddMember("buckets", bucket_arr, allocator);
304
11
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
11
    doc.Accept(writer);
306
307
11
    return !buckets.empty() && buffer.GetSize() > 0;
308
11
}
_ZN5doris17histogram_to_jsonIsEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
11
                       const DataTypePtr& data_type) {
245
11
    rapidjson::Document doc;
246
11
    doc.SetObject();
247
11
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
11
    int num_buckets = cast_set<int>(buckets.size());
250
11
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
11
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
11
    bucket_arr.Reserve(num_buckets, allocator);
254
255
11
    std::stringstream ss1;
256
11
    std::stringstream ss2;
257
258
11
    rapidjson::Value lower_val;
259
11
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
11
    MutableColumnPtr lower_column = data_type->create_column();
263
11
    MutableColumnPtr upper_column = data_type->create_column();
264
24
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
24
        if constexpr (!std::is_same_v<T, std::string>) {
268
24
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
24
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
24
        }
271
24
    }
272
11
    size_t row_num = 0;
273
274
11
    auto format_options = DataTypeSerDe::get_default_format_options();
275
11
    auto time_zone = cctz::utc_time_zone();
276
11
    format_options.timezone = &time_zone;
277
278
24
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
24
        } else {
285
24
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
24
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
24
            ++row_num;
288
24
            lower_val.SetString(lower_str.data(),
289
24
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
24
            upper_val.SetString(upper_str.data(),
291
24
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
24
        }
293
24
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
24
        bucket_json.AddMember("lower", lower_val, allocator);
295
24
        bucket_json.AddMember("upper", upper_val, allocator);
296
24
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
24
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
24
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
24
        bucket_arr.PushBack(bucket_json, allocator);
301
24
    }
302
303
11
    doc.AddMember("buckets", bucket_arr, allocator);
304
11
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
11
    doc.Accept(writer);
306
307
11
    return !buckets.empty() && buffer.GetSize() > 0;
308
11
}
_ZN5doris17histogram_to_jsonIiEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
41
                       const DataTypePtr& data_type) {
245
41
    rapidjson::Document doc;
246
41
    doc.SetObject();
247
41
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
41
    int num_buckets = cast_set<int>(buckets.size());
250
41
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
41
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
41
    bucket_arr.Reserve(num_buckets, allocator);
254
255
41
    std::stringstream ss1;
256
41
    std::stringstream ss2;
257
258
41
    rapidjson::Value lower_val;
259
41
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
41
    MutableColumnPtr lower_column = data_type->create_column();
263
41
    MutableColumnPtr upper_column = data_type->create_column();
264
46
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
46
        if constexpr (!std::is_same_v<T, std::string>) {
268
46
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
46
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
46
        }
271
46
    }
272
41
    size_t row_num = 0;
273
274
41
    auto format_options = DataTypeSerDe::get_default_format_options();
275
41
    auto time_zone = cctz::utc_time_zone();
276
41
    format_options.timezone = &time_zone;
277
278
46
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
46
        } else {
285
46
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
46
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
46
            ++row_num;
288
46
            lower_val.SetString(lower_str.data(),
289
46
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
46
            upper_val.SetString(upper_str.data(),
291
46
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
46
        }
293
46
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
46
        bucket_json.AddMember("lower", lower_val, allocator);
295
46
        bucket_json.AddMember("upper", upper_val, allocator);
296
46
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
46
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
46
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
46
        bucket_arr.PushBack(bucket_json, allocator);
301
46
    }
302
303
41
    doc.AddMember("buckets", bucket_arr, allocator);
304
41
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
41
    doc.Accept(writer);
306
307
41
    return !buckets.empty() && buffer.GetSize() > 0;
308
41
}
_ZN5doris17histogram_to_jsonIlEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
28
                       const DataTypePtr& data_type) {
245
28
    rapidjson::Document doc;
246
28
    doc.SetObject();
247
28
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
28
    int num_buckets = cast_set<int>(buckets.size());
250
28
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
28
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
28
    bucket_arr.Reserve(num_buckets, allocator);
254
255
28
    std::stringstream ss1;
256
28
    std::stringstream ss2;
257
258
28
    rapidjson::Value lower_val;
259
28
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
28
    MutableColumnPtr lower_column = data_type->create_column();
263
28
    MutableColumnPtr upper_column = data_type->create_column();
264
104
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
104
        if constexpr (!std::is_same_v<T, std::string>) {
268
104
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
104
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
104
        }
271
104
    }
272
28
    size_t row_num = 0;
273
274
28
    auto format_options = DataTypeSerDe::get_default_format_options();
275
28
    auto time_zone = cctz::utc_time_zone();
276
28
    format_options.timezone = &time_zone;
277
278
104
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
104
        } else {
285
104
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
104
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
104
            ++row_num;
288
104
            lower_val.SetString(lower_str.data(),
289
104
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
104
            upper_val.SetString(upper_str.data(),
291
104
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
104
        }
293
104
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
104
        bucket_json.AddMember("lower", lower_val, allocator);
295
104
        bucket_json.AddMember("upper", upper_val, allocator);
296
104
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
104
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
104
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
104
        bucket_arr.PushBack(bucket_json, allocator);
301
104
    }
302
303
28
    doc.AddMember("buckets", bucket_arr, allocator);
304
28
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
28
    doc.Accept(writer);
306
307
28
    return !buckets.empty() && buffer.GetSize() > 0;
308
28
}
_ZN5doris17histogram_to_jsonInEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
11
                       const DataTypePtr& data_type) {
245
11
    rapidjson::Document doc;
246
11
    doc.SetObject();
247
11
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
11
    int num_buckets = cast_set<int>(buckets.size());
250
11
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
11
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
11
    bucket_arr.Reserve(num_buckets, allocator);
254
255
11
    std::stringstream ss1;
256
11
    std::stringstream ss2;
257
258
11
    rapidjson::Value lower_val;
259
11
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
11
    MutableColumnPtr lower_column = data_type->create_column();
263
11
    MutableColumnPtr upper_column = data_type->create_column();
264
33
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
33
        if constexpr (!std::is_same_v<T, std::string>) {
268
33
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
33
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
33
        }
271
33
    }
272
11
    size_t row_num = 0;
273
274
11
    auto format_options = DataTypeSerDe::get_default_format_options();
275
11
    auto time_zone = cctz::utc_time_zone();
276
11
    format_options.timezone = &time_zone;
277
278
33
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
33
        } else {
285
33
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
33
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
33
            ++row_num;
288
33
            lower_val.SetString(lower_str.data(),
289
33
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
33
            upper_val.SetString(upper_str.data(),
291
33
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
33
        }
293
33
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
33
        bucket_json.AddMember("lower", lower_val, allocator);
295
33
        bucket_json.AddMember("upper", upper_val, allocator);
296
33
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
33
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
33
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
33
        bucket_arr.PushBack(bucket_json, allocator);
301
33
    }
302
303
11
    doc.AddMember("buckets", bucket_arr, allocator);
304
11
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
11
    doc.Accept(writer);
306
307
11
    return !buckets.empty() && buffer.GetSize() > 0;
308
11
}
_ZN5doris17histogram_to_jsonIfEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
9
                       const DataTypePtr& data_type) {
245
9
    rapidjson::Document doc;
246
9
    doc.SetObject();
247
9
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
9
    int num_buckets = cast_set<int>(buckets.size());
250
9
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
9
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
9
    bucket_arr.Reserve(num_buckets, allocator);
254
255
9
    std::stringstream ss1;
256
9
    std::stringstream ss2;
257
258
9
    rapidjson::Value lower_val;
259
9
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
9
    MutableColumnPtr lower_column = data_type->create_column();
263
9
    MutableColumnPtr upper_column = data_type->create_column();
264
20
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
20
        if constexpr (!std::is_same_v<T, std::string>) {
268
20
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
20
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
20
        }
271
20
    }
272
9
    size_t row_num = 0;
273
274
9
    auto format_options = DataTypeSerDe::get_default_format_options();
275
9
    auto time_zone = cctz::utc_time_zone();
276
9
    format_options.timezone = &time_zone;
277
278
20
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
20
        } else {
285
20
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
20
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
20
            ++row_num;
288
20
            lower_val.SetString(lower_str.data(),
289
20
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
20
            upper_val.SetString(upper_str.data(),
291
20
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
20
        }
293
20
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
20
        bucket_json.AddMember("lower", lower_val, allocator);
295
20
        bucket_json.AddMember("upper", upper_val, allocator);
296
20
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
20
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
20
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
20
        bucket_arr.PushBack(bucket_json, allocator);
301
20
    }
302
303
9
    doc.AddMember("buckets", bucket_arr, allocator);
304
9
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
9
    doc.Accept(writer);
306
307
9
    return !buckets.empty() && buffer.GetSize() > 0;
308
9
}
_ZN5doris17histogram_to_jsonIdEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
9
                       const DataTypePtr& data_type) {
245
9
    rapidjson::Document doc;
246
9
    doc.SetObject();
247
9
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
9
    int num_buckets = cast_set<int>(buckets.size());
250
9
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
9
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
9
    bucket_arr.Reserve(num_buckets, allocator);
254
255
9
    std::stringstream ss1;
256
9
    std::stringstream ss2;
257
258
9
    rapidjson::Value lower_val;
259
9
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
9
    MutableColumnPtr lower_column = data_type->create_column();
263
9
    MutableColumnPtr upper_column = data_type->create_column();
264
20
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
20
        if constexpr (!std::is_same_v<T, std::string>) {
268
20
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
20
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
20
        }
271
20
    }
272
9
    size_t row_num = 0;
273
274
9
    auto format_options = DataTypeSerDe::get_default_format_options();
275
9
    auto time_zone = cctz::utc_time_zone();
276
9
    format_options.timezone = &time_zone;
277
278
20
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
20
        } else {
285
20
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
20
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
20
            ++row_num;
288
20
            lower_val.SetString(lower_str.data(),
289
20
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
20
            upper_val.SetString(upper_str.data(),
291
20
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
20
        }
293
20
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
20
        bucket_json.AddMember("lower", lower_val, allocator);
295
20
        bucket_json.AddMember("upper", upper_val, allocator);
296
20
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
20
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
20
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
20
        bucket_arr.PushBack(bucket_json, allocator);
301
20
    }
302
303
9
    doc.AddMember("buckets", bucket_arr, allocator);
304
9
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
9
    doc.Accept(writer);
306
307
9
    return !buckets.empty() && buffer.GetSize() > 0;
308
9
}
_ZN5doris17histogram_to_jsonINS_7DecimalIiEEEEbRN9rapidjson19GenericStringBufferINS3_4UTF8IcEENS3_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISD_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
12
                       const DataTypePtr& data_type) {
245
12
    rapidjson::Document doc;
246
12
    doc.SetObject();
247
12
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
12
    int num_buckets = cast_set<int>(buckets.size());
250
12
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
12
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
12
    bucket_arr.Reserve(num_buckets, allocator);
254
255
12
    std::stringstream ss1;
256
12
    std::stringstream ss2;
257
258
12
    rapidjson::Value lower_val;
259
12
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
12
    MutableColumnPtr lower_column = data_type->create_column();
263
12
    MutableColumnPtr upper_column = data_type->create_column();
264
25
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
25
        if constexpr (!std::is_same_v<T, std::string>) {
268
25
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
25
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
25
        }
271
25
    }
272
12
    size_t row_num = 0;
273
274
12
    auto format_options = DataTypeSerDe::get_default_format_options();
275
12
    auto time_zone = cctz::utc_time_zone();
276
12
    format_options.timezone = &time_zone;
277
278
25
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
25
        } else {
285
25
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
25
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
25
            ++row_num;
288
25
            lower_val.SetString(lower_str.data(),
289
25
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
25
            upper_val.SetString(upper_str.data(),
291
25
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
25
        }
293
25
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
25
        bucket_json.AddMember("lower", lower_val, allocator);
295
25
        bucket_json.AddMember("upper", upper_val, allocator);
296
25
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
25
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
25
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
25
        bucket_arr.PushBack(bucket_json, allocator);
301
25
    }
302
303
12
    doc.AddMember("buckets", bucket_arr, allocator);
304
12
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
12
    doc.Accept(writer);
306
307
12
    return !buckets.empty() && buffer.GetSize() > 0;
308
12
}
Unexecuted instantiation: _ZN5doris17histogram_to_jsonINS_7DecimalIlEEEEbRN9rapidjson19GenericStringBufferINS3_4UTF8IcEENS3_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISD_EERKSt10shared_ptrIKNS_9IDataTypeEE
Unexecuted instantiation: _ZN5doris17histogram_to_jsonINS_12Decimal128V3EEEbRN9rapidjson19GenericStringBufferINS2_4UTF8IcEENS2_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISC_EERKSt10shared_ptrIKNS_9IDataTypeEE
Unexecuted instantiation: _ZN5doris17histogram_to_jsonINS_7DecimalIN4wide7integerILm256EiEEEEEEbRN9rapidjson19GenericStringBufferINS6_4UTF8IcEENS6_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISG_EERKSt10shared_ptrIKNS_9IDataTypeEE
_ZN5doris17histogram_to_jsonINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRN9rapidjson19GenericStringBufferINS7_4UTF8IcEENS7_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISH_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
31
                       const DataTypePtr& data_type) {
245
31
    rapidjson::Document doc;
246
31
    doc.SetObject();
247
31
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
31
    int num_buckets = cast_set<int>(buckets.size());
250
31
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
31
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
31
    bucket_arr.Reserve(num_buckets, allocator);
254
255
31
    std::stringstream ss1;
256
31
    std::stringstream ss2;
257
258
31
    rapidjson::Value lower_val;
259
31
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
31
    MutableColumnPtr lower_column = data_type->create_column();
263
31
    MutableColumnPtr upper_column = data_type->create_column();
264
60
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
        if constexpr (!std::is_same_v<T, std::string>) {
268
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
        }
271
60
    }
272
31
    size_t row_num = 0;
273
274
31
    auto format_options = DataTypeSerDe::get_default_format_options();
275
31
    auto time_zone = cctz::utc_time_zone();
276
31
    format_options.timezone = &time_zone;
277
278
60
    for (const auto& bucket : buckets) {
279
60
        if constexpr (std::is_same_v<T, std::string>) {
280
60
            lower_val.SetString(bucket.lower.data(),
281
60
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
60
            upper_val.SetString(bucket.upper.data(),
283
60
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
        } else {
285
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
            ++row_num;
288
            lower_val.SetString(lower_str.data(),
289
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
            upper_val.SetString(upper_str.data(),
291
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
        }
293
60
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
60
        bucket_json.AddMember("lower", lower_val, allocator);
295
60
        bucket_json.AddMember("upper", upper_val, allocator);
296
60
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
60
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
60
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
60
        bucket_arr.PushBack(bucket_json, allocator);
301
60
    }
302
303
31
    doc.AddMember("buckets", bucket_arr, allocator);
304
31
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
31
    doc.Accept(writer);
306
307
31
    return !buckets.empty() && buffer.GetSize() > 0;
308
31
}
_ZN5doris17histogram_to_jsonINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRN9rapidjson19GenericStringBufferINS4_4UTF8IcEENS4_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISE_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
14
                       const DataTypePtr& data_type) {
245
14
    rapidjson::Document doc;
246
14
    doc.SetObject();
247
14
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
14
    int num_buckets = cast_set<int>(buckets.size());
250
14
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
14
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
14
    bucket_arr.Reserve(num_buckets, allocator);
254
255
14
    std::stringstream ss1;
256
14
    std::stringstream ss2;
257
258
14
    rapidjson::Value lower_val;
259
14
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
14
    MutableColumnPtr lower_column = data_type->create_column();
263
14
    MutableColumnPtr upper_column = data_type->create_column();
264
40
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
40
        if constexpr (!std::is_same_v<T, std::string>) {
268
40
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
40
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
40
        }
271
40
    }
272
14
    size_t row_num = 0;
273
274
14
    auto format_options = DataTypeSerDe::get_default_format_options();
275
14
    auto time_zone = cctz::utc_time_zone();
276
14
    format_options.timezone = &time_zone;
277
278
40
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
40
        } else {
285
40
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
40
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
40
            ++row_num;
288
40
            lower_val.SetString(lower_str.data(),
289
40
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
40
            upper_val.SetString(upper_str.data(),
291
40
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
40
        }
293
40
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
40
        bucket_json.AddMember("lower", lower_val, allocator);
295
40
        bucket_json.AddMember("upper", upper_val, allocator);
296
40
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
40
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
40
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
40
        bucket_arr.PushBack(bucket_json, allocator);
301
40
    }
302
303
14
    doc.AddMember("buckets", bucket_arr, allocator);
304
14
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
14
    doc.Accept(writer);
306
307
14
    return !buckets.empty() && buffer.GetSize() > 0;
308
14
}
_ZN5doris17histogram_to_jsonINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRN9rapidjson19GenericStringBufferINS4_4UTF8IcEENS4_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISE_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
14
                       const DataTypePtr& data_type) {
245
14
    rapidjson::Document doc;
246
14
    doc.SetObject();
247
14
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
14
    int num_buckets = cast_set<int>(buckets.size());
250
14
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
14
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
14
    bucket_arr.Reserve(num_buckets, allocator);
254
255
14
    std::stringstream ss1;
256
14
    std::stringstream ss2;
257
258
14
    rapidjson::Value lower_val;
259
14
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
14
    MutableColumnPtr lower_column = data_type->create_column();
263
14
    MutableColumnPtr upper_column = data_type->create_column();
264
39
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
39
        if constexpr (!std::is_same_v<T, std::string>) {
268
39
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
39
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
39
        }
271
39
    }
272
14
    size_t row_num = 0;
273
274
14
    auto format_options = DataTypeSerDe::get_default_format_options();
275
14
    auto time_zone = cctz::utc_time_zone();
276
14
    format_options.timezone = &time_zone;
277
278
39
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
39
        } else {
285
39
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
39
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
39
            ++row_num;
288
39
            lower_val.SetString(lower_str.data(),
289
39
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
39
            upper_val.SetString(upper_str.data(),
291
39
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
39
        }
293
39
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
39
        bucket_json.AddMember("lower", lower_val, allocator);
295
39
        bucket_json.AddMember("upper", upper_val, allocator);
296
39
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
39
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
39
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
39
        bucket_arr.PushBack(bucket_json, allocator);
301
39
    }
302
303
14
    doc.AddMember("buckets", bucket_arr, allocator);
304
14
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
14
    doc.Accept(writer);
306
307
14
    return !buckets.empty() && buffer.GetSize() > 0;
308
14
}
Unexecuted instantiation: _ZN5doris17histogram_to_jsonINS_16TimeStampNsValueEEEbRN9rapidjson19GenericStringBufferINS2_4UTF8IcEENS2_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISC_EERKSt10shared_ptrIKNS_9IDataTypeEE
Unexecuted instantiation: _ZN5doris17histogram_to_jsonINS_16TimestampTzValueEEEbRN9rapidjson19GenericStringBufferINS2_4UTF8IcEENS2_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISC_EERKSt10shared_ptrIKNS_9IDataTypeEE
_ZN5doris17histogram_to_jsonIoEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
6
                       const DataTypePtr& data_type) {
245
6
    rapidjson::Document doc;
246
6
    doc.SetObject();
247
6
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
6
    int num_buckets = cast_set<int>(buckets.size());
250
6
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
6
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
6
    bucket_arr.Reserve(num_buckets, allocator);
254
255
6
    std::stringstream ss1;
256
6
    std::stringstream ss2;
257
258
6
    rapidjson::Value lower_val;
259
6
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
6
    MutableColumnPtr lower_column = data_type->create_column();
263
6
    MutableColumnPtr upper_column = data_type->create_column();
264
20
    for (const auto& bucket : buckets) {
265
        // String type is different, it has to pass in length
266
        // if it is string type , directly use string value
267
20
        if constexpr (!std::is_same_v<T, std::string>) {
268
20
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
20
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
20
        }
271
20
    }
272
6
    size_t row_num = 0;
273
274
6
    auto format_options = DataTypeSerDe::get_default_format_options();
275
6
    auto time_zone = cctz::utc_time_zone();
276
6
    format_options.timezone = &time_zone;
277
278
20
    for (const auto& bucket : buckets) {
279
        if constexpr (std::is_same_v<T, std::string>) {
280
            lower_val.SetString(bucket.lower.data(),
281
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
            upper_val.SetString(bucket.upper.data(),
283
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
20
        } else {
285
20
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
20
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
20
            ++row_num;
288
20
            lower_val.SetString(lower_str.data(),
289
20
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
20
            upper_val.SetString(upper_str.data(),
291
20
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
20
        }
293
20
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
20
        bucket_json.AddMember("lower", lower_val, allocator);
295
20
        bucket_json.AddMember("upper", upper_val, allocator);
296
20
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
20
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
20
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
20
        bucket_arr.PushBack(bucket_json, allocator);
301
20
    }
302
303
6
    doc.AddMember("buckets", bucket_arr, allocator);
304
6
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
6
    doc.Accept(writer);
306
307
6
    return !buckets.empty() && buffer.GetSize() > 0;
308
6
}
309
} // namespace  doris