Skip to content
This repository was archived by the owner on Jul 6, 2023. It is now read-only.

Commit c956452

Browse files
authored
Merge pull request #183 from sherfert/4.0-format-long-values
Change formatting ResultTables with long values
2 parents 1c893a8 + e041578 commit c956452

File tree

2 files changed

+139
-18
lines changed

2 files changed

+139
-18
lines changed

cypher-shell/src/main/java/org/neo4j/shell/prettyprint/TableOutputFormatter.java

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package org.neo4j.shell.prettyprint;
22

3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.EnumSet;
6+
import java.util.Iterator;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Set;
10+
import javax.annotation.Nonnull;
11+
import javax.annotation.Nullable;
12+
313
import org.neo4j.driver.internal.InternalRecord;
14+
import org.neo4j.driver.internal.value.NumberValueAdapter;
415
import org.neo4j.driver.Record;
516
import org.neo4j.driver.Value;
617
import org.neo4j.driver.summary.ResultSummary;
718
import org.neo4j.shell.state.BoltResult;
819

9-
import javax.annotation.Nonnull;
10-
import javax.annotation.Nullable;
11-
import java.util.*;
12-
1320
import static java.util.Arrays.asList;
1421
import static java.util.concurrent.TimeUnit.MILLISECONDS;
1522

@@ -47,15 +54,15 @@ private int formatResultAndCountRows(String[] columns,
4754
LinePrinter output) {
4855

4956
List<Record> topRecords = take(records, numSampleRows);
50-
int[] columnSizes = calculateColumnSizes(columns, topRecords);
57+
int[] columnSizes = calculateColumnSizes(columns, topRecords, records.hasNext());
5158

5259
int totalWidth = 1;
5360
for (int columnSize : columnSizes) {
5461
totalWidth += columnSize + 3;
5562
}
5663

5764
StringBuilder builder = new StringBuilder(totalWidth);
58-
String headerLine = formatRow(builder, columnSizes, columns);
65+
String headerLine = formatRow(builder, columnSizes, columns, new boolean[columnSizes.length]);
5966
int lineWidth = totalWidth - 2;
6067
String dashes = "+" + OutputFormatter.repeat('-', lineWidth) + "+";
6168

@@ -76,14 +83,21 @@ private int formatResultAndCountRows(String[] columns,
7683
return numberOfRows;
7784
}
7885

79-
private int[] calculateColumnSizes(@Nonnull String[] columns, @Nonnull List<Record> data) {
86+
/**
87+
* Calculate the size of the columns for table formatting
88+
* @param columns the column names
89+
* @param data (sample) data
90+
* @param moreDataAfterSamples if there is more data that should be written into the table after `data`
91+
* @return the column sizes
92+
*/
93+
private int[] calculateColumnSizes(@Nonnull String[] columns, @Nonnull List<Record> data, boolean moreDataAfterSamples) {
8094
int[] columnSizes = new int[columns.length];
8195
for (int i = 0; i < columns.length; i++) {
8296
columnSizes[i] = columns[i].length();
8397
}
8498
for (Record record : data) {
8599
for (int i = 0; i < columns.length; i++) {
86-
int len = formatValue(record.get(i)).length();
100+
int len = columnLengthForValue(record.get(i), moreDataAfterSamples);
87101
if (columnSizes[i] < len) {
88102
columnSizes[i] = len;
89103
}
@@ -92,9 +106,24 @@ private int[] calculateColumnSizes(@Nonnull String[] columns, @Nonnull List<Reco
92106
return columnSizes;
93107
}
94108

109+
/**
110+
* The length of a column, where Numbers are always getting enough space to fit the highest number possible.
111+
*
112+
* @param value the value to calculate the length for
113+
* @param moreDataAfterSamples if there is more data that should be written into the table after `data`
114+
* @return the column size for this value.
115+
*/
116+
private int columnLengthForValue(Value value, boolean moreDataAfterSamples) {
117+
if (value instanceof NumberValueAdapter && moreDataAfterSamples) {
118+
return 19; // The number of digits of Long.Max
119+
} else {
120+
return formatValue(value).length();
121+
}
122+
}
123+
95124
private String formatRecord(StringBuilder sb, int[] columnSizes, Record record) {
96125
sb.setLength(0);
97-
return formatRow(sb, columnSizes, formatValues(record));
126+
return formatRow(sb, columnSizes, formatValues(record), new boolean[columnSizes.length]);
98127
}
99128

100129
private String[] formatValues(Record record) {
@@ -105,8 +134,21 @@ private String[] formatValues(Record record) {
105134
return row;
106135
}
107136

108-
private String formatRow(StringBuilder sb, int[] columnSizes, String[] row) {
109-
sb.append("|");
137+
/**
138+
* Format one row of data.
139+
*
140+
* @param sb the StringBuilder to use
141+
* @param columnSizes the size of all columns
142+
* @param row the data
143+
* @param continuation for each column whether it holds the remainder of data that did not fit in the column
144+
* @return the String result
145+
*/
146+
private String formatRow(StringBuilder sb, int[] columnSizes, String[] row, boolean[] continuation) {
147+
if (!continuation[0]) {
148+
sb.append("|");
149+
} else {
150+
sb.append("\\");
151+
}
110152
boolean remainder = false;
111153
for (int i = 0; i < row.length; i++) {
112154
sb.append(" ");
@@ -117,6 +159,7 @@ private String formatRow(StringBuilder sb, int[] columnSizes, String[] row) {
117159
if (wrap) {
118160
sb.append(txt, 0, length);
119161
row[i] = txt.substring(length);
162+
continuation[i] = true;
120163
remainder = true;
121164
} else {
122165
sb.append(txt, 0, length - 1);
@@ -129,11 +172,15 @@ private String formatRow(StringBuilder sb, int[] columnSizes, String[] row) {
129172
} else {
130173
sb.append(OutputFormatter.repeat(' ', length));
131174
}
132-
sb.append(" |");
175+
if (i == row.length -1 || !continuation[i+1]) {
176+
sb.append(" |");
177+
} else {
178+
sb.append(" \\");
179+
}
133180
}
134181
if (wrap && remainder) {
135182
sb.append(OutputFormatter.NEWLINE);
136-
formatRow(sb, columnSizes, row);
183+
formatRow(sb, columnSizes, row, continuation);
137184
}
138185
return sb.toString();
139186
}

cypher-shell/src/test/java/org/neo4j/shell/prettyprint/TableOutputFormatterTest.java

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ public void basicTable() {
308308
}
309309

310310
@Test
311-
public void twoRows() {
311+
public void twoRowsWithNumbersAllSampled() {
312312
// GIVEN
313313
Result result = mockResult(asList("c1", "c2"), "a", 42, "b", 43);
314314
// WHEN
@@ -319,7 +319,21 @@ public void twoRows() {
319319
}
320320

321321
@Test
322-
public void wrapContent()
322+
public void fiveRowsWithNumbersNotAllSampled() {
323+
// GIVEN
324+
Result result = mockResult(asList("c1", "c2"), "a", 42, "b", 43, "c", 44, "d", 45, "e", 46);
325+
// WHEN
326+
String table = formatResult(result);
327+
// THEN
328+
assertThat(table, containsString("| \"a\" | 42 |"));
329+
assertThat(table, containsString("| \"b\" | 43 |"));
330+
assertThat(table, containsString("| \"c\" | 44 |"));
331+
assertThat(table, containsString("| \"d\" | 45 |"));
332+
assertThat(table, containsString("| \"e\" | 46 |"));
333+
}
334+
335+
@Test
336+
public void wrapStringContent()
323337
{
324338
// GIVEN
325339
Result result = mockResult( asList( "c1"), "a", "bb","ccc","dddd","eeeee" );
@@ -335,15 +349,75 @@ public void wrapContent()
335349
"| \"a\" |",
336350
"| \"bb\" |",
337351
"| \"ccc |",
338-
"| \" |",
352+
"\\ \" |",
339353
"| \"ddd |",
340-
"| d\" |",
354+
"\\ d\" |",
341355
"| \"eee |",
342-
"| ee\" |",
356+
"\\ ee\" |",
343357
"+------+",
344358
NEWLINE)));
345359
}
346360

361+
@Test
362+
public void wrapStringContentWithTwoColumns()
363+
{
364+
// GIVEN
365+
Result result = mockResult( asList( "c1", "c2" ), "a", "b",
366+
"aa", "bb",
367+
"aaa", "b",
368+
"a", "bbb",
369+
"aaaa", "bb",
370+
"aa", "bbbb",
371+
"aaaaa", "bbbbb" );
372+
// WHEN
373+
ToStringLinePrinter printer = new ToStringLinePrinter();
374+
new TableOutputFormatter(true, 2).formatAndCount(new ListBoltResult(result.list(), result.consume()), printer);
375+
String table = printer.result();
376+
// THEN
377+
assertThat(table, is(String.join(NEWLINE,
378+
"+-------------+",
379+
"| c1 | c2 |",
380+
"+-------------+",
381+
"| \"a\" | \"b\" |",
382+
"| \"aa\" | \"bb\" |",
383+
"| \"aaa | \"b\" |",
384+
"\\ \" | |",
385+
"| \"a\" | \"bbb |",
386+
"| \\ \" |",
387+
"| \"aaa | \"bb\" |",
388+
"\\ a\" | |",
389+
"| \"aa\" | \"bbb |",
390+
"| \\ b\" |",
391+
"| \"aaa | \"bbb |",
392+
"\\ aa\" \\ bb\" |",
393+
"+-------------+",
394+
NEWLINE)));
395+
}
396+
397+
@Test
398+
public void wrapNumberContentWithLongSize()
399+
{
400+
// GIVEN
401+
Result result = mockResult( asList( "c1"), 345, 12, 978623, 132456798, 9223372036854775807L );
402+
result = mockResult( asList( "c1"), 345, 12, 978623, 132456798, 9223372036854775807L );
403+
// WHEN
404+
ToStringLinePrinter printer = new ToStringLinePrinter();
405+
new TableOutputFormatter(true, 2).formatAndCount(new ListBoltResult(result.list(), result.consume()), printer);
406+
String table = printer.result();
407+
// THEN
408+
assertThat(table, is(String.join(NEWLINE,
409+
"+---------------------+",
410+
"| c1 |",
411+
"+---------------------+",
412+
"| 345 |",
413+
"| 12 |",
414+
"| 978623 |",
415+
"| 132456798 |",
416+
"| 9223372036854775807 |",
417+
"+---------------------+",
418+
NEWLINE)));
419+
}
420+
347421
@Test
348422
public void truncateContent()
349423
{

0 commit comments

Comments
 (0)