Skip to content

Commit

Permalink
added parameter support via "queryParams" parameter in request body J…
Browse files Browse the repository at this point in the history
…SON maps
  • Loading branch information
jexp committed Oct 1, 2014
1 parent 965bbe4 commit a47f8a0
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 34 deletions.
30 changes: 19 additions & 11 deletions src/main/java/org/neo4j/community/console/ConsoleApplication.java
Expand Up @@ -7,6 +7,7 @@

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -43,11 +44,15 @@ public void uncaughtException(Thread thread, Throwable throwable) {
protected Object doHandle(Request request, Response response, Neo4jService service) {
Map<String, Object> result;
try {
final String query = request.body();
if (query != null && !query.isEmpty()) {
LOG.warn("cypher: " + query);
final String body = request.body();
if (body != null && !body.isEmpty()) {
LOG.warn("cypher: " + body);
}
result = consoleService.execute(service, null, query, null,queryParamsMap(request));
Map<String, Object> requestParams = queryParamsMap(request);
Map data = body.startsWith("{") ? fromJson(body) : Collections.singletonMap("query", body);
String query = (String) data.get("query");
Map<String,Object> queryParams = (Map) data.get("queryParams");
result = consoleService.execute(service, null, query, null, requestParams, queryParams);
} catch (Exception e) {
result = map("error",e.toString());
}
Expand Down Expand Up @@ -102,16 +107,16 @@ protected Object doHandle(Request request, Response response, Neo4jService servi
});
get(new Route("console/to_yuml") {
protected Object doHandle(Request request, Response response, Neo4jService service) {
String query = param( request,"query", "");
String[] props = param( request,"props", "name").split(",");
String query = param(request, "query", "");
String[] props = param(request, "props", "name").split(",");
final String type = param(request, "type", "jpg");
final String scale = param(request, "type", "100");
SubGraph graph;
if (query.trim().isEmpty() || !service.isCypherQuery(query) || service.isMutatingQuery(query)) {
graph = SubGraph.from(service.getGraphDatabase());
} else {
final CypherQueryExecutor.CypherResult result = service.cypherQuery(query);
graph = SubGraph.from(service.getGraphDatabase(),result);
final CypherQueryExecutor.CypherResult result = service.cypherQuery(query, null);
graph = SubGraph.from(service.getGraphDatabase(), result);
}
final String yuml = new YumlExport().toYuml(graph, props);
return String.format("http://yuml.me/diagram/scruffy;dir:LR;scale:%s;/class/%s.%s", scale, yuml, type);
Expand Down Expand Up @@ -144,10 +149,10 @@ protected Object doHandle(Request request, Response response, Neo4jService servi
post(new Route("console/geoff") {
protected Object doHandle(Request request, Response response, Neo4jService service) throws SyntaxError, SubgraphError {
String geoff = request.body();
if (geoff!=null && !geoff.isEmpty()) {
LOG.warn( "geoff: "+geoff );
if (geoff != null && !geoff.isEmpty()) {
LOG.warn("geoff: " + geoff);
}
Map res = service.mergeGeoff( geoff );
Map res = service.mergeGeoff(geoff);
return toJson(res);
}
});
Expand All @@ -164,6 +169,9 @@ private Map<String, Object> queryParamsMap(Request request) {
private String toJson(Object result) {
return new GsonBuilder().serializeNulls().create().toJson(result);
}
private Map fromJson(String input) {
return new GsonBuilder().serializeNulls().create().fromJson(input, Map.class);
}

private Map requestBodyToMap(Request request) {
Map result = new Gson().fromJson(request.body(), Map.class);
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/org/neo4j/community/console/ConsoleService.java
Expand Up @@ -100,7 +100,7 @@ private void log(String msg) {
}

// split init and query on ";\n"
public Map<String, Object> execute(Neo4jService service, String init, String query, String version,Map<String,Object> params) {
public Map<String, Object> execute(Neo4jService service, String init, String query, String version,Map<String,Object> requestParams,Map<String,Object> queryParams) {
if (version!=null) service.setVersion(version);
boolean initial = init != null;
if (dontInitialize(service) || init==null || init.equalsIgnoreCase("none")) init=null;
Expand All @@ -116,7 +116,7 @@ public Map<String, Object> execute(Neo4jService service, String init, String que
data.put("graph",service.exportToGeoff());
} else if (service.isMutatingQuery(init)) {
for (String q : splitQuery(init)) {
service.initCypherQuery(q);
service.initCypherQuery(q,queryParams);
}
data.put("graph",service.exportToGeoff());
} else {
Expand All @@ -132,7 +132,7 @@ public Map<String, Object> execute(Neo4jService service, String init, String que
CypherQueryExecutor.CypherResult result = null;
if (query!=null) {
for (String q : splitQuery(query)) {
result = service.cypherQuery(q);
result = service.cypherQuery(q,queryParams);
}
data.put("result", result.getText());
data.put("json", result.getJson());
Expand All @@ -143,7 +143,7 @@ public Map<String, Object> execute(Neo4jService service, String init, String que
if (pretty!=null) data.put("query",pretty);
}
time = trace("cypher", time);
if (!noViz(params)) {
if (!noViz(requestParams)) {
data.put("visualization", service.cypherQueryViz(result));
}
trace("viz", time);
Expand Down Expand Up @@ -186,8 +186,8 @@ public String shortenUrl(String uri) {
}
}

public Map<String, Object> execute(Neo4jService service, GraphInfo info, Map<String,Object> params) {
final Map<String, Object> result = this.execute(service, info.getInit(), info.getQuery(), info.getVersion(),params);
public Map<String, Object> execute(Neo4jService service, GraphInfo info, Map<String, Object> params, Map<String, Object> queryParams) {
final Map<String, Object> result = this.execute(service, info.getInit(), info.getQuery(), info.getVersion(),params,queryParams);
result.put("message",info.getMessage());
return result;
}
Expand All @@ -206,7 +206,7 @@ protected String param(Map input, String param, String defaultValue) {
public Map<String, Object> init(Neo4jService service, Map<String,Object> input) {
input.put("init",param(input,"init",DEFAULT_GRAPH_CYPHER));
input.put("query",param(input,"query",DEFAULT_QUERY));
return execute(service, GraphInfo.from(input), input);
return execute(service, GraphInfo.from(input), input, (Map)input.get("queryParams"));
}

protected String baseUri(HttpServletRequest request, String query, final String path) {
Expand Down Expand Up @@ -241,7 +241,7 @@ Map<String, Object> init(Neo4jService service, String id, Map<String,Object> par
final GraphInfo info = storage.find(id);
Map<String, Object> result;
if (info!=null) {
result = execute(service, info.getInit(), info.getQuery(), info.getVersion(), params);
result = execute(service, info.getInit(), info.getQuery(), info.getVersion(), params,(Map)params.get("queryParams"));
result.put("message",info.getMessage());
} else {
result = init(service, params);
Expand Down
20 changes: 12 additions & 8 deletions src/main/java/org/neo4j/community/console/CypherQueryExecutor.java
Expand Up @@ -187,36 +187,40 @@ public long getTime() {
public String prettify(String query) {
return executionEngine.prettify(query).replaceAll("\n","\n ");
}
public CypherResult cypherQuery(String query, String version) {
public CypherResult cypherQuery(String query, String version, Map<String, Object> params) {
// query = replaceIndex(query);
if (version==null || version.isEmpty() || startsWithCypher(query)) return cypherQuery(query);
return cypherQuery("CYPHER "+version+" "+query);
if (version==null || version.isEmpty() || startsWithCypher(query)) return cypherQuery(query,params);
return cypherQuery("CYPHER "+version+" "+query, params);
}
public CypherResult cypherQuery(String query, String version) {
return cypherQuery(query,version,null);
}

private boolean startsWithCypher(String query) {
String q = query.trim();
return q.length() > CYPHER_LENGTH && q.substring(0, CYPHER_LENGTH).equalsIgnoreCase("cypher");
}

private CypherResult cypherQuery(String query) {
private CypherResult cypherQuery(String query, Map<String, Object> params) {
if (isMutatingQuery(query)) {
registerProperties(query);
}
boolean canProfile = canProfileQuery(query);
try {
return doExecuteQuery(query, canProfile);
return doExecuteQuery(query, params, canProfile);
} catch (NotImplementedError |AssertionError e) {
return doExecuteQuery(query, false);
return doExecuteQuery(query, params, false);
}
}

private CypherResult doExecuteQuery(String query, boolean canProfile) {
private CypherResult doExecuteQuery(String query, Map<String, Object> params, boolean canProfile) {
params = params == null ? Collections.<String,Object>emptyMap() : params;
long time=System.currentTimeMillis();
Transaction tx = gdb.beginTx();
javax.transaction.Transaction resumeTx;
try {
resumeTx = suspendTx(query);
ExecutionResult result = canProfile ? executionEngine.profile(query) : executionEngine.execute(query);
ExecutionResult result = canProfile ? executionEngine.profile(query,params) : executionEngine.execute(query,params);
final Collection<Map<String, Object>> data = IteratorUtil.asCollection(result);
time = System.currentTimeMillis() - time;
resumeTransaction(resumeTx);
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/org/neo4j/community/console/Neo4jService.java
Expand Up @@ -63,7 +63,7 @@ private Neo4jService(GraphDatabaseService gdb, boolean ownsDatabase) {

public Map cypherQueryViz(String query) {
final boolean invalidQuery = query == null || query.trim().isEmpty() || cypherQueryExecutor.isMutatingQuery(query);
return invalidQuery ? cypherQueryViz((CypherQueryExecutor.CypherResult) null) : cypherQueryViz(cypherQuery(query));
return invalidQuery ? cypherQueryViz((CypherQueryExecutor.CypherResult) null) : cypherQueryViz(cypherQuery(query, null));
}
public Map cypherQueryViz(CypherQueryExecutor.CypherResult result) {
try (Transaction tx = gdb.beginTx()) {
Expand Down Expand Up @@ -107,17 +107,17 @@ public Map<String,Object> mergeGeoff(String geoff) {

public Collection<Map<String,Object>> cypherQueryResults(String query) {
Collection<Map<String,Object>> result=new ArrayList<>();
for (Map<String, Object> row : cypherQuery(query)) {
for (Map<String, Object> row : cypherQuery(query, null)) {
result.add(row);
}
return result;
}

public CypherQueryExecutor.CypherResult initCypherQuery(String query) {
return cypherQueryExecutor.cypherQuery(query,null);
public CypherQueryExecutor.CypherResult initCypherQuery(String query, Map<String, Object> queryParams) {
return cypherQueryExecutor.cypherQuery(query,null,queryParams);
}
public CypherQueryExecutor.CypherResult cypherQuery(String query) {
return cypherQueryExecutor.cypherQuery(query,version);
public CypherQueryExecutor.CypherResult cypherQuery(String query, Map<String, Object> queryParams) {
return cypherQueryExecutor.cypherQuery(query,version,queryParams);
}

public String prettify(String query) {
Expand Down
Expand Up @@ -17,6 +17,7 @@
import static org.junit.Assert.*;
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
import static org.neo4j.helpers.collection.MapUtil.map;

/**
* @author mh
Expand Down Expand Up @@ -193,6 +194,12 @@ public void testReplaceIndex() throws Exception {

}

@Test
public void testUseParameters() throws Exception {
CypherQueryExecutor.CypherResult result = cypherQueryExecutor.cypherQuery("MATCH (n) WHERE id(n) = {id} RETURN count(*)",null, map("id",rootNode.getId()));
assertEquals(1,result.getRowCount());
}

@Test
public void testDontProfileUnionCheck() throws Exception {
assertFalse(cypherQueryExecutor.canProfileQuery("start n=node(*) return n UNION start n=node(*) return n"));
Expand All @@ -209,10 +216,11 @@ public void testDontProfileUnion() throws Exception {
@Test
public void testHandlePeriodicCommit() throws Exception {
String query = "USING PERIODIC COMMIT\n" +
"LOAD CSV WITH HEADERS FROM 'http://docs.neo4j.org/chunked/2.1-SNAPSHOT/csv/import/roles.csv' AS csvLine\n" +
"LOAD CSV WITH HEADERS FROM 'http://docs.neo4j.org/chunked/stable/csv/import/roles.csv' AS csvLine\n" +
"CREATE (p:Person { id: csvLine.personId})\n" +
"RETURN p";
CypherQueryExecutor.CypherResult result = cypherQueryExecutor.cypherQuery(query, null);
assertEquals(6,result.getRowCount());
}

}
11 changes: 11 additions & 0 deletions src/test/java/org/neo4j/community/console/Neo4jServiceTest.java
Expand Up @@ -5,6 +5,8 @@
import org.junit.Before;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.helpers.collection.MapUtil;
import org.neo4j.test.TestGraphDatabaseFactory;

Expand All @@ -29,6 +31,15 @@ public void testMergeGeoff() throws Exception {
assertEquals(MapUtil.map("foo", "bar"),map.get("(0)"));
assertEquals("{\"(0)\":{\"foo\":\"bar\"}}",new Gson().toJson(map));
}
@Test
public void testQueryCypher() throws Exception {
try (Transaction tx = gdb.beginTx()) {
final CypherQueryExecutor.CypherResult newNode = neo4jService.initCypherQuery("CREATE (n:Person {name:{name}}) RETURN id(n) as id", MapUtil.map("name", "Anders"));
long id = ((Number)newNode.getRows().iterator().next().get("id")).longValue();
final CypherQueryExecutor.CypherResult map = neo4jService.cypherQuery("MATCH (n) WHERE id(n) = {id} RETURN n.name", MapUtil.map("id", id));
assertEquals(1, map.getRowCount());
}
}

@After
public void tearDown() throws Exception {
Expand Down

0 comments on commit a47f8a0

Please sign in to comment.