Coverage Report

Created: 2026-09-29 06:08

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
2.20k
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_7DecimalIiEEEC2ES2_S2_mmm
Line
Count
Source
35
133
            : 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
188
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_11DateV2ValueINS_15DateV2ValueTypeEEEEC2ES3_S3_mmm
Line
Count
Source
35
266
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEC2ES3_S3_mmm
Line
Count
Source
35
265
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_16TimeStampNsValueEEC2ES1_S1_mmm
Line
Count
Source
35
142
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketINS_16TimestampTzValueEEC2ES1_S1_mmm
Line
Count
Source
35
3
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIhEC2Ehhmmm
Line
Count
Source
35
2
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIaEC2Eaammm
Line
Count
Source
35
140
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIsEC2Essmmm
Line
Count
Source
35
142
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIiEC2Eiimmm
Line
Count
Source
35
278
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIlEC2Ellmmm
Line
Count
Source
35
222
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketInEC2Ennmmm
Line
Count
Source
35
151
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIfEC2Effmmm
Line
Count
Source
35
138
            : lower(lower), upper(upper), ndv(ndv), count(count), pre_sum(pre_sum) {}
_ZN5doris6BucketIdEC2Eddmmm
Line
Count
Source
35
138
            : 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
721
                             const size_t num_buckets) {
57
721
    if (value_map.empty()) {
58
2
        return false;
59
719
    };
60
61
719
    size_t used_buckets = 1;
62
719
    size_t current_bucket_size = 0;
63
64
59.1k
    for (const auto& [value, count] : value_map) {
65
59.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
59.1k
        if (current_bucket_size > max_bucket_size) {
70
1.85k
            ++used_buckets;
71
1.85k
            current_bucket_size = count;
72
1.85k
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
59.1k
        if (used_buckets > num_buckets) {
76
317
            return false;
77
317
        }
78
59.1k
    }
79
80
402
    return true;
81
719
}
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsIhEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
_ZN5doris23can_assign_into_bucketsIaEEbRKSt3mapIT_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
2.43k
    for (const auto& [value, count] : value_map) {
65
2.43k
        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
2.43k
        if (current_bucket_size > max_bucket_size) {
70
127
            ++used_buckets;
71
127
            current_bucket_size = count;
72
127
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.43k
        if (used_buckets > num_buckets) {
76
18
            return false;
77
18
        }
78
2.43k
    }
79
80
22
    return true;
81
40
}
_ZN5doris23can_assign_into_bucketsIsEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
53
                             const size_t num_buckets) {
57
53
    if (value_map.empty()) {
58
0
        return false;
59
53
    };
60
61
53
    size_t used_buckets = 1;
62
53
    size_t current_bucket_size = 0;
63
64
2.54k
    for (const auto& [value, count] : value_map) {
65
2.54k
        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
2.54k
        if (current_bucket_size > max_bucket_size) {
70
145
            ++used_buckets;
71
145
            current_bucket_size = count;
72
145
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.54k
        if (used_buckets > num_buckets) {
76
25
            return false;
77
25
        }
78
2.54k
    }
79
80
28
    return true;
81
53
}
_ZN5doris23can_assign_into_bucketsIiEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
162
                             const size_t num_buckets) {
57
162
    if (value_map.empty()) {
58
2
        return false;
59
160
    };
60
61
160
    size_t used_buckets = 1;
62
160
    size_t current_bucket_size = 0;
63
64
2.81k
    for (const auto& [value, count] : value_map) {
65
2.81k
        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
2.81k
        if (current_bucket_size > max_bucket_size) {
70
334
            ++used_buckets;
71
334
            current_bucket_size = count;
72
334
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.81k
        if (used_buckets > num_buckets) {
76
59
            return false;
77
59
        }
78
2.81k
    }
79
80
101
    return true;
81
160
}
_ZN5doris23can_assign_into_bucketsIlEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
47
                             const size_t num_buckets) {
57
47
    if (value_map.empty()) {
58
0
        return false;
59
47
    };
60
61
47
    size_t used_buckets = 1;
62
47
    size_t current_bucket_size = 0;
63
64
2.48k
    for (const auto& [value, count] : value_map) {
65
2.48k
        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
2.48k
        if (current_bucket_size > max_bucket_size) {
70
147
            ++used_buckets;
71
147
            current_bucket_size = count;
72
147
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.48k
        if (used_buckets > num_buckets) {
76
24
            return false;
77
24
        }
78
2.48k
    }
79
80
23
    return true;
81
47
}
_ZN5doris23can_assign_into_bucketsInEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
45
                             const size_t num_buckets) {
57
45
    if (value_map.empty()) {
58
0
        return false;
59
45
    };
60
61
45
    size_t used_buckets = 1;
62
45
    size_t current_bucket_size = 0;
63
64
2.48k
    for (const auto& [value, count] : value_map) {
65
2.48k
        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
2.48k
        if (current_bucket_size > max_bucket_size) {
70
153
            ++used_buckets;
71
153
            current_bucket_size = count;
72
153
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.48k
        if (used_buckets > num_buckets) {
76
22
            return false;
77
22
        }
78
2.48k
    }
79
80
23
    return true;
81
45
}
_ZN5doris23can_assign_into_bucketsIfEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
44
                             const size_t num_buckets) {
57
44
    if (value_map.empty()) {
58
0
        return false;
59
44
    };
60
61
44
    size_t used_buckets = 1;
62
44
    size_t current_bucket_size = 0;
63
64
2.44k
    for (const auto& [value, count] : value_map) {
65
2.44k
        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
2.44k
        if (current_bucket_size > max_bucket_size) {
70
135
            ++used_buckets;
71
135
            current_bucket_size = count;
72
135
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.44k
        if (used_buckets > num_buckets) {
76
22
            return false;
77
22
        }
78
2.44k
    }
79
80
22
    return true;
81
44
}
_ZN5doris23can_assign_into_bucketsIdEEbRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEmm
Line
Count
Source
56
44
                             const size_t num_buckets) {
57
44
    if (value_map.empty()) {
58
0
        return false;
59
44
    };
60
61
44
    size_t used_buckets = 1;
62
44
    size_t current_bucket_size = 0;
63
64
2.44k
    for (const auto& [value, count] : value_map) {
65
2.44k
        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
2.44k
        if (current_bucket_size > max_bucket_size) {
70
135
            ++used_buckets;
71
135
            current_bucket_size = count;
72
135
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.44k
        if (used_buckets > num_buckets) {
76
22
            return false;
77
22
        }
78
2.44k
    }
79
80
22
    return true;
81
44
}
_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
119
                             const size_t num_buckets) {
57
119
    if (value_map.empty()) {
58
0
        return false;
59
119
    };
60
61
119
    size_t used_buckets = 1;
62
119
    size_t current_bucket_size = 0;
63
64
36.3k
    for (const auto& [value, count] : value_map) {
65
36.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
36.3k
        if (current_bucket_size > max_bucket_size) {
70
281
            ++used_buckets;
71
281
            current_bucket_size = count;
72
281
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
36.3k
        if (used_buckets > num_buckets) {
76
48
            return false;
77
48
        }
78
36.3k
    }
79
80
71
    return true;
81
119
}
_ZN5doris23can_assign_into_bucketsINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEmm
Line
Count
Source
56
64
                             const size_t num_buckets) {
57
64
    if (value_map.empty()) {
58
0
        return false;
59
64
    };
60
61
64
    size_t used_buckets = 1;
62
64
    size_t current_bucket_size = 0;
63
64
2.50k
    for (const auto& [value, count] : value_map) {
65
2.50k
        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
2.50k
        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
2.50k
        if (used_buckets > num_buckets) {
76
30
            return false;
77
30
        }
78
2.50k
    }
79
80
34
    return true;
81
64
}
_ZN5doris23can_assign_into_bucketsINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEmm
Line
Count
Source
56
64
                             const size_t num_buckets) {
57
64
    if (value_map.empty()) {
58
0
        return false;
59
64
    };
60
61
64
    size_t used_buckets = 1;
62
64
    size_t current_bucket_size = 0;
63
64
2.50k
    for (const auto& [value, count] : value_map) {
65
2.50k
        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
2.50k
        if (current_bucket_size > max_bucket_size) {
70
172
            ++used_buckets;
71
172
            current_bucket_size = count;
72
172
        }
73
74
        // If we have used more buckets than num_buckets, we cannot assign the values to buckets.
75
2.50k
        if (used_buckets > num_buckets) {
76
30
            return false;
77
30
        }
78
2.50k
    }
79
80
34
    return true;
81
64
}
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_16TimeStampNsValueEEEbRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEmm
Unexecuted instantiation: _ZN5doris23can_assign_into_bucketsINS_16TimestampTzValueEEEbRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_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
806
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
806
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
806
    size_t total_values = 0;
99
9.82k
    for (const auto& [value, count] : value_map) {
100
9.82k
        total_values += count;
101
9.82k
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
806
    if (num_buckets == 1) {
105
35
        return total_values;
106
35
    }
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
771
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
771
    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
771
    int search_step = 0;
119
771
    const int max_search_steps =
120
771
            10; // Limit the number of search steps to avoid excessive iteration
121
122
1.46k
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
693
        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
693
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
388
            upper_bucket_values = bucket_values;
130
388
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
305
            lower_bucket_values = bucket_values;
133
305
        }
134
        // Increment the search step counter
135
693
        ++search_step;
136
693
    }
137
138
771
    return upper_bucket_values;
139
806
}
_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
45
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
45
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
45
    size_t total_values = 0;
99
541
    for (const auto& [value, count] : value_map) {
100
541
        total_values += count;
101
541
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
45
    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
44
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
44
    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
44
    int search_step = 0;
119
44
    const int max_search_steps =
120
44
            10; // Limit the number of search steps to avoid excessive iteration
121
122
84
    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
44
    return upper_bucket_values;
139
45
}
_ZN5doris27calculate_bucket_max_valuesIsEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
45
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
45
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
45
    size_t total_values = 0;
99
549
    for (const auto& [value, count] : value_map) {
100
549
        total_values += count;
101
549
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
45
    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
45
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
45
    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
45
    int search_step = 0;
119
45
    const int max_search_steps =
120
45
            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
53
        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
53
        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
25
            lower_bucket_values = bucket_values;
133
25
        }
134
        // Increment the search step counter
135
53
        ++search_step;
136
53
    }
137
138
45
    return upper_bucket_values;
139
45
}
_ZN5doris27calculate_bucket_max_valuesIiEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
150
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
150
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
150
    size_t total_values = 0;
99
697
    for (const auto& [value, count] : value_map) {
100
697
        total_values += count;
101
697
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
150
    if (num_buckets == 1) {
105
34
        return total_values;
106
34
    }
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
116
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
116
    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
116
    int search_step = 0;
119
116
    const int max_search_steps =
120
116
            10; // Limit the number of search steps to avoid excessive iteration
121
122
250
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
134
        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
134
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
87
            upper_bucket_values = bucket_values;
130
87
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
47
            lower_bucket_values = bucket_values;
133
47
        }
134
        // Increment the search step counter
135
134
        ++search_step;
136
134
    }
137
138
116
    return upper_bucket_values;
139
150
}
_ZN5doris27calculate_bucket_max_valuesIlEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
61
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
61
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
61
    size_t total_values = 0;
99
618
    for (const auto& [value, count] : value_map) {
100
618
        total_values += count;
101
618
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
61
    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
61
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
61
    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
61
    int search_step = 0;
119
61
    const int max_search_steps =
120
61
            10; // Limit the number of search steps to avoid excessive iteration
121
122
108
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
47
        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
47
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
23
            upper_bucket_values = bucket_values;
130
24
        } 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
47
        ++search_step;
136
47
    }
137
138
61
    return upper_bucket_values;
139
61
}
_ZN5doris27calculate_bucket_max_valuesInEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
44
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
44
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
44
    size_t total_values = 0;
99
543
    for (const auto& [value, count] : value_map) {
100
543
        total_values += count;
101
543
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
44
    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
44
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
44
    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
44
    int search_step = 0;
119
44
    const int max_search_steps =
120
44
            10; // Limit the number of search steps to avoid excessive iteration
121
122
89
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
45
        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
45
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
23
            upper_bucket_values = bucket_values;
130
23
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
22
            lower_bucket_values = bucket_values;
133
22
        }
134
        // Increment the search step counter
135
45
        ++search_step;
136
45
    }
137
138
44
    return upper_bucket_values;
139
44
}
_ZN5doris27calculate_bucket_max_valuesIfEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
43
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
43
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
43
    size_t total_values = 0;
99
528
    for (const auto& [value, count] : value_map) {
100
528
        total_values += count;
101
528
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
43
    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
43
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
43
    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
43
    int search_step = 0;
119
43
    const int max_search_steps =
120
43
            10; // Limit the number of search steps to avoid excessive iteration
121
122
87
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
44
        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
44
        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
22
            lower_bucket_values = bucket_values;
133
22
        }
134
        // Increment the search step counter
135
44
        ++search_step;
136
44
    }
137
138
43
    return upper_bucket_values;
139
43
}
_ZN5doris27calculate_bucket_max_valuesIdEEmRKSt3mapIT_mSt4lessIS2_ESaISt4pairIKS2_mEEEm
Line
Count
Source
93
43
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
43
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
43
    size_t total_values = 0;
99
528
    for (const auto& [value, count] : value_map) {
100
528
        total_values += count;
101
528
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
43
    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
43
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
43
    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
43
    int search_step = 0;
119
43
    const int max_search_steps =
120
43
            10; // Limit the number of search steps to avoid excessive iteration
121
122
87
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
44
        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
44
        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
22
            lower_bucket_values = bucket_values;
133
22
        }
134
        // Increment the search step counter
135
44
        ++search_step;
136
44
    }
137
138
43
    return upper_bucket_values;
139
43
}
_ZN5doris27calculate_bucket_max_valuesINS_7DecimalIiEEEEmRKSt3mapIT_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Line
Count
Source
93
45
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
45
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
45
    size_t total_values = 0;
99
161
    for (const auto& [value, count] : value_map) {
100
161
        total_values += count;
101
161
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
45
    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
45
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
45
    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
45
    int search_step = 0;
119
45
    const int max_search_steps =
120
45
            10; // Limit the number of search steps to avoid excessive iteration
121
122
84
    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
45
    return upper_bucket_values;
139
45
}
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
102
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
102
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
102
    size_t total_values = 0;
99
4.20k
    for (const auto& [value, count] : value_map) {
100
4.20k
        total_values += count;
101
4.20k
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
102
    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
102
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
102
    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
102
    int search_step = 0;
119
102
    const int max_search_steps =
120
102
            10; // Limit the number of search steps to avoid excessive iteration
121
122
221
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
119
        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
119
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
71
            upper_bucket_values = bucket_values;
130
71
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
48
            lower_bucket_values = bucket_values;
133
48
        }
134
        // Increment the search step counter
135
119
        ++search_step;
136
119
    }
137
138
102
    return upper_bucket_values;
139
102
}
_ZN5doris27calculate_bucket_max_valuesINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEmRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Line
Count
Source
93
83
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
83
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
83
    size_t total_values = 0;
99
658
    for (const auto& [value, count] : value_map) {
100
658
        total_values += count;
101
658
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
83
    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
83
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
83
    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
83
    int search_step = 0;
119
83
    const int max_search_steps =
120
83
            10; // Limit the number of search steps to avoid excessive iteration
121
122
147
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
64
        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
64
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
34
            upper_bucket_values = bucket_values;
130
34
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
30
            lower_bucket_values = bucket_values;
133
30
        }
134
        // Increment the search step counter
135
64
        ++search_step;
136
64
    }
137
138
83
    return upper_bucket_values;
139
83
}
_ZN5doris27calculate_bucket_max_valuesINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEmRKSt3mapIT_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Line
Count
Source
93
83
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
83
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
83
    size_t total_values = 0;
99
657
    for (const auto& [value, count] : value_map) {
100
657
        total_values += count;
101
657
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
83
    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
83
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
83
    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
83
    int search_step = 0;
119
83
    const int max_search_steps =
120
83
            10; // Limit the number of search steps to avoid excessive iteration
121
122
147
    while (upper_bucket_values > lower_bucket_values + 1 && search_step < max_search_steps) {
123
        // Calculate the midpoint of the upper and lower bounds
124
64
        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
64
        if (can_assign_into_buckets(value_map, bucket_values, num_buckets)) {
128
            // If it can, then set the upper bound to the midpoint
129
34
            upper_bucket_values = bucket_values;
130
34
        } else {
131
            // If it can't, then set the lower bound to the midpoint
132
30
            lower_bucket_values = bucket_values;
133
30
        }
134
        // Increment the search step counter
135
64
        ++search_step;
136
64
    }
137
138
83
    return upper_bucket_values;
139
83
}
_ZN5doris27calculate_bucket_max_valuesINS_16TimeStampNsValueEEEmRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
93
60
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
60
    assert(!value_map.empty());
96
97
    // Calculate the total number of values in the map using std::accumulate()
98
60
    size_t total_values = 0;
99
142
    for (const auto& [value, count] : value_map) {
100
142
        total_values += count;
101
142
    }
102
103
    // If there is only one bucket, then all values will be assigned to that bucket
104
60
    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
60
    size_t upper_bucket_values = 2 * total_values / (num_buckets - 1) + 1;
113
114
    // Initialize the lower bound to 0
115
60
    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
60
    int search_step = 0;
119
60
    const int max_search_steps =
120
60
            10; // Limit the number of search steps to avoid excessive iteration
121
122
60
    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
60
    return upper_bucket_values;
139
60
}
_ZN5doris27calculate_bucket_max_valuesINS_16TimestampTzValueEEEmRKSt3mapIT_mSt4lessIS3_ESaISt4pairIKS3_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
3
    for (const auto& [value, count] : value_map) {
100
3
        total_values += count;
101
3
    }
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
}
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
880
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
880
    if (ordered_map.empty()) {
177
86
        return false;
178
86
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
794
    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
794
    buckets.clear();
186
794
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
794
    size_t distinct_values_count = 0;
190
794
    size_t values_count = 0;
191
794
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
794
    auto remaining_distinct_values = ordered_map.size();
195
196
794
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
794
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
10.5k
    for (; it != ordered_map.end(); ++it) {
203
9.80k
        const auto count = it->second;
204
9.80k
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
9.80k
        distinct_values_count++;
208
9.80k
        remaining_distinct_values--;
209
9.80k
        values_count += count;
210
9.80k
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
9.80k
        auto next = std::next(it);
214
9.80k
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
9.80k
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
9.80k
            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
7.60k
            continue;
222
7.60k
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
2.20k
        auto pre_sum = cumulative_values - values_count;
226
227
2.20k
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
2.20k
                             pre_sum);
229
2.20k
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
2.20k
        if (next != ordered_map.end()) {
233
1.41k
            lower_value = &next->first;
234
1.41k
        }
235
2.20k
        values_count = 0;
236
2.20k
        distinct_values_count = 0;
237
2.20k
    }
238
239
794
    return true;
240
880
}
_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
53
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
53
    if (ordered_map.empty()) {
177
8
        return false;
178
8
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
45
    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
45
    buckets.clear();
186
45
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
45
    size_t distinct_values_count = 0;
190
45
    size_t values_count = 0;
191
45
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
45
    auto remaining_distinct_values = ordered_map.size();
195
196
45
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
45
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
586
    for (; it != ordered_map.end(); ++it) {
203
541
        const auto count = it->second;
204
541
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
541
        distinct_values_count++;
208
541
        remaining_distinct_values--;
209
541
        values_count += count;
210
541
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
541
        auto next = std::next(it);
214
541
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
541
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
541
            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
401
            continue;
222
401
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
140
        auto pre_sum = cumulative_values - values_count;
226
227
140
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
140
                             pre_sum);
229
140
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
140
        if (next != ordered_map.end()) {
233
95
            lower_value = &next->first;
234
95
        }
235
140
        values_count = 0;
236
140
        distinct_values_count = 0;
237
140
    }
238
239
45
    return true;
240
53
}
_ZN5doris15build_histogramIsEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
52
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
52
    if (ordered_map.empty()) {
177
7
        return false;
178
7
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
45
    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
45
    buckets.clear();
186
45
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
45
    size_t distinct_values_count = 0;
190
45
    size_t values_count = 0;
191
45
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
45
    auto remaining_distinct_values = ordered_map.size();
195
196
45
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
45
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
594
    for (; it != ordered_map.end(); ++it) {
203
549
        const auto count = it->second;
204
549
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
549
        distinct_values_count++;
208
549
        remaining_distinct_values--;
209
549
        values_count += count;
210
549
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
549
        auto next = std::next(it);
214
549
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
549
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
549
            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
407
            continue;
222
407
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
142
        auto pre_sum = cumulative_values - values_count;
226
227
142
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
142
                             pre_sum);
229
142
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
142
        if (next != ordered_map.end()) {
233
97
            lower_value = &next->first;
234
97
        }
235
142
        values_count = 0;
236
142
        distinct_values_count = 0;
237
142
    }
238
239
45
    return true;
240
52
}
_ZN5doris15build_histogramIiEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
150
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
150
    if (ordered_map.empty()) {
177
12
        return false;
178
12
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
138
    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
138
    buckets.clear();
186
138
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
138
    size_t distinct_values_count = 0;
190
138
    size_t values_count = 0;
191
138
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
138
    auto remaining_distinct_values = ordered_map.size();
195
196
138
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
138
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
811
    for (; it != ordered_map.end(); ++it) {
203
673
        const auto count = it->second;
204
673
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
673
        distinct_values_count++;
208
673
        remaining_distinct_values--;
209
673
        values_count += count;
210
673
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
673
        auto next = std::next(it);
214
673
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
673
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
673
            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
399
            continue;
222
399
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
274
        auto pre_sum = cumulative_values - values_count;
226
227
274
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
274
                             pre_sum);
229
274
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
274
        if (next != ordered_map.end()) {
233
136
            lower_value = &next->first;
234
136
        }
235
274
        values_count = 0;
236
274
        distinct_values_count = 0;
237
274
    }
238
239
138
    return true;
240
150
}
_ZN5doris15build_histogramIlEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
69
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
69
    if (ordered_map.empty()) {
177
8
        return false;
178
8
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
61
    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
61
    buckets.clear();
186
61
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
61
    size_t distinct_values_count = 0;
190
61
    size_t values_count = 0;
191
61
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
61
    auto remaining_distinct_values = ordered_map.size();
195
196
61
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
61
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
679
    for (; it != ordered_map.end(); ++it) {
203
618
        const auto count = it->second;
204
618
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
618
        distinct_values_count++;
208
618
        remaining_distinct_values--;
209
618
        values_count += count;
210
618
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
618
        auto next = std::next(it);
214
618
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
618
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
618
            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
396
            continue;
222
396
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
222
        auto pre_sum = cumulative_values - values_count;
226
227
222
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
222
                             pre_sum);
229
222
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
222
        if (next != ordered_map.end()) {
233
161
            lower_value = &next->first;
234
161
        }
235
222
        values_count = 0;
236
222
        distinct_values_count = 0;
237
222
    }
238
239
61
    return true;
240
69
}
_ZN5doris15build_histogramInEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
52
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
52
    if (ordered_map.empty()) {
177
8
        return false;
178
8
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
44
    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
44
    buckets.clear();
186
44
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
44
    size_t distinct_values_count = 0;
190
44
    size_t values_count = 0;
191
44
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
44
    auto remaining_distinct_values = ordered_map.size();
195
196
44
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
44
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
587
    for (; it != ordered_map.end(); ++it) {
203
543
        const auto count = it->second;
204
543
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
543
        distinct_values_count++;
208
543
        remaining_distinct_values--;
209
543
        values_count += count;
210
543
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
543
        auto next = std::next(it);
214
543
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
543
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
543
            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
392
            continue;
222
392
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
151
        auto pre_sum = cumulative_values - values_count;
226
227
151
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
151
                             pre_sum);
229
151
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
151
        if (next != ordered_map.end()) {
233
107
            lower_value = &next->first;
234
107
        }
235
151
        values_count = 0;
236
151
        distinct_values_count = 0;
237
151
    }
238
239
44
    return true;
240
52
}
_ZN5doris15build_histogramIfEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
50
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
50
    if (ordered_map.empty()) {
177
7
        return false;
178
7
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
43
    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
43
    buckets.clear();
186
43
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
43
    size_t distinct_values_count = 0;
190
43
    size_t values_count = 0;
191
43
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
43
    auto remaining_distinct_values = ordered_map.size();
195
196
43
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
43
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
571
    for (; it != ordered_map.end(); ++it) {
203
528
        const auto count = it->second;
204
528
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
528
        distinct_values_count++;
208
528
        remaining_distinct_values--;
209
528
        values_count += count;
210
528
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
528
        auto next = std::next(it);
214
528
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
528
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
528
            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
390
            continue;
222
390
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
138
        auto pre_sum = cumulative_values - values_count;
226
227
138
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
138
                             pre_sum);
229
138
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
138
        if (next != ordered_map.end()) {
233
95
            lower_value = &next->first;
234
95
        }
235
138
        values_count = 0;
236
138
        distinct_values_count = 0;
237
138
    }
238
239
43
    return true;
240
50
}
_ZN5doris15build_histogramIdEEbRSt6vectorINS_6BucketIT_EESaIS4_EERKSt3mapIS3_mSt4lessIS3_ESaISt4pairIKS3_mEEEm
Line
Count
Source
174
50
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
50
    if (ordered_map.empty()) {
177
7
        return false;
178
7
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
43
    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
43
    buckets.clear();
186
43
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
43
    size_t distinct_values_count = 0;
190
43
    size_t values_count = 0;
191
43
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
43
    auto remaining_distinct_values = ordered_map.size();
195
196
43
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
43
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
571
    for (; it != ordered_map.end(); ++it) {
203
528
        const auto count = it->second;
204
528
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
528
        distinct_values_count++;
208
528
        remaining_distinct_values--;
209
528
        values_count += count;
210
528
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
528
        auto next = std::next(it);
214
528
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
528
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
528
            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
390
            continue;
222
390
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
138
        auto pre_sum = cumulative_values - values_count;
226
227
138
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
138
                             pre_sum);
229
138
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
138
        if (next != ordered_map.end()) {
233
95
            lower_value = &next->first;
234
95
        }
235
138
        values_count = 0;
236
138
        distinct_values_count = 0;
237
138
    }
238
239
43
    return true;
240
50
}
_ZN5doris15build_histogramINS_7DecimalIiEEEEbRSt6vectorINS_6BucketIT_EESaIS6_EERKSt3mapIS5_mSt4lessIS5_ESaISt4pairIKS5_mEEEm
Line
Count
Source
174
49
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
49
    if (ordered_map.empty()) {
177
4
        return false;
178
4
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
45
    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
45
    buckets.clear();
186
45
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
45
    size_t distinct_values_count = 0;
190
45
    size_t values_count = 0;
191
45
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
45
    auto remaining_distinct_values = ordered_map.size();
195
196
45
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
45
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
206
    for (; it != ordered_map.end(); ++it) {
203
161
        const auto count = it->second;
204
161
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
161
        distinct_values_count++;
208
161
        remaining_distinct_values--;
209
161
        values_count += count;
210
161
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
161
        auto next = std::next(it);
214
161
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
161
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
161
            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
133
        auto pre_sum = cumulative_values - values_count;
226
227
133
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
133
                             pre_sum);
229
133
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
133
        if (next != ordered_map.end()) {
233
88
            lower_value = &next->first;
234
88
        }
235
133
        values_count = 0;
236
133
        distinct_values_count = 0;
237
133
    }
238
239
45
    return true;
240
49
}
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
109
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
109
    if (ordered_map.empty()) {
177
7
        return false;
178
7
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
102
    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
102
    buckets.clear();
186
102
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
102
    size_t distinct_values_count = 0;
190
102
    size_t values_count = 0;
191
102
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
102
    auto remaining_distinct_values = ordered_map.size();
195
196
102
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
102
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
4.30k
    for (; it != ordered_map.end(); ++it) {
203
4.20k
        const auto count = it->second;
204
4.20k
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
4.20k
        distinct_values_count++;
208
4.20k
        remaining_distinct_values--;
209
4.20k
        values_count += count;
210
4.20k
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
4.20k
        auto next = std::next(it);
214
4.20k
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
4.20k
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
4.20k
            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
4.01k
            continue;
222
4.01k
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
188
        auto pre_sum = cumulative_values - values_count;
226
227
188
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
188
                             pre_sum);
229
188
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
188
        if (next != ordered_map.end()) {
233
86
            lower_value = &next->first;
234
86
        }
235
188
        values_count = 0;
236
188
        distinct_values_count = 0;
237
188
    }
238
239
102
    return true;
240
109
}
_ZN5doris15build_histogramINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRSt6vectorINS_6BucketIT_EESaIS7_EERKSt3mapIS6_mSt4lessIS6_ESaISt4pairIKS6_mEEEm
Line
Count
Source
174
90
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
90
    if (ordered_map.empty()) {
177
7
        return false;
178
7
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
83
    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
83
    buckets.clear();
186
83
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
83
    size_t distinct_values_count = 0;
190
83
    size_t values_count = 0;
191
83
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
83
    auto remaining_distinct_values = ordered_map.size();
195
196
83
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
83
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
741
    for (; it != ordered_map.end(); ++it) {
203
658
        const auto count = it->second;
204
658
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
658
        distinct_values_count++;
208
658
        remaining_distinct_values--;
209
658
        values_count += count;
210
658
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
658
        auto next = std::next(it);
214
658
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
658
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
658
            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
392
            continue;
222
392
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
266
        auto pre_sum = cumulative_values - values_count;
226
227
266
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
266
                             pre_sum);
229
266
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
266
        if (next != ordered_map.end()) {
233
183
            lower_value = &next->first;
234
183
        }
235
266
        values_count = 0;
236
266
        distinct_values_count = 0;
237
266
    }
238
239
83
    return true;
240
90
}
_ZN5doris15build_histogramINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRSt6vectorINS_6BucketIT_EESaIS7_EERKSt3mapIS6_mSt4lessIS6_ESaISt4pairIKS6_mEEEm
Line
Count
Source
174
90
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
90
    if (ordered_map.empty()) {
177
7
        return false;
178
7
    }
179
180
    // Calculate the maximum number of values that can be assigned to each bucket.
181
83
    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
83
    buckets.clear();
186
83
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
83
    size_t distinct_values_count = 0;
190
83
    size_t values_count = 0;
191
83
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
83
    auto remaining_distinct_values = ordered_map.size();
195
196
83
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
83
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
740
    for (; it != ordered_map.end(); ++it) {
203
657
        const auto count = it->second;
204
657
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
657
        distinct_values_count++;
208
657
        remaining_distinct_values--;
209
657
        values_count += count;
210
657
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
657
        auto next = std::next(it);
214
657
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
657
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
657
            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
392
            continue;
222
392
        }
223
224
        // Finalize the current bucket and add it to our collection of buckets.
225
265
        auto pre_sum = cumulative_values - values_count;
226
227
265
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
265
                             pre_sum);
229
265
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
265
        if (next != ordered_map.end()) {
233
182
            lower_value = &next->first;
234
182
        }
235
265
        values_count = 0;
236
265
        distinct_values_count = 0;
237
265
    }
238
239
83
    return true;
240
90
}
_ZN5doris15build_histogramINS_16TimeStampNsValueEEEbRSt6vectorINS_6BucketIT_EESaIS5_EERKSt3mapIS4_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Line
Count
Source
174
63
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
63
    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
60
    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
60
    buckets.clear();
186
60
    buckets.reserve(max_num_buckets);
187
188
    // Initialize bucket variables.
189
60
    size_t distinct_values_count = 0;
190
60
    size_t values_count = 0;
191
60
    size_t cumulative_values = 0;
192
193
    // Record how many values still need to be assigned.
194
60
    auto remaining_distinct_values = ordered_map.size();
195
196
60
    auto it = ordered_map.begin();
197
198
    // Lower value of the current bucket.
199
60
    const T* lower_value = &it->first;
200
201
    // Iterate over the ordered map of distinct values and their counts.
202
202
    for (; it != ordered_map.end(); ++it) {
203
142
        const auto count = it->second;
204
142
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
142
        distinct_values_count++;
208
142
        remaining_distinct_values--;
209
142
        values_count += count;
210
142
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
142
        auto next = std::next(it);
214
142
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
142
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
142
            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
142
        auto pre_sum = cumulative_values - values_count;
226
227
142
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
142
                             pre_sum);
229
142
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
142
        if (next != ordered_map.end()) {
233
82
            lower_value = &next->first;
234
82
        }
235
142
        values_count = 0;
236
142
        distinct_values_count = 0;
237
142
    }
238
239
60
    return true;
240
63
}
_ZN5doris15build_histogramINS_16TimestampTzValueEEEbRSt6vectorINS_6BucketIT_EESaIS5_EERKSt3mapIS4_mSt4lessIS4_ESaISt4pairIKS4_mEEEm
Line
Count
Source
174
1
                     const size_t max_num_buckets) {
175
    // If the input map is empty, there is nothing to build.
176
1
    if (ordered_map.empty()) {
177
0
        return false;
178
0
    }
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
4
    for (; it != ordered_map.end(); ++it) {
203
3
        const auto count = it->second;
204
3
        const auto current_value = it->first;
205
206
        // Update the bucket counts and track the number of distinct values assigned.
207
3
        distinct_values_count++;
208
3
        remaining_distinct_values--;
209
3
        values_count += count;
210
3
        cumulative_values += count;
211
212
        // Check whether the current value should be added to the current bucket.
213
3
        auto next = std::next(it);
214
3
        size_t remaining_empty_buckets = max_num_buckets - buckets.size() - 1;
215
216
3
        if (next != ordered_map.end() && remaining_distinct_values > remaining_empty_buckets &&
217
3
            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
3
        auto pre_sum = cumulative_values - values_count;
226
227
3
        Bucket<T> new_bucket(*lower_value, current_value, distinct_values_count, values_count,
228
3
                             pre_sum);
229
3
        buckets.push_back(new_bucket);
230
231
        // Reset variables for the next bucket.
232
3
        if (next != ordered_map.end()) {
233
2
            lower_value = &next->first;
234
2
        }
235
3
        values_count = 0;
236
3
        distinct_values_count = 0;
237
3
    }
238
239
1
    return true;
240
1
}
241
242
template <typename T>
243
bool histogram_to_json(rapidjson::StringBuffer& buffer, const std::vector<Bucket<T>>& buckets,
244
870
                       const DataTypePtr& data_type) {
245
870
    rapidjson::Document doc;
246
870
    doc.SetObject();
247
870
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
870
    int num_buckets = cast_set<int>(buckets.size());
250
870
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
870
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
870
    bucket_arr.Reserve(num_buckets, allocator);
254
255
870
    std::stringstream ss1;
256
870
    std::stringstream ss2;
257
258
870
    rapidjson::Value lower_val;
259
870
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
870
    MutableColumnPtr lower_column = data_type->create_column();
263
870
    MutableColumnPtr upper_column = data_type->create_column();
264
2.18k
    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.18k
        if constexpr (!std::is_same_v<T, std::string>) {
268
1.99k
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
1.99k
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
1.99k
        }
271
2.18k
    }
272
870
    size_t row_num = 0;
273
274
870
    auto format_options = DataTypeSerDe::get_default_format_options();
275
870
    auto time_zone = cctz::utc_time_zone();
276
870
    format_options.timezone = &time_zone;
277
278
2.18k
    for (const auto& bucket : buckets) {
279
2.18k
        if constexpr (std::is_same_v<T, std::string>) {
280
188
            lower_val.SetString(bucket.lower.data(),
281
188
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
188
            upper_val.SetString(bucket.upper.data(),
283
188
                                static_cast<rapidjson::SizeType>(bucket.upper.size()), allocator);
284
1.99k
        } else {
285
1.99k
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
1.99k
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
1.99k
            ++row_num;
288
1.99k
            lower_val.SetString(lower_str.data(),
289
1.99k
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
1.99k
            upper_val.SetString(upper_str.data(),
291
1.99k
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
1.99k
        }
293
2.18k
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
2.18k
        bucket_json.AddMember("lower", lower_val, allocator);
295
2.18k
        bucket_json.AddMember("upper", upper_val, allocator);
296
2.18k
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
2.18k
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
2.18k
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
2.18k
        bucket_arr.PushBack(bucket_json, allocator);
301
2.18k
    }
302
303
870
    doc.AddMember("buckets", bucket_arr, allocator);
304
870
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
870
    doc.Accept(writer);
306
307
870
    return !buckets.empty() && buffer.GetSize() > 0;
308
870
}
_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
53
                       const DataTypePtr& data_type) {
245
53
    rapidjson::Document doc;
246
53
    doc.SetObject();
247
53
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
53
    int num_buckets = cast_set<int>(buckets.size());
250
53
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
53
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
53
    bucket_arr.Reserve(num_buckets, allocator);
254
255
53
    std::stringstream ss1;
256
53
    std::stringstream ss2;
257
258
53
    rapidjson::Value lower_val;
259
53
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
53
    MutableColumnPtr lower_column = data_type->create_column();
263
53
    MutableColumnPtr upper_column = data_type->create_column();
264
140
    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
140
        if constexpr (!std::is_same_v<T, std::string>) {
268
140
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
140
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
140
        }
271
140
    }
272
53
    size_t row_num = 0;
273
274
53
    auto format_options = DataTypeSerDe::get_default_format_options();
275
53
    auto time_zone = cctz::utc_time_zone();
276
53
    format_options.timezone = &time_zone;
277
278
140
    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
140
        } else {
285
140
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
140
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
140
            ++row_num;
288
140
            lower_val.SetString(lower_str.data(),
289
140
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
140
            upper_val.SetString(upper_str.data(),
291
140
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
140
        }
293
140
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
140
        bucket_json.AddMember("lower", lower_val, allocator);
295
140
        bucket_json.AddMember("upper", upper_val, allocator);
296
140
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
140
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
140
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
140
        bucket_arr.PushBack(bucket_json, allocator);
301
140
    }
302
303
53
    doc.AddMember("buckets", bucket_arr, allocator);
304
53
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
53
    doc.Accept(writer);
306
307
53
    return !buckets.empty() && buffer.GetSize() > 0;
308
53
}
_ZN5doris17histogram_to_jsonIsEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
52
                       const DataTypePtr& data_type) {
245
52
    rapidjson::Document doc;
246
52
    doc.SetObject();
247
52
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
52
    int num_buckets = cast_set<int>(buckets.size());
250
52
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
52
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
52
    bucket_arr.Reserve(num_buckets, allocator);
254
255
52
    std::stringstream ss1;
256
52
    std::stringstream ss2;
257
258
52
    rapidjson::Value lower_val;
259
52
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
52
    MutableColumnPtr lower_column = data_type->create_column();
263
52
    MutableColumnPtr upper_column = data_type->create_column();
264
142
    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
142
        if constexpr (!std::is_same_v<T, std::string>) {
268
142
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
142
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
142
        }
271
142
    }
272
52
    size_t row_num = 0;
273
274
52
    auto format_options = DataTypeSerDe::get_default_format_options();
275
52
    auto time_zone = cctz::utc_time_zone();
276
52
    format_options.timezone = &time_zone;
277
278
142
    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
142
        } else {
285
142
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
142
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
142
            ++row_num;
288
142
            lower_val.SetString(lower_str.data(),
289
142
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
142
            upper_val.SetString(upper_str.data(),
291
142
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
142
        }
293
142
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
142
        bucket_json.AddMember("lower", lower_val, allocator);
295
142
        bucket_json.AddMember("upper", upper_val, allocator);
296
142
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
142
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
142
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
142
        bucket_arr.PushBack(bucket_json, allocator);
301
142
    }
302
303
52
    doc.AddMember("buckets", bucket_arr, allocator);
304
52
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
52
    doc.Accept(writer);
306
307
52
    return !buckets.empty() && buffer.GetSize() > 0;
308
52
}
_ZN5doris17histogram_to_jsonIiEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
140
                       const DataTypePtr& data_type) {
245
140
    rapidjson::Document doc;
246
140
    doc.SetObject();
247
140
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
140
    int num_buckets = cast_set<int>(buckets.size());
250
140
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
140
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
140
    bucket_arr.Reserve(num_buckets, allocator);
254
255
140
    std::stringstream ss1;
256
140
    std::stringstream ss2;
257
258
140
    rapidjson::Value lower_val;
259
140
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
140
    MutableColumnPtr lower_column = data_type->create_column();
263
140
    MutableColumnPtr upper_column = data_type->create_column();
264
250
    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
250
        if constexpr (!std::is_same_v<T, std::string>) {
268
250
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
250
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
250
        }
271
250
    }
272
140
    size_t row_num = 0;
273
274
140
    auto format_options = DataTypeSerDe::get_default_format_options();
275
140
    auto time_zone = cctz::utc_time_zone();
276
140
    format_options.timezone = &time_zone;
277
278
250
    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
250
        } else {
285
250
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
250
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
250
            ++row_num;
288
250
            lower_val.SetString(lower_str.data(),
289
250
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
250
            upper_val.SetString(upper_str.data(),
291
250
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
250
        }
293
250
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
250
        bucket_json.AddMember("lower", lower_val, allocator);
295
250
        bucket_json.AddMember("upper", upper_val, allocator);
296
250
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
250
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
250
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
250
        bucket_arr.PushBack(bucket_json, allocator);
301
250
    }
302
303
140
    doc.AddMember("buckets", bucket_arr, allocator);
304
140
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
140
    doc.Accept(writer);
306
307
140
    return !buckets.empty() && buffer.GetSize() > 0;
308
140
}
_ZN5doris17histogram_to_jsonIlEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
69
                       const DataTypePtr& data_type) {
245
69
    rapidjson::Document doc;
246
69
    doc.SetObject();
247
69
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
69
    int num_buckets = cast_set<int>(buckets.size());
250
69
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
69
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
69
    bucket_arr.Reserve(num_buckets, allocator);
254
255
69
    std::stringstream ss1;
256
69
    std::stringstream ss2;
257
258
69
    rapidjson::Value lower_val;
259
69
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
69
    MutableColumnPtr lower_column = data_type->create_column();
263
69
    MutableColumnPtr upper_column = data_type->create_column();
264
222
    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
222
        if constexpr (!std::is_same_v<T, std::string>) {
268
222
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
222
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
222
        }
271
222
    }
272
69
    size_t row_num = 0;
273
274
69
    auto format_options = DataTypeSerDe::get_default_format_options();
275
69
    auto time_zone = cctz::utc_time_zone();
276
69
    format_options.timezone = &time_zone;
277
278
222
    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
222
        } else {
285
222
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
222
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
222
            ++row_num;
288
222
            lower_val.SetString(lower_str.data(),
289
222
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
222
            upper_val.SetString(upper_str.data(),
291
222
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
222
        }
293
222
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
222
        bucket_json.AddMember("lower", lower_val, allocator);
295
222
        bucket_json.AddMember("upper", upper_val, allocator);
296
222
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
222
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
222
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
222
        bucket_arr.PushBack(bucket_json, allocator);
301
222
    }
302
303
69
    doc.AddMember("buckets", bucket_arr, allocator);
304
69
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
69
    doc.Accept(writer);
306
307
69
    return !buckets.empty() && buffer.GetSize() > 0;
308
69
}
_ZN5doris17histogram_to_jsonInEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
52
                       const DataTypePtr& data_type) {
245
52
    rapidjson::Document doc;
246
52
    doc.SetObject();
247
52
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
52
    int num_buckets = cast_set<int>(buckets.size());
250
52
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
52
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
52
    bucket_arr.Reserve(num_buckets, allocator);
254
255
52
    std::stringstream ss1;
256
52
    std::stringstream ss2;
257
258
52
    rapidjson::Value lower_val;
259
52
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
52
    MutableColumnPtr lower_column = data_type->create_column();
263
52
    MutableColumnPtr upper_column = data_type->create_column();
264
151
    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
151
        if constexpr (!std::is_same_v<T, std::string>) {
268
151
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
151
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
151
        }
271
151
    }
272
52
    size_t row_num = 0;
273
274
52
    auto format_options = DataTypeSerDe::get_default_format_options();
275
52
    auto time_zone = cctz::utc_time_zone();
276
52
    format_options.timezone = &time_zone;
277
278
151
    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
151
        } else {
285
151
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
151
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
151
            ++row_num;
288
151
            lower_val.SetString(lower_str.data(),
289
151
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
151
            upper_val.SetString(upper_str.data(),
291
151
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
151
        }
293
151
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
151
        bucket_json.AddMember("lower", lower_val, allocator);
295
151
        bucket_json.AddMember("upper", upper_val, allocator);
296
151
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
151
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
151
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
151
        bucket_arr.PushBack(bucket_json, allocator);
301
151
    }
302
303
52
    doc.AddMember("buckets", bucket_arr, allocator);
304
52
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
52
    doc.Accept(writer);
306
307
52
    return !buckets.empty() && buffer.GetSize() > 0;
308
52
}
_ZN5doris17histogram_to_jsonIfEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
50
                       const DataTypePtr& data_type) {
245
50
    rapidjson::Document doc;
246
50
    doc.SetObject();
247
50
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
50
    int num_buckets = cast_set<int>(buckets.size());
250
50
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
50
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
50
    bucket_arr.Reserve(num_buckets, allocator);
254
255
50
    std::stringstream ss1;
256
50
    std::stringstream ss2;
257
258
50
    rapidjson::Value lower_val;
259
50
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
50
    MutableColumnPtr lower_column = data_type->create_column();
263
50
    MutableColumnPtr upper_column = data_type->create_column();
264
138
    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
138
        if constexpr (!std::is_same_v<T, std::string>) {
268
138
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
138
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
138
        }
271
138
    }
272
50
    size_t row_num = 0;
273
274
50
    auto format_options = DataTypeSerDe::get_default_format_options();
275
50
    auto time_zone = cctz::utc_time_zone();
276
50
    format_options.timezone = &time_zone;
277
278
138
    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
138
        } else {
285
138
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
138
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
138
            ++row_num;
288
138
            lower_val.SetString(lower_str.data(),
289
138
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
138
            upper_val.SetString(upper_str.data(),
291
138
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
138
        }
293
138
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
138
        bucket_json.AddMember("lower", lower_val, allocator);
295
138
        bucket_json.AddMember("upper", upper_val, allocator);
296
138
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
138
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
138
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
138
        bucket_arr.PushBack(bucket_json, allocator);
301
138
    }
302
303
50
    doc.AddMember("buckets", bucket_arr, allocator);
304
50
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
50
    doc.Accept(writer);
306
307
50
    return !buckets.empty() && buffer.GetSize() > 0;
308
50
}
_ZN5doris17histogram_to_jsonIdEEbRN9rapidjson19GenericStringBufferINS1_4UTF8IcEENS1_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISB_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
50
                       const DataTypePtr& data_type) {
245
50
    rapidjson::Document doc;
246
50
    doc.SetObject();
247
50
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
50
    int num_buckets = cast_set<int>(buckets.size());
250
50
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
50
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
50
    bucket_arr.Reserve(num_buckets, allocator);
254
255
50
    std::stringstream ss1;
256
50
    std::stringstream ss2;
257
258
50
    rapidjson::Value lower_val;
259
50
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
50
    MutableColumnPtr lower_column = data_type->create_column();
263
50
    MutableColumnPtr upper_column = data_type->create_column();
264
138
    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
138
        if constexpr (!std::is_same_v<T, std::string>) {
268
138
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
138
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
138
        }
271
138
    }
272
50
    size_t row_num = 0;
273
274
50
    auto format_options = DataTypeSerDe::get_default_format_options();
275
50
    auto time_zone = cctz::utc_time_zone();
276
50
    format_options.timezone = &time_zone;
277
278
138
    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
138
        } else {
285
138
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
138
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
138
            ++row_num;
288
138
            lower_val.SetString(lower_str.data(),
289
138
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
138
            upper_val.SetString(upper_str.data(),
291
138
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
138
        }
293
138
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
138
        bucket_json.AddMember("lower", lower_val, allocator);
295
138
        bucket_json.AddMember("upper", upper_val, allocator);
296
138
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
138
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
138
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
138
        bucket_arr.PushBack(bucket_json, allocator);
301
138
    }
302
303
50
    doc.AddMember("buckets", bucket_arr, allocator);
304
50
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
50
    doc.Accept(writer);
306
307
50
    return !buckets.empty() && buffer.GetSize() > 0;
308
50
}
_ZN5doris17histogram_to_jsonINS_7DecimalIiEEEEbRN9rapidjson19GenericStringBufferINS3_4UTF8IcEENS3_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISD_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
49
                       const DataTypePtr& data_type) {
245
49
    rapidjson::Document doc;
246
49
    doc.SetObject();
247
49
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
49
    int num_buckets = cast_set<int>(buckets.size());
250
49
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
49
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
49
    bucket_arr.Reserve(num_buckets, allocator);
254
255
49
    std::stringstream ss1;
256
49
    std::stringstream ss2;
257
258
49
    rapidjson::Value lower_val;
259
49
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
49
    MutableColumnPtr lower_column = data_type->create_column();
263
49
    MutableColumnPtr upper_column = data_type->create_column();
264
133
    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
133
        if constexpr (!std::is_same_v<T, std::string>) {
268
133
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
133
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
133
        }
271
133
    }
272
49
    size_t row_num = 0;
273
274
49
    auto format_options = DataTypeSerDe::get_default_format_options();
275
49
    auto time_zone = cctz::utc_time_zone();
276
49
    format_options.timezone = &time_zone;
277
278
133
    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
133
        } else {
285
133
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
133
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
133
            ++row_num;
288
133
            lower_val.SetString(lower_str.data(),
289
133
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
133
            upper_val.SetString(upper_str.data(),
291
133
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
133
        }
293
133
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
133
        bucket_json.AddMember("lower", lower_val, allocator);
295
133
        bucket_json.AddMember("upper", upper_val, allocator);
296
133
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
133
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
133
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
133
        bucket_arr.PushBack(bucket_json, allocator);
301
133
    }
302
303
49
    doc.AddMember("buckets", bucket_arr, allocator);
304
49
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
49
    doc.Accept(writer);
306
307
49
    return !buckets.empty() && buffer.GetSize() > 0;
308
49
}
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
109
                       const DataTypePtr& data_type) {
245
109
    rapidjson::Document doc;
246
109
    doc.SetObject();
247
109
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
109
    int num_buckets = cast_set<int>(buckets.size());
250
109
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
109
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
109
    bucket_arr.Reserve(num_buckets, allocator);
254
255
109
    std::stringstream ss1;
256
109
    std::stringstream ss2;
257
258
109
    rapidjson::Value lower_val;
259
109
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
109
    MutableColumnPtr lower_column = data_type->create_column();
263
109
    MutableColumnPtr upper_column = data_type->create_column();
264
188
    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
188
    }
272
109
    size_t row_num = 0;
273
274
109
    auto format_options = DataTypeSerDe::get_default_format_options();
275
109
    auto time_zone = cctz::utc_time_zone();
276
109
    format_options.timezone = &time_zone;
277
278
188
    for (const auto& bucket : buckets) {
279
188
        if constexpr (std::is_same_v<T, std::string>) {
280
188
            lower_val.SetString(bucket.lower.data(),
281
188
                                static_cast<rapidjson::SizeType>(bucket.lower.size()), allocator);
282
188
            upper_val.SetString(bucket.upper.data(),
283
188
                                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
188
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
188
        bucket_json.AddMember("lower", lower_val, allocator);
295
188
        bucket_json.AddMember("upper", upper_val, allocator);
296
188
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
188
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
188
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
188
        bucket_arr.PushBack(bucket_json, allocator);
301
188
    }
302
303
109
    doc.AddMember("buckets", bucket_arr, allocator);
304
109
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
109
    doc.Accept(writer);
306
307
109
    return !buckets.empty() && buffer.GetSize() > 0;
308
109
}
_ZN5doris17histogram_to_jsonINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRN9rapidjson19GenericStringBufferINS4_4UTF8IcEENS4_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISE_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
90
                       const DataTypePtr& data_type) {
245
90
    rapidjson::Document doc;
246
90
    doc.SetObject();
247
90
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
90
    int num_buckets = cast_set<int>(buckets.size());
250
90
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
90
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
90
    bucket_arr.Reserve(num_buckets, allocator);
254
255
90
    std::stringstream ss1;
256
90
    std::stringstream ss2;
257
258
90
    rapidjson::Value lower_val;
259
90
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
90
    MutableColumnPtr lower_column = data_type->create_column();
263
90
    MutableColumnPtr upper_column = data_type->create_column();
264
266
    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
266
        if constexpr (!std::is_same_v<T, std::string>) {
268
266
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
266
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
266
        }
271
266
    }
272
90
    size_t row_num = 0;
273
274
90
    auto format_options = DataTypeSerDe::get_default_format_options();
275
90
    auto time_zone = cctz::utc_time_zone();
276
90
    format_options.timezone = &time_zone;
277
278
266
    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
266
        } else {
285
266
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
266
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
266
            ++row_num;
288
266
            lower_val.SetString(lower_str.data(),
289
266
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
266
            upper_val.SetString(upper_str.data(),
291
266
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
266
        }
293
266
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
266
        bucket_json.AddMember("lower", lower_val, allocator);
295
266
        bucket_json.AddMember("upper", upper_val, allocator);
296
266
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
266
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
266
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
266
        bucket_arr.PushBack(bucket_json, allocator);
301
266
    }
302
303
90
    doc.AddMember("buckets", bucket_arr, allocator);
304
90
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
90
    doc.Accept(writer);
306
307
90
    return !buckets.empty() && buffer.GetSize() > 0;
308
90
}
_ZN5doris17histogram_to_jsonINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRN9rapidjson19GenericStringBufferINS4_4UTF8IcEENS4_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISE_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
90
                       const DataTypePtr& data_type) {
245
90
    rapidjson::Document doc;
246
90
    doc.SetObject();
247
90
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
90
    int num_buckets = cast_set<int>(buckets.size());
250
90
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
90
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
90
    bucket_arr.Reserve(num_buckets, allocator);
254
255
90
    std::stringstream ss1;
256
90
    std::stringstream ss2;
257
258
90
    rapidjson::Value lower_val;
259
90
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
90
    MutableColumnPtr lower_column = data_type->create_column();
263
90
    MutableColumnPtr upper_column = data_type->create_column();
264
265
    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
265
        if constexpr (!std::is_same_v<T, std::string>) {
268
265
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
265
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
265
        }
271
265
    }
272
90
    size_t row_num = 0;
273
274
90
    auto format_options = DataTypeSerDe::get_default_format_options();
275
90
    auto time_zone = cctz::utc_time_zone();
276
90
    format_options.timezone = &time_zone;
277
278
265
    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
265
        } else {
285
265
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
265
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
265
            ++row_num;
288
265
            lower_val.SetString(lower_str.data(),
289
265
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
265
            upper_val.SetString(upper_str.data(),
291
265
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
265
        }
293
265
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
265
        bucket_json.AddMember("lower", lower_val, allocator);
295
265
        bucket_json.AddMember("upper", upper_val, allocator);
296
265
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
265
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
265
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
265
        bucket_arr.PushBack(bucket_json, allocator);
301
265
    }
302
303
90
    doc.AddMember("buckets", bucket_arr, allocator);
304
90
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
90
    doc.Accept(writer);
306
307
90
    return !buckets.empty() && buffer.GetSize() > 0;
308
90
}
_ZN5doris17histogram_to_jsonINS_16TimeStampNsValueEEEbRN9rapidjson19GenericStringBufferINS2_4UTF8IcEENS2_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISC_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
63
                       const DataTypePtr& data_type) {
245
63
    rapidjson::Document doc;
246
63
    doc.SetObject();
247
63
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
63
    int num_buckets = cast_set<int>(buckets.size());
250
63
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
63
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
63
    bucket_arr.Reserve(num_buckets, allocator);
254
255
63
    std::stringstream ss1;
256
63
    std::stringstream ss2;
257
258
63
    rapidjson::Value lower_val;
259
63
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
63
    MutableColumnPtr lower_column = data_type->create_column();
263
63
    MutableColumnPtr upper_column = data_type->create_column();
264
142
    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
142
        if constexpr (!std::is_same_v<T, std::string>) {
268
142
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
142
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
142
        }
271
142
    }
272
63
    size_t row_num = 0;
273
274
63
    auto format_options = DataTypeSerDe::get_default_format_options();
275
63
    auto time_zone = cctz::utc_time_zone();
276
63
    format_options.timezone = &time_zone;
277
278
142
    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
142
        } else {
285
142
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
142
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
142
            ++row_num;
288
142
            lower_val.SetString(lower_str.data(),
289
142
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
142
            upper_val.SetString(upper_str.data(),
291
142
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
142
        }
293
142
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
142
        bucket_json.AddMember("lower", lower_val, allocator);
295
142
        bucket_json.AddMember("upper", upper_val, allocator);
296
142
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
142
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
142
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
142
        bucket_arr.PushBack(bucket_json, allocator);
301
142
    }
302
303
63
    doc.AddMember("buckets", bucket_arr, allocator);
304
63
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
63
    doc.Accept(writer);
306
307
63
    return !buckets.empty() && buffer.GetSize() > 0;
308
63
}
_ZN5doris17histogram_to_jsonINS_16TimestampTzValueEEEbRN9rapidjson19GenericStringBufferINS2_4UTF8IcEENS2_12CrtAllocatorEEERKSt6vectorINS_6BucketIT_EESaISC_EERKSt10shared_ptrIKNS_9IDataTypeEE
Line
Count
Source
244
1
                       const DataTypePtr& data_type) {
245
1
    rapidjson::Document doc;
246
1
    doc.SetObject();
247
1
    rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
248
249
1
    int num_buckets = cast_set<int>(buckets.size());
250
1
    doc.AddMember("num_buckets", num_buckets, allocator);
251
252
1
    rapidjson::Value bucket_arr(rapidjson::kArrayType);
253
1
    bucket_arr.Reserve(num_buckets, allocator);
254
255
1
    std::stringstream ss1;
256
1
    std::stringstream ss2;
257
258
1
    rapidjson::Value lower_val;
259
1
    rapidjson::Value upper_val;
260
261
    // Convert bucket's lower and upper to 2 columns
262
1
    MutableColumnPtr lower_column = data_type->create_column();
263
1
    MutableColumnPtr upper_column = data_type->create_column();
264
3
    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
3
        if constexpr (!std::is_same_v<T, std::string>) {
268
3
            lower_column->insert_data(reinterpret_cast<const char*>(&bucket.lower), 0);
269
3
            upper_column->insert_data(reinterpret_cast<const char*>(&bucket.upper), 0);
270
3
        }
271
3
    }
272
1
    size_t row_num = 0;
273
274
1
    auto format_options = DataTypeSerDe::get_default_format_options();
275
1
    auto time_zone = cctz::utc_time_zone();
276
1
    format_options.timezone = &time_zone;
277
278
3
    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
3
        } else {
285
3
            std::string lower_str = data_type->to_string(*lower_column, row_num, format_options);
286
3
            std::string upper_str = data_type->to_string(*upper_column, row_num, format_options);
287
3
            ++row_num;
288
3
            lower_val.SetString(lower_str.data(),
289
3
                                static_cast<rapidjson::SizeType>(lower_str.size()), allocator);
290
3
            upper_val.SetString(upper_str.data(),
291
3
                                static_cast<rapidjson::SizeType>(upper_str.size()), allocator);
292
3
        }
293
3
        rapidjson::Value bucket_json(rapidjson::kObjectType);
294
3
        bucket_json.AddMember("lower", lower_val, allocator);
295
3
        bucket_json.AddMember("upper", upper_val, allocator);
296
3
        bucket_json.AddMember("ndv", static_cast<int64_t>(bucket.ndv), allocator);
297
3
        bucket_json.AddMember("count", static_cast<int64_t>(bucket.count), allocator);
298
3
        bucket_json.AddMember("pre_sum", static_cast<int64_t>(bucket.pre_sum), allocator);
299
300
3
        bucket_arr.PushBack(bucket_json, allocator);
301
3
    }
302
303
1
    doc.AddMember("buckets", bucket_arr, allocator);
304
1
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
305
1
    doc.Accept(writer);
306
307
1
    return !buckets.empty() && buffer.GetSize() > 0;
308
1
}
309
} // namespace  doris