27 #include <relpipe/reader/typedefs.h> |
27 #include <relpipe/reader/typedefs.h> |
28 #include <relpipe/reader/TypeId.h> |
28 #include <relpipe/reader/TypeId.h> |
29 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h> |
29 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h> |
30 #include <relpipe/reader/handlers/AttributeMetadata.h> |
30 #include <relpipe/reader/handlers/AttributeMetadata.h> |
31 |
31 |
|
32 #include "Configuration.h" |
|
33 |
32 namespace relpipe { |
34 namespace relpipe { |
33 namespace out { |
35 namespace out { |
34 namespace tabular { |
36 namespace tabular { |
35 |
37 |
36 using namespace relpipe::reader; |
38 using namespace relpipe::reader; |
50 const char* ESC_VALUE = ESC_CYAN; |
52 const char* ESC_VALUE = ESC_CYAN; |
51 const char* ESC_REPLACEMENT = ESC_RED; |
53 const char* ESC_REPLACEMENT = ESC_RED; |
52 |
54 |
53 const char* INDENT = " "; // table indent from the left |
55 const char* INDENT = " "; // table indent from the left |
54 |
56 |
55 std::ostream &output; |
57 std::ostream& output; |
|
58 Configuration& configuration; |
|
59 RelationConfiguration* currentRelationConfiguration; |
|
60 |
|
61 #define getConfiguration(option) (currentRelationConfiguration ? currentRelationConfiguration->option : configuration.option) |
56 |
62 |
57 std::vector<TypeId> columnTypes; |
63 std::vector<TypeId> columnTypes; |
58 std::vector<string_t> columnTypeCodes; |
64 std::vector<string_t> columnTypeCodes; |
59 std::vector<string_t> columnNames; |
65 std::vector<string_t> columnNames; |
60 std::vector<integer_t> columnWidths; |
66 std::vector<integer_t> columnWidths; |
144 // Compute column widths and paddings: |
150 // Compute column widths and paddings: |
145 vector<integer_t> paddings(columnCount); |
151 vector<integer_t> paddings(columnCount); |
146 for (size_t i = 0; i < columnCount; i++) { |
152 for (size_t i = 0; i < columnCount; i++) { |
147 string_t typeCode = columnTypeCodes[i]; |
153 string_t typeCode = columnTypeCodes[i]; |
148 string_t columnName = columnNames[i]; |
154 string_t columnName = columnNames[i]; |
149 integer_t minWidth = columnName.size() + typeCode.size() + 3; // 3 = " ()" in "columnName (typeCode)" |
155 integer_t minWidth = columnName.size() + (getConfiguration(printTypes) ? typeCode.size() + 3 : 0); // 3 = " ()" in "columnName (typeCode)" |
150 columnWidths[i] = max(columnWidths[i], minWidth); |
156 columnWidths[i] = max(columnWidths[i], minWidth); |
151 paddings[i] = columnWidths[i] - minWidth; |
157 paddings[i] = columnWidths[i] - minWidth; |
152 } |
158 } |
153 |
159 |
154 printHorizontalLine(L"╭", L"┬", L"╮"); |
160 printHorizontalLine(L"╭", L"┬", L"╮"); |
158 for (size_t i = 0; i < columnCount; i++) { |
164 for (size_t i = 0; i < columnCount; i++) { |
159 output << " " << convertor.to_bytes(formatValue(columnNames[i], ESC_HEADER)); |
165 output << " " << convertor.to_bytes(formatValue(columnNames[i], ESC_HEADER)); |
160 for (integer_t p = 0; p < paddings[i]; p++) { |
166 for (integer_t p = 0; p < paddings[i]; p++) { |
161 output << " "; |
167 output << " "; |
162 } |
168 } |
163 output << " (" << convertor.to_bytes(columnTypeCodes[i]) << ")"; |
169 if (getConfiguration(printTypes)) output << " (" << convertor.to_bytes(columnTypeCodes[i]) << ")"; |
164 output << ESC_BORDER << " │" << ESC_RESET; |
170 output << ESC_BORDER << " │" << ESC_RESET; |
165 } |
171 } |
166 output << std::endl; |
172 output << std::endl; |
167 printHorizontalLine(L"├", L"┼", L"┤"); |
173 printHorizontalLine(L"├", L"┼", L"┤"); |
168 |
174 |
180 |
186 |
181 output << ESC_BORDER << " │" << ESC_RESET; |
187 output << ESC_BORDER << " │" << ESC_RESET; |
182 if (columnIndex == (columnCount - 1)) output << std::endl; |
188 if (columnIndex == (columnCount - 1)) output << std::endl; |
183 } |
189 } |
184 printHorizontalLine(L"╰", L"┴", L"╯"); |
190 printHorizontalLine(L"╰", L"┴", L"╯"); |
185 integer_t recordCount = values.size() / columnCount; |
191 |
186 output << ESC_YELLOW << "Record count: " << ESC_RESET << recordCount << std::endl; |
192 if (getConfiguration(printRecordCount)) { |
|
193 integer_t recordCount = values.size() / columnCount; |
|
194 output << ESC_YELLOW << "Record count: " << ESC_RESET << recordCount << std::endl; |
|
195 } |
187 |
196 |
188 values.clear(); |
197 values.clear(); |
189 } |
198 } |
190 |
199 |
191 public: |
200 public: |
192 |
201 |
193 TabularPrefetchingHandler(std::ostream& output) : output(output) { |
202 TabularPrefetchingHandler(std::ostream& output, Configuration& configuration) : output(output), configuration(configuration) { |
194 } |
203 } |
195 |
204 |
196 void startRelation(string_t name, std::vector<handlers::AttributeMetadata> attributes) override { |
205 void startRelation(string_t name, std::vector<handlers::AttributeMetadata> attributes) override { |
197 if (columnCount) printCachedData(); |
206 if (columnCount) printCachedData(); |
198 |
207 |
199 output << ESC_RED << convertor.to_bytes(name) << ":" << ESC_RESET << endl; |
208 currentRelationConfiguration = nullptr; |
|
209 for (int i = 0; i < configuration.relationConfigurations.size(); i++) { |
|
210 if (std::regex_match(name, std::wregex(configuration.relationConfigurations[i].relation))) { |
|
211 currentRelationConfiguration = &configuration.relationConfigurations[i]; |
|
212 break; // it there are multiple matches, only the first configuration is used |
|
213 } |
|
214 } |
|
215 |
|
216 if (getConfiguration(printRelationName)) output << ESC_RED << convertor.to_bytes(name) << ":" << ESC_RESET << endl; |
200 columnCount = attributes.size(); |
217 columnCount = attributes.size(); |
201 columnTypes.resize(columnCount); |
218 columnTypes.resize(columnCount); |
202 columnTypeCodes.resize(columnCount); |
219 columnTypeCodes.resize(columnCount); |
203 columnNames.resize(columnCount); |
220 columnNames.resize(columnCount); |
204 columnWidths.resize(columnCount, 0); |
221 columnWidths.resize(columnCount, 0); |