Skip to content

Commit

Permalink
fix runFirstColumn for neo4j-graphql-js, fixes #819 fixes #776
Browse files Browse the repository at this point in the history
  • Loading branch information
jexp committed Jun 24, 2018
1 parent bebfff1 commit 39559c8
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
3 changes: 2 additions & 1 deletion docs/overview.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,8 @@ CALL apoc.generate.simple([2,2,2,2], null, null)
[cols="1m,5"]
|===
| CALL apoc.cypher.run(fragment, params) yield value | executes reading fragment with the given parameters
| apoc.cypher.runFirstColumn(statement, params, [expectMultiplevalues]) | function that executes statement with given parameters returning first column only, if expectMultipleValues is true will collect results into a list
| apoc.cypher.runFirstColumnSingle(statement, params) | function that executes statement with given parameters returning first column only, will return first/single row or null
| apoc.cypher.runFirstColumnMany(statement, params) | function that executes statement with given parameters returning first column only, will collect all rows into a list
| CALL apoc.cypher.runFile(file or url,{config}) yield row, result | runs each statement in the file, all semicolon separated - currently no schema operations
| CALL apoc.cypher.runFiles([files or urls],{config}) yield row, result | runs each statement in the files, all semicolon separated
| CALL apoc.cypher.runSchemaFile(file or url,{config}) - allows only schema operations, runs each schema statement in the file, all semicolon separated
Expand Down
22 changes: 19 additions & 3 deletions src/main/java/apoc/cypher/CypherFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import org.neo4j.procedure.UserFunction;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static apoc.cypher.Cypher.withParamMapping;

Expand All @@ -21,16 +23,30 @@ public class CypherFunctions {
public GraphDatabaseService db;

@UserFunction
@Description("apoc.cypher.runFirstColumn(kernelTransaction, params, expectMultipleValues) - executes kernelTransaction with given parameters, returns first column only, if expectMultipleValues is true will collect results into an array")
@Deprecated
@Description("use either apoc.cypher.runFirstColumnMany for a list return or apoc.cypher.runFirstColumnSingle for returning the first row of the first column")
public Object runFirstColumn(@Name("cypher") String statement, @Name("params") Map<String, Object> params, @Name(value = "expectMultipleValues",defaultValue = "true") boolean expectMultipleValues) {
if (params == null) params = Collections.emptyMap();
try (Result result = db.execute(withParamMapping(statement, params.keySet()), params)) {
String resolvedStatement = withParamMapping(statement, params.keySet());
if (!resolvedStatement.contains(" runtime")) resolvedStatement = "cypher runtime=slotted " + resolvedStatement;
try (Result result = db.execute(resolvedStatement, params)) {

String firstColumn = result.columns().get(0);
try (ResourceIterator<Object> iter = result.columnAs(firstColumn)) {
if (expectMultipleValues) return iter.stream().toArray();
if (expectMultipleValues) return iter.stream().collect(Collectors.toList());
return iter.hasNext() ? iter.next() : null;
}
}
}

@UserFunction
@Description("apoc.cypher.runFirstColumnMany(statement, params, expectMultipleValues) - executes statement with given parameters, returns first column only collected into a list, params are available as identifiers")
public List<Object> runFirstColumnMany(@Name("cypher") String statement, @Name("params") Map<String, Object> params) {
return (List)runFirstColumn(statement, params, true);
}
@UserFunction
@Description("apoc.cypher.runFirstColumnSingle(statement, params, expectMultipleValues) - executes statement with given parameters, returns first element of the first column only, params are available as identifiers")
public Object runFirstColumnSingle(@Name("cypher") String statement, @Name("params") Map<String, Object> params) {
return runFirstColumn(statement, params, false);
}
}
10 changes: 8 additions & 2 deletions src/test/java/apoc/cypher/CypherTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,17 @@ public void testRunVariable() throws Exception {
}

@Test
public void testRunFirstColumn() throws Exception {
testCall(db, "RETURN apoc.cypher.runFirstColumn('RETURN a + 7 AS b', {a: 3}, false) AS s",
public void testRunFirstColumnSingle() throws Exception {
testCall(db, "RETURN apoc.cypher.runFirstColumnSingle('RETURN a + 7 AS b', {a: 3}) AS s",
r -> assertEquals(10L, (r.get("s"))));
}

@Test
public void testRunFirstColumnMany() throws Exception {
testCall(db, "RETURN apoc.cypher.runFirstColumnMany('UNWIND range(1,a) as id RETURN id', {a: 3}) AS s",
r -> assertEquals(Arrays.asList(1L,2L,3L), (r.get("s"))));
}

@Test
public void testRunFirstColumnBugCompiled() throws Exception {
ResourceIterator<Node> it = db.execute("CREATE (m:Movie {title:'MovieA'})<-[:ACTED_IN]-(p:Person {name:'PersonA'})-[:ACTED_IN]->(m2:Movie {title:'MovieB'}) RETURN m").columnAs("m");
Expand Down

0 comments on commit 39559c8

Please sign in to comment.