Skip to content

Commit

Permalink
Add float type and fix values not showing with useTypes is used (#698)
Browse files Browse the repository at this point in the history
  • Loading branch information
gem-neo4j authored Dec 9, 2024
1 parent 311a019 commit e55bdf4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 7 deletions.
3 changes: 2 additions & 1 deletion common/src/main/java/apoc/export/util/MetaInformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ public static String typeFor(Class value, Set<String> allowed) {
case NULL:
return null;
case INTEGER:
case FLOAT:
return "integer".equals(name) || !isAllowed ? "int" : name;
case FLOAT:
return !isAllowed ? "float" : name;
default:
return isAllowed ? name : "string"; // We manage all other data types as strings
}
Expand Down
14 changes: 8 additions & 6 deletions core/src/main/java/apoc/export/csv/CsvFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ public void writeAll(InternalTransaction threadBoundTx, SubGraph graph, Reporter
final var relPropTypes = collectPropTypesForRelationships(graph, db, config);
final var nodeHeader = generateHeader(nodePropTypes, config.useTypes(), NODE_HEADER_FIXED_COLUMNS);
final var relHeader = generateHeader(relPropTypes, config.useTypes(), REL_HEADER_FIXED_COLUMNS);
final var nodePropNames = nodePropTypes.keySet().stream().sorted().toList();
final var relPropNames = relPropTypes.keySet().stream().sorted().toList();
final var header = new ArrayList<>(nodeHeader);
header.addAll(relHeader);
out.writeNext(header.toArray(String[]::new), applyQuotesToAll);
Expand All @@ -182,7 +184,7 @@ public void writeAll(InternalTransaction threadBoundTx, SubGraph graph, Reporter
graph,
out,
reporter,
nodeHeader.subList(NODE_HEADER_FIXED_COLUMNS.length, nodeHeader.size()),
nodePropNames,
cols,
config.getBatchSize(),
config.shouldDifferentiateNulls());
Expand All @@ -191,7 +193,7 @@ public void writeAll(InternalTransaction threadBoundTx, SubGraph graph, Reporter
graph,
out,
reporter,
relHeader.subList(REL_HEADER_FIXED_COLUMNS.length, relHeader.size()),
relPropNames,
cols,
nodeHeader.size(),
config.getBatchSize(),
Expand Down Expand Up @@ -350,7 +352,7 @@ private void writeNodes(
SubGraph graph,
CSVWriter out,
Reporter reporter,
List<String> header,
List<String> nodePropTypes,
int cols,
int batchSize,
boolean keepNulls) {
Expand All @@ -359,7 +361,7 @@ private void writeNodes(
for (Node node : graph.getNodes()) {
row[0] = String.valueOf(getNodeId(threadBoundTx, node.getElementId()));
row[1] = getLabelsString(node);
collectProps(header, node, reporter, row, 2, keepNulls);
collectProps(nodePropTypes, node, reporter, row, 2, keepNulls);
out.writeNext(row, applyQuotesToAll);
nodes++;
if (batchSize == -1 || nodes % batchSize == 0) {
Expand Down Expand Up @@ -392,7 +394,7 @@ private void writeRels(
SubGraph graph,
CSVWriter out,
Reporter reporter,
List<String> relHeader,
List<String> relPropNames,
int cols,
int offset,
int batchSize,
Expand All @@ -405,7 +407,7 @@ private void writeRels(
row[offset + 1] =
String.valueOf(getNodeId(threadBoundTx, rel.getEndNode().getElementId()));
row[offset + 2] = rel.getType().name();
collectProps(relHeader, rel, reporter, row, 3 + offset, keepNull);
collectProps(relPropNames, rel, reporter, row, 3 + offset, keepNull);
out.writeNext(row, applyQuotesToAll);
rels++;
if (batchSize == -1 || rels % batchSize == 0) {
Expand Down
30 changes: 30 additions & 0 deletions core/src/test/java/apoc/export/csv/ExportCsvTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,36 @@ public void testExportInvalidQuoteValue() {
}
}

@Test
public void textExportWithTypes() {
db.executeTransactionally(
"CREATE (n:TestNode) SET n = {valFloat:toFloat(123), name:'NodeName', valInt:5, dateVal: date('2024-11-01')};");
TestUtil.testCall(
db,
"""
CALL apoc.graph.fromCypher("MATCH (n:TestNode) RETURN n", {}, 'TestNode.csv',{}) YIELD graph
CALL apoc.export.csv.graph(graph, null, {stream:true, useTypes:true}) YIELD properties, rows, data
return properties, rows, data;
""",
(r) -> {
String data = (String) r.get("data");
// FLOAT value
assertTrue(data.contains("valFloat:float"));
assertTrue(data.contains("123.0"));
// INT value
assertTrue(data.contains("valInt:int"));
assertTrue(data.contains("5"));
// STRING value and unknown types to csv export
assertTrue(data.contains("name"));
assertTrue(data.contains("NodeName"));
assertTrue(data.contains("dateVal"));
assertTrue(data.contains("2024-11-01"));
});

final String deleteQuery = "MATCH (n:TestNode) DETACH DELETE n";
db.executeTransactionally(deleteQuery);
}

@Test
public void testExportAllCsvCompressed() {
final CompressionAlgo compressionAlgo = DEFLATE;
Expand Down

0 comments on commit e55bdf4

Please sign in to comment.