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

Commit 6a2dd3f

Browse files
authored
Merge pull request #181 from sherfert/1.1-format-long-values
Change formatting ResultTables with long values
2 parents ca1dd2a + 4cd81b5 commit 6a2dd3f

File tree

2 files changed

+163
-23
lines changed

2 files changed

+163
-23
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.v1.Record;
516
import org.neo4j.driver.v1.Value;
617
import org.neo4j.driver.v1.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: 103 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,31 @@
22

33
import org.hamcrest.CoreMatchers;
44
import org.junit.Test;
5-
import org.neo4j.driver.internal.*;
6-
import org.neo4j.driver.internal.value.*;
7-
import org.neo4j.driver.v1.*;
5+
6+
import java.util.ArrayList;
7+
import java.util.Collections;
8+
import java.util.HashMap;
9+
import java.util.LinkedHashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
import org.neo4j.driver.internal.InternalIsoDuration;
14+
import org.neo4j.driver.internal.InternalNode;
15+
import org.neo4j.driver.internal.InternalPath;
16+
import org.neo4j.driver.internal.InternalPoint2D;
17+
import org.neo4j.driver.internal.InternalPoint3D;
18+
import org.neo4j.driver.internal.InternalRecord;
19+
import org.neo4j.driver.internal.InternalRelationship;
20+
import org.neo4j.driver.internal.value.DurationValue;
21+
import org.neo4j.driver.internal.value.NodeValue;
22+
import org.neo4j.driver.internal.value.PathValue;
23+
import org.neo4j.driver.internal.value.PointValue;
24+
import org.neo4j.driver.internal.value.RelationshipValue;
25+
import org.neo4j.driver.v1.Record;
26+
import org.neo4j.driver.v1.Statement;
27+
import org.neo4j.driver.v1.StatementResult;
28+
import org.neo4j.driver.v1.Value;
29+
import org.neo4j.driver.v1.Values;
830
import org.neo4j.driver.v1.summary.ProfiledPlan;
931
import org.neo4j.driver.v1.summary.ResultSummary;
1032
import org.neo4j.driver.v1.summary.StatementType;
@@ -15,8 +37,6 @@
1537
import org.neo4j.shell.state.BoltResult;
1638
import org.neo4j.shell.state.ListBoltResult;
1739

18-
import java.util.*;
19-
2040
import static java.util.Arrays.asList;
2141
import static java.util.Collections.singletonMap;
2242
import static org.hamcrest.CoreMatchers.is;
@@ -288,7 +308,7 @@ public void basicTable() {
288308
}
289309

290310
@Test
291-
public void twoRows() {
311+
public void twoRowsWithNumbersAllSampled() {
292312
// GIVEN
293313
StatementResult result = mockResult(asList("c1", "c2"), "a", 42, "b", 43);
294314
// WHEN
@@ -299,7 +319,21 @@ public void twoRows() {
299319
}
300320

301321
@Test
302-
public void wrapContent()
322+
public void fiveRowsWithNumbersNotAllSampled() {
323+
// GIVEN
324+
StatementResult 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()
303337
{
304338
// GIVEN
305339
StatementResult result = mockResult( asList( "c1"), "a", "bb","ccc","dddd","eeeee" );
@@ -315,15 +349,74 @@ public void wrapContent()
315349
"| \"a\" |",
316350
"| \"bb\" |",
317351
"| \"ccc |",
318-
"| \" |",
352+
"\\ \" |",
319353
"| \"ddd |",
320-
"| d\" |",
354+
"\\ d\" |",
321355
"| \"eee |",
322-
"| ee\" |",
356+
"\\ ee\" |",
323357
"+------+",
324358
NEWLINE)));
325359
}
326360

361+
@Test
362+
public void wrapStringContentWithTwoColumns()
363+
{
364+
// GIVEN
365+
StatementResult 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.summary()), 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+
StatementResult result = mockResult( asList( "c1"), 345, 12, 978623, 132456798, 9223372036854775807L );
402+
// WHEN
403+
ToStringLinePrinter printer = new ToStringLinePrinter();
404+
new TableOutputFormatter(true, 2).formatAndCount(new ListBoltResult(result.list(), result.summary()), printer);
405+
String table = printer.result();
406+
// THEN
407+
assertThat(table, is(String.join(NEWLINE,
408+
"+---------------------+",
409+
"| c1 |",
410+
"+---------------------+",
411+
"| 345 |",
412+
"| 12 |",
413+
"| 978623 |",
414+
"| 132456798 |",
415+
"| 9223372036854775807 |",
416+
"+---------------------+",
417+
NEWLINE)));
418+
}
419+
327420
@Test
328421
public void truncateContent()
329422
{

0 commit comments

Comments
 (0)