48950 {
48951 auto column_count = result_types.size();
48952
48953
48954
48955 BoxRenderRow header_row;
48956 BoxRenderRow type_row;
48957 for (idx_t c = 0; c < column_count; c++) {
48958 auto column_name = ConvertRenderValue(column_names[c]);
48960 idx_t column_type_width = 0;
48961
48962 header_row.values.emplace_back(column_name, ResultRenderType::COLUMN_NAME, ValueRenderAlignment::MIDDLE,
48963 optional_idx(), column_name_width);
48965 auto column_type = RenderType(result_types[c]);
48967 type_row.values.emplace_back(column_type, ResultRenderType::COLUMN_TYPE, ValueRenderAlignment::MIDDLE,
48968 optional_idx(), column_type_width);
48969 }
48970 column_widths.push_back(MaxValue<idx_t>(column_name_width, column_type_width));
48971 }
48972 header_rows.push_back(std::move(header_row));
48974 header_rows.push_back(std::move(type_row));
48975 }
48976
48977
48978 vector<column_t> column_ids;
48979 for (idx_t c = 0; c < column_count; c++) {
48980 column_ids.push_back(c * 2 + 1);
48981 }
48982 for (auto &collection : collections) {
48983 for (auto &chunk : collection.render_values->Chunks(column_ids)) {
48984 for (idx_t c = 0; c < column_count; c++) {
48985 auto render_widths = FlatVector::GetData<uint64_t>(chunk.data[c]);
48986 for (idx_t r = 0; r < chunk.size(); r++) {
48987 if (render_widths[r] > column_widths[c]) {
48988 column_widths[c] = render_widths[r];
48989 }
48990 }
48991 }
48992 }
48993 }
48994
48995 bool shortened_columns = false;
48996
48997
48998 total_render_length = 1;
48999 for (idx_t c = 0; c < column_widths.size(); c++) {
49000
49001
49002 total_render_length += column_widths[c] + 3;
49003 }
49004 if (total_render_length < min_width) {
49005
49006
49007 column_widths[0] += min_width - total_render_length;
49008 total_render_length = min_width;
49009 }
49010
49011 if (total_render_length > max_width) {
49012 auto original_widths = column_widths;
49013
49014 vector<idx_t> max_shorten_amount;
49015 idx_t total_max_shorten_amount = 0;
49016 for (auto &w : column_widths) {
49017 if (w <= config.max_col_width) {
49018 max_shorten_amount.push_back(0);
49019 continue;
49020 }
49021 auto max_diff = w - config.max_col_width;
49022 max_shorten_amount.push_back(max_diff);
49023 total_max_shorten_amount += max_diff;
49024 }
49025 idx_t shorten_amount_required = total_render_length - max_width;
49026 if (total_max_shorten_amount >= shorten_amount_required) {
49027
49028
49029
49030
49031
49032 map<idx_t, vector<idx_t>> shorten_amount_required_map;
49033 for (idx_t col_idx = 0; col_idx < max_shorten_amount.size(); col_idx++) {
49034 shorten_amount_required_map[max_shorten_amount[col_idx]].push_back(col_idx);
49035 }
49036 vector<idx_t> actual_shorten_amounts;
49037 actual_shorten_amounts.resize(max_shorten_amount.size());
49038
49039 while (shorten_amount_required > 0) {
49040
49041 auto entry = shorten_amount_required_map.rbegin();
49042 auto largest_width = entry->first;
49043 auto &column_list = entry->second;
49044
49045
49046 entry++;
49047 auto second_largest_width = entry == shorten_amount_required_map.rend() ? 0 : entry->first;
49048 auto max_shorten_width = largest_width - second_largest_width;
49049 D_ASSERT(max_shorten_width > 0);
49050
49051 auto total_potential_shorten_width = max_shorten_width * column_list.size();
49052 if (total_potential_shorten_width >= shorten_amount_required) {
49053
49054
49055 idx_t shorten_amount_per_column = shorten_amount_required / column_list.size();
49056 for (auto &column_idx : column_list) {
49057 actual_shorten_amounts[column_idx] += shorten_amount_per_column;
49058 shorten_amount_required -= shorten_amount_per_column;
49059 }
49060
49061
49062 for (idx_t i = column_list.size(); i > 0 && shorten_amount_required > 0; i--) {
49063 actual_shorten_amounts[column_list[i - 1]]++;
49064 shorten_amount_required--;
49065 }
49066 if (shorten_amount_required != 0) {
49067 throw InternalException("Shorten amount required has tob e zero now");
49068 }
49069
49070
49071 break;
49072 }
49073 if (entry == shorten_amount_required_map.rend()) {
49074 throw InternalException(
49075 "ColumnRenderer - we could not reach the shorten amount required but we ran out of columns?");
49076 }
49077
49078 for (auto &column_idx : column_list) {
49079 actual_shorten_amounts[column_idx] += max_shorten_width;
49080 }
49081
49082 auto &second_largest_column_list = entry->second;
49083 second_largest_column_list.insert(second_largest_column_list.end(), column_list.begin(),
49084 column_list.end());
49085
49086 shorten_amount_required_map.erase(largest_width);
49087 shorten_amount_required -= total_potential_shorten_width;
49088 }
49089
49090
49091 for (idx_t c = 0; c < actual_shorten_amounts.size(); c++) {
49092 if (actual_shorten_amounts[c] == 0) {
49093 continue;
49094 }
49095 D_ASSERT(actual_shorten_amounts[c] < column_widths[c]);
49096 column_widths[c] -= actual_shorten_amounts[c];
49097 total_render_length -= actual_shorten_amounts[c];
49098 shortened_columns = true;
49099 }
49100 } else {
49101
49102
49103
49104 for (auto &w : column_widths) {
49105 if (w <= config.max_col_width) {
49106 continue;
49107 }
49108 total_render_length -= w - config.max_col_width;
49109 w = config.max_col_width;
49110 shortened_columns = true;
49111 }
49112 D_ASSERT(total_render_length > max_width);
49113 }
49114
49115 if (total_render_length > max_width) {
49116
49117
49118
49119
49120 total_render_length += 3 + config.DOTDOTDOT_LENGTH;
49121
49122
49123
49125 while (total_render_length > max_width) {
49126 auto c = NumericCast<idx_t>(NumericCast<int64_t>(column_count) / 2 + offset);
49127 total_render_length -= column_widths[c] + 3;
49128 pruned_columns.insert(c);
49129 if (offset >= 0) {
49130 offset = -offset - 1;
49131 } else {
49132 offset = -offset;
49133 }
49134 }
49135
49136
49137 idx_t space_left = max_width - total_render_length;
49138 for (idx_t c = 0; c < column_widths.size() && space_left > 0; c++) {
49139 if (pruned_columns.find(c) != pruned_columns.end()) {
49140
49141 continue;
49142 }
49143 if (column_widths[c] >= original_widths[c]) {
49144 continue;
49145 }
49146 idx_t increase_amount = MinValue<idx_t>(space_left, original_widths[c] - column_widths[c]);
49147 column_widths[c] += increase_amount;
49148 space_left -= increase_amount;
49149 total_render_length += increase_amount;
49150 }
49151 }
49152 }
49153
49154
49155 UpdateColumnCountFooter(column_count, pruned_columns);
49156
49157 bool added_split_column = false;
49158 vector<idx_t> new_widths;
49159 for (idx_t c = 0; c < column_count; c++) {
49160 if (pruned_columns.find(c) == pruned_columns.end()) {
49161 column_map.push_back(c);
49162 new_widths.push_back(column_widths[c]);
49163 } else if (!added_split_column) {
49164
49165 column_map.push_back(optional_idx());
49166 new_widths.push_back(config.DOTDOTDOT_LENGTH);
49167 added_split_column = true;
49168 }
49169 }
49170 column_widths = std::move(new_widths);
49171 column_count = column_widths.size();
49172
49173
49174 for (auto &header_row : header_rows) {
49175 vector<BoxRenderValue> new_rows;
49176 for (auto &c : column_map) {
49177 if (!c.IsValid()) {
49178
49179 continue;
49180 }
49181 new_rows.push_back(std::move(header_row.values[c.GetIndex()]));
49182 }
49183 header_row.values = std::move(new_rows);
49184 }
49185
49186 idx_t row_count = 0;
49187 for (auto &collection : collections) {
49188 row_count += collection.render_values->Count();
49189 }
49190
49191
49192
49193 if (shortened_columns && config.
render_mode == RenderMode::ROWS && row_count > 0 &&
49194 row_count + 5 < config.max_rows && pruned_columns.empty()) {
49195 max_rows_per_row = MaxValue<idx_t>(1, config.max_rows <= 5 ? 0 : (config.max_rows - 5) / row_count);
49196 if (max_rows_per_row > 1) {
49197
49198 expand_rows = true;
49199 }
49200 }
49201}