@@ -91,10 +91,10 @@ public class ExportCsvTest {
9191 + "\" Andrea\" ,\" Milano\" ,\" Via Garibaldi, 7\" ,\" [\" \" Address1\" \" ,\" \" Address\" \" ]\" %n"
9292 + "\" Bar Sport\" ,\" \" ,\" \" ,\" [\" \" Address\" \" ]\" %n"
9393 + "\" \" ,\" \" ,\" via Benni\" ,\" [\" \" Address\" \" ]\" %n" );
94- private static final String EXPECTED_QUERY_QUOTES_NEEDED = String .format (
95- "a.name,a.city,a.street,labels(a)%n" + "Andrea,Milano,\" Via Garibaldi, 7\" ,\" [\" Address1\" ,\" Address\" ]\" %n"
96- + "Bar Sport,,,\" [\" Address\" ]\" %n"
97- + ",,via Benni,\" [\" Address\" ]\" %n" );
94+ private static final String EXPECTED_QUERY_QUOTES_NEEDED = String .format ("a.name,a.city,a.street,labels(a)%n"
95+ + "Andrea,Milano,\" Via Garibaldi, 7\" ,\" [\" \" Address1\" \" ,\" \" Address\" \" ]\" %n"
96+ + "Bar Sport,,,\" [\" \" Address\" \" ]\" %n"
97+ + ",,via Benni,\" [\" \" Address\" \" ]\" %n" );
9898 private static final String EXPECTED = String .format (
9999 "\" _id\" ,\" _labels\" ,\" age\" ,\" city\" ,\" kids\" ,\" male\" ,\" name\" ,\" street\" ,\" _start\" ,\" _end\" ,\" _type\" %n"
100100 + "\" 0\" ,\" :User:User1\" ,\" 42\" ,\" \" ,\" [\" \" a\" \" ,\" \" b\" \" ,\" \" c\" \" ]\" ,\" true\" ,\" foo\" ,\" \" ,,,%n"
@@ -134,14 +134,24 @@ public class ExportCsvTest {
134134 + ",,,,,,,,3,4,NEXT_DELIVERY%n" );
135135 private static final String EXPECTED_NEEDED_QUOTES =
136136 String .format ("_id,_labels,age,city,kids,male,name,street,_start,_end,_type%n"
137- + "0,:User:User1,42,,\" [\" a\" ,\" b\" ,\" c \" ]\" ,true,foo,,,,%n"
137+ + "0,:User:User1,42,,\" [\" \" a\" \" ,\" \" b\" \" ,\" \" c \" \" ]\" ,true,foo,,,,%n"
138138 + "1,:User,42,,,,bar,,,,%n"
139139 + "2,:User,12,,,,,,,,%n"
140140 + "3,:Address:Address1,,Milano,,,Andrea,\" Via Garibaldi, 7\" ,,,%n"
141141 + "4,:Address,,,,,Bar Sport,,,,%n"
142142 + "5,:Address,,,,,,via Benni,,,%n"
143143 + ",,,,,,,,0,1,KNOWS%n"
144144 + ",,,,,,,,3,4,NEXT_DELIVERY%n" );
145+ private static final String EXPECTED_QUOTES_ALWAYS =
146+ "\" _id\" ,\" _labels\" ,\" age\" ,\" city\" ,\" kids\" ,\" male\" ,\" name\" ,\" street\" ,\" _start\" ,\" _end\" ,\" _type\" \n "
147+ + "\" 0\" ,\" :User:User1\" ,\" 42\" ,\" \" ,\" [\" \" a\" \" ,\" \" b\" \" ,\" \" c\" \" ]\" ,\" true\" ,\" foo\" ,\" \" ,,,\n "
148+ + "\" 1\" ,\" :User\" ,\" 42\" ,\" \" ,\" \" ,\" \" ,\" bar\" ,\" \" ,,,\n "
149+ + "\" 2\" ,\" :User\" ,\" 12\" ,\" \" ,\" \" ,\" \" ,\" \" ,\" \" ,,,\n "
150+ + "\" 3\" ,\" :Address:Address1\" ,\" \" ,\" Milano\" ,\" \" ,\" \" ,\" Andrea\" ,\" Via Garibaldi, 7\" ,,,\n "
151+ + "\" 4\" ,\" :Address\" ,\" \" ,\" \" ,\" \" ,\" \" ,\" Bar Sport\" ,\" \" ,,,\n "
152+ + "\" 5\" ,\" :Address\" ,\" \" ,\" \" ,\" \" ,\" \" ,\" \" ,\" via Benni\" ,,,\n "
153+ + ",,,,,,,,\" 0\" ,\" 1\" ,\" KNOWS\" \n "
154+ + ",,,,,,,,\" 3\" ,\" 4\" ,\" NEXT_DELIVERY\" \n " ;
145155
146156 private static final File directory = new File ("target/import" );
147157
@@ -367,6 +377,17 @@ public void testExportAllCsvNeededQuotes() {
367377 assertEquals (EXPECTED_NEEDED_QUOTES , readFile (fileName ));
368378 }
369379
380+ @ Test
381+ public void testExportAllCsvAlwaysQuotes () {
382+ String fileName = "all.csv" ;
383+ TestUtil .testCall (
384+ db ,
385+ "CALL apoc.export.csv.all($file,{quotes: 'always'})" ,
386+ map ("file" , fileName ),
387+ (r ) -> assertResults (fileName , r , "database" ));
388+ assertEquals (EXPECTED_QUOTES_ALWAYS , readFile (fileName ));
389+ }
390+
370391 @ Test
371392 public void testExportGraphCsv () {
372393 String fileName = "graph.csv" ;
@@ -698,6 +719,41 @@ public void testExportWgsPoint() {
698719 db .executeTransactionally ("MATCH (n:Position) DETACH DELETE n" );
699720 }
700721
722+ @ Test
723+ public void testGithubIssue4120 () {
724+ String query = "UNWIND [\" \\ \" Jan\\ \" Apoc User\" , \" \\ \" Jan\\ \" Apoc\\ \" \\ \" User\" ] AS name RETURN name" ;
725+ String expected = "name\n " + "\" \" \" Jan\" \" Apoc User\" \n " + "\" \" \" Jan\" \" Apoc\" \" \" \" User\" \n " ;
726+ StringBuilder sb = new StringBuilder ();
727+ testResult (
728+ db ,
729+ "CALL apoc.export.csv.query($query,null,{quotes: 'ifNeeded', stream:true,batchSize:2})" ,
730+ map ("query" , query ),
731+ (res ) -> {
732+ Map <String , Object > r = res .next ();
733+ assertEquals (2L , r .get ("batchSize" ));
734+ assertEquals (1L , r .get ("batches" ));
735+ assertEquals (0L , r .get ("nodes" ));
736+ assertEquals (2L , r .get ("rows" ));
737+ assertEquals (0L , r .get ("relationships" ));
738+ assertEquals (2L , r .get ("properties" ));
739+ assertNull ("Should get file" , r .get ("file" ));
740+ assertEquals ("csv" , r .get ("format" ));
741+ assertTrue ("Should get time greater than 0" , ((long ) r .get ("time" )) >= 0 );
742+ sb .append (r .get ("data" ));
743+ r = res .next ();
744+ assertEquals (2L , r .get ("batchSize" ));
745+ assertEquals (2L , r .get ("batches" ));
746+ assertEquals (0L , r .get ("nodes" ));
747+ assertEquals (2L , r .get ("rows" ));
748+ assertEquals (0L , r .get ("relationships" ));
749+ assertEquals (2L , r .get ("properties" ));
750+ assertTrue ("Should get time greater than 0" , ((long ) r .get ("time" )) >= 0 );
751+ sb .append (r .get ("data" ));
752+ });
753+
754+ assertEquals (expected , sb .toString ());
755+ }
756+
701757 private Consumer <Result > getAndCheckStreamingMetadataQueryMatchAddress (StringBuilder sb ) {
702758 return (res ) -> {
703759 Map <String , Object > r = res .next ();
0 commit comments