1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/common/box_renderer.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/constants.hpp"
12#include "duckdb/common/vector.hpp"
13#include "duckdb/main/query_profiler.hpp"
14#include "duckdb/common/list.hpp"
15
16namespace duckdb {
17class ColumnDataCollection;
18class ColumnDataRowCollection;
19
20enum class ValueRenderAlignment { LEFT, MIDDLE, RIGHT };
21enum class RenderMode { ROWS, COLUMNS };
22
23struct BoxRendererConfig {
24 // a max_width of 0 means we default to the terminal width
25 idx_t max_width = 0;
26 // the maximum amount of rows to render
27 idx_t max_rows = 20;
28 // the limit that is applied prior to rendering
29 // if we are rendering exactly "limit" rows then a question mark is rendered instead
30 idx_t limit = 0;
31 // the max col width determines the maximum size of a single column
32 // note that the max col width is only used if the result does not fit on the screen
33 idx_t max_col_width = 20;
34 //! how to render NULL values
35 string null_value = "NULL";
36 //! Whether or not to render row-wise or column-wise
37 RenderMode render_mode = RenderMode::ROWS;
38
39#ifndef DUCKDB_ASCII_TREE_RENDERER
40 const char *LTCORNER = "\342\224\214"; // "┌";
41 const char *RTCORNER = "\342\224\220"; // "┐";
42 const char *LDCORNER = "\342\224\224"; // "└";
43 const char *RDCORNER = "\342\224\230"; // "┘";
44
45 const char *MIDDLE = "\342\224\274"; // "┼";
46 const char *TMIDDLE = "\342\224\254"; // "┬";
47 const char *LMIDDLE = "\342\224\234"; // "├";
48 const char *RMIDDLE = "\342\224\244"; // "┤";
49 const char *DMIDDLE = "\342\224\264"; // "┴";
50
51 const char *VERTICAL = "\342\224\202"; // "│";
52 const char *HORIZONTAL = "\342\224\200"; // "─";
53
54 const char *DOTDOTDOT = "\xE2\x80\xA6"; // "…";
55 const char *DOT = "\xC2\xB7"; // "·";
56 const idx_t DOTDOTDOT_LENGTH = 1;
57
58#else
59 // ASCII version
60 const char *LTCORNER = "<";
61 const char *RTCORNER = ">";
62 const char *LDCORNER = "<";
63 const char *RDCORNER = ">";
64
65 const char *MIDDLE = "+";
66 const char *TMIDDLE = "+";
67 const char *LMIDDLE = "+";
68 const char *RMIDDLE = "+";
69 const char *DMIDDLE = "+";
70
71 const char *VERTICAL = "|";
72 const char *HORIZONTAL = "-";
73
74 const char *DOTDOTDOT = "..."; // "...";
75 const char *DOT = "."; // ".";
76 const idx_t DOTDOTDOT_LENGTH = 3;
77#endif
78};
79
80class BoxRenderer {
81 static const idx_t SPLIT_COLUMN;
82
83public:
84 explicit BoxRenderer(BoxRendererConfig config_p = BoxRendererConfig());
85
86 string ToString(ClientContext &context, const vector<string> &names, const ColumnDataCollection &op);
87
88 void Render(ClientContext &context, const vector<string> &names, const ColumnDataCollection &op, std::ostream &ss);
89 void Print(ClientContext &context, const vector<string> &names, const ColumnDataCollection &op);
90
91private:
92 //! The configuration used for rendering
93 BoxRendererConfig config;
94
95private:
96 void RenderValue(std::ostream &ss, const string &value, idx_t column_width,
97 ValueRenderAlignment alignment = ValueRenderAlignment::MIDDLE);
98 string RenderType(const LogicalType &type);
99 ValueRenderAlignment TypeAlignment(const LogicalType &type);
100 string GetRenderValue(ColumnDataRowCollection &rows, idx_t c, idx_t r);
101 list<ColumnDataCollection> FetchRenderCollections(ClientContext &context, const ColumnDataCollection &result,
102 idx_t top_rows, idx_t bottom_rows);
103 list<ColumnDataCollection> PivotCollections(ClientContext &context, list<ColumnDataCollection> input,
104 vector<string> &column_names, vector<LogicalType> &result_types,
105 idx_t row_count);
106 vector<idx_t> ComputeRenderWidths(const vector<string> &names, const vector<LogicalType> &result_types,
107 list<ColumnDataCollection> &collections, idx_t min_width, idx_t max_width,
108 vector<idx_t> &column_map, idx_t &total_length);
109 void RenderHeader(const vector<string> &names, const vector<LogicalType> &result_types,
110 const vector<idx_t> &column_map, const vector<idx_t> &widths, const vector<idx_t> &boundaries,
111 idx_t total_length, bool has_results, std::ostream &ss);
112 void RenderValues(const list<ColumnDataCollection> &collections, const vector<idx_t> &column_map,
113 const vector<idx_t> &widths, const vector<LogicalType> &result_types, std::ostream &ss);
114 void RenderRowCount(string row_count_str, string shown_str, const string &column_count_str,
115 const vector<idx_t> &boundaries, bool has_hidden_rows, bool has_hidden_columns,
116 idx_t total_length, idx_t row_count, idx_t column_count, idx_t minimum_row_length,
117 std::ostream &ss);
118};
119
120} // namespace duckdb
121