Coverage Report

Created: 2026-03-31 18:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/common/agg_context_utils.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include "common/exception.h"
21
#include "core/block/block.h"
22
#include "exec/common/agg_utils.h"
23
#include "exec/common/template_helpers.hpp"
24
#include "exprs/vectorized_agg_fn.h"
25
#include "exprs/vexpr_context.h"
26
#include "exprs/vslot_ref.h"
27
28
/// Utility functions for aggregation context result output.
29
/// Eliminates duplicate column-preparation and block-assembly patterns
30
/// across GroupByAggContext, InlineCountAggContext, and UngroupByAggContext.
31
namespace doris::agg_context_utils {
32
33
/// Visit the hash table method variant, throwing on uninitialized (monostate).
34
/// For void-returning functors: visit_agg_method(data, [&](auto& m) { ... });
35
/// For non-void: visit_agg_method<RetType>(data, [&](auto& m) -> RetType { ... });
36
template <typename ReturnType = void, typename Func>
37
378
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
378
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
0
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
0
                                                           "uninited hash table");
41
0
                                },
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext23init_agg_data_containerEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESA_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNKS_17GroupByAggContext12memory_usageEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESA_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext15update_memusageEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESA_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodINS_6StatusEZNS_17GroupByAggContext16reset_hash_tableEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESB_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext23emplace_into_hash_tableEPPcRSt6vectorIPKNS_7IColumnESaIS8_EEjPNS_14RuntimeProfile7CounterESE_SE_E3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESM_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext18find_in_hash_tableEPPcRSt6vectorIPKNS_7IColumnESaIS8_EEjE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESJ_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIbZNS_17GroupByAggContext29emplace_into_hash_table_limitEPPcPNS_5BlockEPKSt6vectorIiSaIiEERS7_IPKNS_7IColumnESaISE_EEjE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESP_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIbZNS_17GroupByAggContext31should_expand_preagg_hash_tableEllbE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESA_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIbZNS_17GroupByAggContext18should_skip_preaggEmmllbE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESA_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext9serializeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESF_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_2EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESF_
Unexecuted instantiation: groupby_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodISt6vectorINS_3COWINS_7IColumnEE11mutable_ptrIS4_EESaIS7_EEZNS_17GroupByAggContext20_get_keys_hash_tableEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESI_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext23emplace_into_hash_tableEPPcRSt6vectorIPKNS_7IColumnESaIS8_EEjPNS_14RuntimeProfile7CounterESE_SE_E3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESM_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext19_merge_inline_countERSt6vectorIPKNS_7IColumnESaIS6_EES6_jE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESH_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext9serializeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESF_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESF_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZZN5doris17agg_context_utils16visit_agg_methodINS_6StatusEZNS_21InlineCountAggContext16reset_hash_tableEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_ENKUlRSt9monostateE_clESB_
42
378
                                std::forward<Func>(func)},
43
378
                      data.method_variant);
44
378
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext23init_agg_data_containerEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
51
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
51
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
51
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
51
                                                           "uninited hash table");
41
51
                                },
42
51
                                std::forward<Func>(func)},
43
51
                      data.method_variant);
44
51
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNKS_17GroupByAggContext12memory_usageEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
34
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
34
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
34
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
34
                                                           "uninited hash table");
41
34
                                },
42
34
                                std::forward<Func>(func)},
43
34
                      data.method_variant);
44
34
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext15update_memusageEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
69
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
69
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
69
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
69
                                                           "uninited hash table");
41
69
                                },
42
69
                                std::forward<Func>(func)},
43
69
                      data.method_variant);
44
69
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodINS_6StatusEZNS_17GroupByAggContext16reset_hash_tableEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
55
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
55
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
55
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
55
                                                           "uninited hash table");
41
55
                                },
42
55
                                std::forward<Func>(func)},
43
55
                      data.method_variant);
44
55
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext23emplace_into_hash_tableEPPcRSt6vectorIPKNS_7IColumnESaIS8_EEjPNS_14RuntimeProfile7CounterESE_SE_E3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
83
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
83
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
83
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
83
                                                           "uninited hash table");
41
83
                                },
42
83
                                std::forward<Func>(func)},
43
83
                      data.method_variant);
44
83
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext18find_in_hash_tableEPPcRSt6vectorIPKNS_7IColumnESaIS8_EEjE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
5
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
5
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
5
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
5
                                                           "uninited hash table");
41
5
                                },
42
5
                                std::forward<Func>(func)},
43
5
                      data.method_variant);
44
5
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIbZNS_17GroupByAggContext29emplace_into_hash_table_limitEPPcPNS_5BlockEPKSt6vectorIiSaIiEERS7_IPKNS_7IColumnESaISE_EEjE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
4
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
4
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
4
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
4
                                                           "uninited hash table");
41
4
                                },
42
4
                                std::forward<Func>(func)},
43
4
                      data.method_variant);
44
4
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIbZNS_17GroupByAggContext31should_expand_preagg_hash_tableEllbE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
6
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
6
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
6
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
6
                                                           "uninited hash table");
41
6
                                },
42
6
                                std::forward<Func>(func)},
43
6
                      data.method_variant);
44
6
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIbZNS_17GroupByAggContext18should_skip_preaggEmmllbE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
8
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
8
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
8
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
8
                                                           "uninited hash table");
41
8
                                },
42
8
                                std::forward<Func>(func)},
43
8
                      data.method_variant);
44
8
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext9serializeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
44
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
44
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
44
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
44
                                                           "uninited hash table");
41
44
                                },
42
44
                                std::forward<Func>(func)},
43
44
                      data.method_variant);
44
44
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_17GroupByAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_2EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
15
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
15
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
15
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
15
                                                           "uninited hash table");
41
15
                                },
42
15
                                std::forward<Func>(func)},
43
15
                      data.method_variant);
44
15
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodISt6vectorINS_3COWINS_7IColumnEE11mutable_ptrIS4_EESaIS7_EEZNS_17GroupByAggContext20_get_keys_hash_tableEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Line
Count
Source
37
4
ReturnType visit_agg_method(AggregatedDataVariants& data, Func&& func) {
38
4
    return std::visit(Overload {[](std::monostate&) -> ReturnType {
39
4
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
40
4
                                                           "uninited hash table");
41
4
                                },
42
4
                                std::forward<Func>(func)},
43
4
                      data.method_variant);
44
4
}
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext23emplace_into_hash_tableEPPcRSt6vectorIPKNS_7IColumnESaIS8_EEjPNS_14RuntimeProfile7CounterESE_SE_E3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext19_merge_inline_countERSt6vectorIPKNS_7IColumnESaIS6_EES6_jE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext9serializeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EET_RNS_22AggregatedDataVariantsEOT0_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodIvZNS_21InlineCountAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EET_RNS_22AggregatedDataVariantsEOT0_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils16visit_agg_methodINS_6StatusEZNS_21InlineCountAggContext16reset_hash_tableEvE3$_0EET_RNS_22AggregatedDataVariantsEOT0_
45
46
template <typename ReturnType = void, typename Func>
47
ReturnType visit_agg_method(const AggregatedDataVariants& data, Func&& func) {
48
    return std::visit(Overload {[](const std::monostate&) -> ReturnType {
49
                                    throw doris::Exception(ErrorCode::INTERNAL_ERROR,
50
                                                           "uninited hash table");
51
                                },
52
                                std::forward<Func>(func)},
53
                      data.method_variant);
54
}
55
56
/// Null-safe COUNTER_SET: only calls set() when counter is non-null.
57
690
inline void set_counter_if(RuntimeProfile::Counter* counter, int64_t val) {
58
690
    if (counter) {
59
377
        COUNTER_SET(counter, val);
60
377
    }
61
690
}
62
63
/// Take existing columns from block [start, start+count) if mem_reuse,
64
/// otherwise create new columns via create_fn(index).
65
///
66
/// @param block       the output block
67
/// @param mem_reuse   whether the block supports memory reuse
68
/// @param start       starting column position in the block
69
/// @param count       number of columns to take or create
70
/// @param create_fn   callable(size_t i) -> MutableColumnPtr for non-reuse path
71
/// @return MutableColumns with count elements
72
template <typename CreateFn>
73
MutableColumns take_or_create_columns(Block* block, bool mem_reuse, size_t start, size_t count,
74
76
                                      CreateFn&& create_fn) {
75
76
    MutableColumns columns;
76
76
    columns.reserve(count);
77
152
    for (size_t i = 0; i < count; ++i) {
78
76
        if (mem_reuse) {
79
22
            columns.emplace_back(std::move(*block->get_by_position(start + i).column).mutate());
80
54
        } else {
81
54
            columns.emplace_back(create_fn(i));
82
54
        }
83
76
    }
84
76
    return columns;
85
76
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils22take_or_create_columnsIZNS_17GroupByAggContext31streaming_serialize_passthroughEPNS_5BlockES4_RSt6vectorIPKNS_7IColumnESaIS8_EEjbE3$_0EES5_INS_3COWIS6_E11mutable_ptrIS6_EESaISG_EES4_bmmOT_
Line
Count
Source
74
2
                                      CreateFn&& create_fn) {
75
2
    MutableColumns columns;
76
2
    columns.reserve(count);
77
4
    for (size_t i = 0; i < count; ++i) {
78
2
        if (mem_reuse) {
79
0
            columns.emplace_back(std::move(*block->get_by_position(start + i).column).mutate());
80
2
        } else {
81
2
            columns.emplace_back(create_fn(i));
82
2
        }
83
2
    }
84
2
    return columns;
85
2
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils22take_or_create_columnsIZNS_17GroupByAggContext9serializeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_0EESt6vectorINS_3COWINS_7IColumnEE11mutable_ptrISB_EESaISE_EES6_bmmOT_
Line
Count
Source
74
44
                                      CreateFn&& create_fn) {
75
44
    MutableColumns columns;
76
44
    columns.reserve(count);
77
88
    for (size_t i = 0; i < count; ++i) {
78
44
        if (mem_reuse) {
79
22
            columns.emplace_back(std::move(*block->get_by_position(start + i).column).mutate());
80
22
        } else {
81
22
            columns.emplace_back(create_fn(i));
82
22
        }
83
44
    }
84
44
    return columns;
85
44
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils22take_or_create_columnsIZNS_17GroupByAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_0EESt6vectorINS_3COWINS_7IColumnEE11mutable_ptrISB_EESaISE_EES6_bmmOT_
Line
Count
Source
74
15
                                      CreateFn&& create_fn) {
75
15
    MutableColumns columns;
76
15
    columns.reserve(count);
77
30
    for (size_t i = 0; i < count; ++i) {
78
15
        if (mem_reuse) {
79
0
            columns.emplace_back(std::move(*block->get_by_position(start + i).column).mutate());
80
15
        } else {
81
15
            columns.emplace_back(create_fn(i));
82
15
        }
83
15
    }
84
15
    return columns;
85
15
}
groupby_agg_context.cpp:_ZN5doris17agg_context_utils22take_or_create_columnsIZNS_17GroupByAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_1EESt6vectorINS_3COWINS_7IColumnEE11mutable_ptrISB_EESaISE_EES6_bmmOT_
Line
Count
Source
74
15
                                      CreateFn&& create_fn) {
75
15
    MutableColumns columns;
76
15
    columns.reserve(count);
77
30
    for (size_t i = 0; i < count; ++i) {
78
15
        if (mem_reuse) {
79
0
            columns.emplace_back(std::move(*block->get_by_position(start + i).column).mutate());
80
15
        } else {
81
15
            columns.emplace_back(create_fn(i));
82
15
        }
83
15
    }
84
15
    return columns;
85
15
}
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils22take_or_create_columnsIZNS_21InlineCountAggContext9serializeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_0EESt6vectorINS_3COWINS_7IColumnEE11mutable_ptrISB_EESaISE_EES6_bmmOT_
Unexecuted instantiation: inline_count_agg_context.cpp:_ZN5doris17agg_context_utils22take_or_create_columnsIZNS_21InlineCountAggContext8finalizeEPNS_12RuntimeStateEPNS_5BlockEPbE3$_0EESt6vectorINS_3COWINS_7IColumnEE11mutable_ptrISB_EESaISE_EES6_bmmOT_
86
87
/// Assemble a finalized output block from schema + key/value columns (non mem_reuse path).
88
///
89
/// @param block                the output block to overwrite
90
/// @param columns_with_schema  the target schema
91
/// @param key_columns          key columns to place at [0, key_size)
92
/// @param value_columns        value columns to place at [key_size, ...)
93
/// @param key_size             number of key columns
94
inline void assemble_finalized_output(Block* block,
95
                                      const ColumnsWithTypeAndName& columns_with_schema,
96
                                      MutableColumns& key_columns, MutableColumns& value_columns,
97
15
                                      size_t key_size) {
98
15
    *block = columns_with_schema;
99
15
    MutableColumns columns(block->columns());
100
45
    for (size_t i = 0; i < columns.size(); ++i) {
101
30
        if (i < key_size) {
102
15
            columns[i] = std::move(key_columns[i]);
103
15
        } else {
104
15
            columns[i] = std::move(value_columns[i - key_size]);
105
15
        }
106
30
    }
107
15
    block->set_columns(std::move(columns));
108
15
}
109
110
/// Build a serialized output block from key expr types + value data types (non mem_reuse path).
111
///
112
/// @param block          the output block to overwrite
113
/// @param key_columns    key columns (moved into the new block)
114
/// @param key_exprs      groupby expression contexts (for type and name)
115
/// @param value_columns  value columns (moved into the new block)
116
/// @param value_types    data types for value columns
117
inline void build_serialized_output_block(Block* block, MutableColumns& key_columns,
118
                                          const VExprContextSPtrs& key_exprs,
119
                                          MutableColumns& value_columns,
120
22
                                          const DataTypes& value_types) {
121
22
    ColumnsWithTypeAndName schema;
122
22
    schema.reserve(key_columns.size() + value_columns.size());
123
44
    for (size_t i = 0; i < key_columns.size(); ++i) {
124
22
        schema.emplace_back(std::move(key_columns[i]), key_exprs[i]->root()->data_type(),
125
22
                            key_exprs[i]->root()->expr_name());
126
22
    }
127
44
    for (size_t i = 0; i < value_columns.size(); ++i) {
128
22
        schema.emplace_back(std::move(value_columns[i]), value_types[i], "");
129
22
    }
130
22
    *block = Block(schema);
131
22
}
132
133
/// Overload for streaming agg passthrough: keys come from ColumnRawPtrs (clone + resize).
134
///
135
/// @param block          the output block to overwrite (via swap)
136
/// @param key_columns    raw key column pointers (will be clone_resized)
137
/// @param rows           number of rows to clone
138
/// @param key_exprs      groupby expression contexts (for type and name)
139
/// @param value_columns  value columns (moved into the new block)
140
/// @param value_types    data types for value columns
141
inline void build_serialized_output_block(Block* block, ColumnRawPtrs& key_columns, uint32_t rows,
142
                                          const VExprContextSPtrs& key_exprs,
143
                                          MutableColumns& value_columns,
144
2
                                          const DataTypes& value_types) {
145
2
    ColumnsWithTypeAndName schema;
146
2
    schema.reserve(key_columns.size() + value_columns.size());
147
4
    for (size_t i = 0; i < key_columns.size(); ++i) {
148
2
        schema.emplace_back(key_columns[i]->clone_resized(rows), key_exprs[i]->root()->data_type(),
149
2
                            key_exprs[i]->root()->expr_name());
150
2
    }
151
4
    for (size_t i = 0; i < value_columns.size(); ++i) {
152
2
        schema.emplace_back(std::move(value_columns[i]), value_types[i], "");
153
2
    }
154
2
    block->swap(Block(schema));
155
2
}
156
157
/// Get the input column id from an evaluator's single SlotRef input expression.
158
/// Unified version used by both GroupByAggContext and UngroupByAggContext.
159
8
inline int get_slot_column_id(const AggFnEvaluator* evaluator) {
160
8
    auto ctxs = evaluator->input_exprs_ctxs();
161
8
    DCHECK(ctxs.size() == 1 && ctxs[0]->root()->is_slot_ref())
162
0
            << "input_exprs_ctxs is invalid, input_exprs_ctx[0]="
163
0
            << ctxs[0]->root()->debug_string();
164
8
    return static_cast<VSlotRef*>(ctxs[0]->root().get())->column_id();
165
8
}
166
167
} // namespace doris::agg_context_utils