From b7ea858f15f90e0416345f5129c4f942359f212a Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Mon, 1 Jul 2019 15:32:20 +0300 Subject: [PATCH 001/128] closes #40 (#41) --- pom.xml | 6 ++++++ .../java/com/redislabs/redisgraph/RedisGraphAPITest.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bd6487..8fd22c7 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,12 @@ commons-text 1.6 + + org.slf4j + slf4j-simple + 1.6.6 + test + 8 diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 8730526..bf4be21 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -78,7 +78,7 @@ public void testConnectNodes() { Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); // Connect source and destination nodes. - ResultSet resultSet = api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)"); + ResultSet resultSet = api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); Assert.assertFalse(resultSet.hasNext()); Assert.assertNull(resultSet.getStatistics().getStringValue(Label.NODES_CREATED)); From 8aa70bb39f9d7b1b716ba4f5c2eb1506f87199b4 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 4 Jul 2019 11:17:02 +0300 Subject: [PATCH 002/128] changed Jedis client to new 3.1.0 version. Modified send command flow --- pom.xml | 11 ++++-- .../com/redislabs/redisgraph/RedisGraph.java | 36 +++---------------- .../impl/JRedisGraphTransaction.java | 4 +++ 3 files changed, 17 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java diff --git a/pom.xml b/pom.xml index 8fd22c7..5323061 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,14 @@ repo - + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + + + org.apache.commons @@ -62,7 +69,7 @@ redis.clients jedis - 3.0.1 + 3.1.0-SNAPSHOT org.apache.commons diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index 9c0871d..e738c95 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -10,6 +10,7 @@ import redis.clients.jedis.JedisPool; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.util.Pool; +import redis.clients.jedis.util.SafeEncoder; import java.io.Closeable; import java.util.*; @@ -29,7 +30,7 @@ public class RedisGraph implements Closeable { - private static final CharSequenceTranslator ESCAPE_CHYPER; + public static final CharSequenceTranslator ESCAPE_CHYPER; static { final Map escapeJavaMap = new HashMap<>(); escapeJavaMap.put("\'", "\\'"); @@ -91,7 +92,7 @@ public ResultSet query(String graphId, String query, Object ...args) { graphCaches.putIfAbsent(graphId, new GraphCache(graphId, this)); List rawResponse = null; try(Jedis conn = getConnection()){ - rawResponse= sendCompactCommand(conn, Command.QUERY, graphId, query).getObjectMultiBulkReply(); + rawResponse = (List) conn.sendCommand(Command.QUERY, graphId, query, "--COMPACT"); } return new ResultSetImpl(rawResponse, graphCaches.get(graphId)); @@ -129,40 +130,11 @@ public String deleteGraph(String graphId) { //clear local state graphCaches.remove(graphId); try (Jedis conn = getConnection()) { - return sendCommand(conn, Command.DELETE, graphId).getBulkReply(); + return SafeEncoder.encode((byte[]) conn.sendCommand(Command.DELETE, graphId)); } } - - /** - * Sends command - will be replaced with sendCompactCommand once graph.delete support --compact flag - * @param conn - connection - * @param provider - command type - * @param args - command arguments - * @return - */ - private BinaryClient sendCommand(Jedis conn, ProtocolCommand provider, String ...args) { - BinaryClient binaryClient = conn.getClient(); - binaryClient.sendCommand(provider, args); - return binaryClient; - } - - - /** - * Sends the command with --COMPACT flag - * @param conn - connection - * @param provider - command type - * @param args - command arguments - * @return - */ - private BinaryClient sendCompactCommand(Jedis conn, ProtocolCommand provider, String ...args) { - String[] t = new String[args.length +1]; - System.arraycopy(args, 0 , t, 0, args.length); - t[args.length]="--COMPACT"; - return sendCommand(conn, provider, t); - } - private Jedis getConnection() { return this.client.getResource(); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java new file mode 100644 index 0000000..cc77969 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java @@ -0,0 +1,4 @@ +package com.redislabs.redisgraph.impl; + +public class JRedisGraphTransaction { +} From 62e9c432a97e006effe63afac8a11ce1c87b0ebf Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 4 Jul 2019 16:34:08 +0300 Subject: [PATCH 003/128] added multi exec support --- pom.xml | 2 +- .../com/redislabs/redisgraph/RedisGraph.java | 53 ++++----- .../java/com/redislabs/redisgraph/Utils.java | 56 ++++++++- .../impl/JRedisGraphTransaction.java | 104 ++++++++++++++++- .../redisgraph/RedisGraphAPITest.java | 109 ++++++++++++++++++ 5 files changed, 289 insertions(+), 35 deletions(-) diff --git a/pom.xml b/pom.xml index 5323061..10707ce 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ redis.clients jedis - 3.1.0-SNAPSHOT + 3.1.0-m4 org.apache.commons diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index e738c95..c33b44d 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -1,11 +1,13 @@ package com.redislabs.redisgraph; +import com.redislabs.redisgraph.impl.JRedisGraphTransaction; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; import com.redislabs.redisgraph.impl.ResultSetImpl; import org.apache.commons.text.translate.AggregateTranslator; import org.apache.commons.text.translate.CharSequenceTranslator; import org.apache.commons.text.translate.LookupTranslator; import redis.clients.jedis.BinaryClient; +import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.commands.ProtocolCommand; @@ -28,16 +30,6 @@ public class RedisGraph implements Closeable { private final Pool client; private final Map graphCaches = new ConcurrentHashMap<>(); - - - public static final CharSequenceTranslator ESCAPE_CHYPER; - static { - final Map escapeJavaMap = new HashMap<>(); - escapeJavaMap.put("\'", "\\'"); - escapeJavaMap.put("\"", "\\\""); - ESCAPE_CHYPER = new AggregateTranslator(new LookupTranslator(Collections.unmodifiableMap(escapeJavaMap))); - } - /** * Creates a client running on the local machine @@ -81,21 +73,13 @@ public void close(){ * @return a result set */ public ResultSet query(String graphId, String query, Object ...args) { - if(args.length > 0) { - for(int i=0; i rawResponse = null; try(Jedis conn = getConnection()){ - rawResponse = (List) conn.sendCommand(Command.QUERY, graphId, query, "--COMPACT"); + rawResponse = (List) conn.sendCommand(Command.QUERY, graphId, preparedQuery, "--COMPACT"); } return new ResultSetImpl(rawResponse, graphCaches.get(graphId)); - } /** @@ -104,7 +88,7 @@ public ResultSet query(String graphId, String query, Object ...args) { * @param procedure procedure name to invoke * @return result set with the procedure data */ - public ResultSet callProcedure(String graphId, String procedure ){ + public ResultSet callProcedure(String graphId, String procedure){ return callProcedure(graphId, procedure, new ArrayList<>(), new HashMap<>()); } @@ -120,10 +104,9 @@ public ResultSet callProcedure(String graphId, String procedure, List ar return callProcedure(graphId, procedure, args, new HashMap<>()); } - /** * Deletes the entire graph - * + * @param graphId graph to delete * @return delete running time statistics */ public String deleteGraph(String graphId) { @@ -146,17 +129,23 @@ private Jedis getConnection() { * @param procedure - procedure to execute * @param args - procedure arguments * @param kwargs - procedure output arguments - * @return + * @return result set with the procedure data */ public ResultSet callProcedure(String graphId, String procedure, List args , Map> kwargs ){ - args = args.stream().map( s -> Utils.quoteString(s)).collect(Collectors.toList()); - StringBuilder queryString = new StringBuilder(); - queryString.append(String.format("CALL %s(%s)", procedure, String.join(",", args))); - List kwargsList = kwargs.getOrDefault("y", null); - if(kwargsList != null){ - queryString.append(String.join(",", kwargsList)); - } - return query(graphId, queryString.toString()); + String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); + return query(graphId, preparedProcedure); + } + + public JRedisGraphTransaction multi(){ + Jedis jedis = getConnection(); + Client client = jedis.getClient(); + client.multi(); + client.getOne(); + return new JRedisGraphTransaction(client,this, this.graphCaches); + } + + public Map getGraphCaches() { + return graphCaches; } } diff --git a/src/main/java/com/redislabs/redisgraph/Utils.java b/src/main/java/com/redislabs/redisgraph/Utils.java index 180e8fb..2be06d4 100644 --- a/src/main/java/com/redislabs/redisgraph/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/Utils.java @@ -1,14 +1,32 @@ package com.redislabs.redisgraph; +import org.apache.commons.text.translate.AggregateTranslator; +import org.apache.commons.text.translate.CharSequenceTranslator; +import org.apache.commons.text.translate.LookupTranslator; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + /** * Utilities class */ public class Utils { + public static final CharSequenceTranslator ESCAPE_CHYPER; + static { + final Map escapeJavaMap = new HashMap<>(); + escapeJavaMap.put("\'", "\\'"); + escapeJavaMap.put("\"", "\\\""); + ESCAPE_CHYPER = new AggregateTranslator(new LookupTranslator(Collections.unmodifiableMap(escapeJavaMap))); + } + /** * * @param str - a string - * @return the input string surounded with quotation marks, if needed + * @return the input string surrounded with quotation marks, if needed */ public static String quoteString(String str){ if(str.startsWith("\"") && str.endsWith("\"")){ @@ -25,4 +43,40 @@ public static String quoteString(String str){ } return sb.toString(); } + + /** + * Prepare and formats a query and query arguments + * @param query - query + * @param args - query arguments + * @return formatted query + */ + public static String prepareQuery(String query, Object ...args){ + if(args.length > 0) { + for(int i=0; i args , Map> kwargs){ + args = args.stream().map( s -> Utils.quoteString(s)).collect(Collectors.toList()); + StringBuilder queryStringBuilder = new StringBuilder(); + queryStringBuilder.append(String.format("CALL %s(%s)", procedure, String.join(",", args))); + List kwargsList = kwargs.getOrDefault("y", null); + if(kwargsList != null){ + queryStringBuilder.append(String.join(",", kwargsList)); + } + return queryStringBuilder.toString(); + } } diff --git a/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java index cc77969..5476c6d 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java @@ -1,4 +1,106 @@ package com.redislabs.redisgraph.impl; -public class JRedisGraphTransaction { + +import com.redislabs.redisgraph.Command; +import com.redislabs.redisgraph.RedisGraph; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.Utils; +import com.redislabs.redisgraph.impl.graph_cache.GraphCache; +import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.Client; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.Response; +import redis.clients.jedis.Transaction; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class is extending Jedis Transaction + */ +public class JRedisGraphTransaction extends Transaction { + + private final RedisGraph redisGraph; + private final Map graphCaches; + + + public JRedisGraphTransaction(Client client, RedisGraph redisGraph, Map graphCaches){ + // init as in Jedis + super(client); + + this.redisGraph = redisGraph; + this.graphCaches = graphCaches; + } + + /** + * Execute a Cypher query with arguments + * + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param args + * @return response with a result set + */ + public Response graphQuery(String graphId, String query, Object ...args){ + String preparedQuery = Utils.prepareQuery(query, args); + graphCaches.putIfAbsent(graphId, new GraphCache(graphId, redisGraph)); + client.sendCommand(Command.QUERY, graphId, preparedQuery, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, graphCaches.get(graphId)); + } + }); + } + + + /** + * Invokes stored procedures without arguments, in multi/exec context + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @return response with result set with the procedure data + */ + public Response graphCallProcedure(String graphId, String procedure){ + return graphCallProcedure(graphId, procedure, new ArrayList<>(), new HashMap<>()); + } + + /** + * Invokes stored procedure with arguments, in multi/exec context + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @param args procedure arguments + * @return response with result set with the procedure data + */ + public Response graphCallProcedure(String graphId, String procedure, List args ){ + return graphCallProcedure(graphId, procedure, args, new HashMap<>()); + } + + + /** + * Invoke a stored procedure, in multi/exec context + * @param graphId a graph to perform the query on + * @param procedure - procedure to execute + * @param args - procedure arguments + * @param kwargs - procedure output arguments + * @return response with result set with the procedure data + */ + public Response graphCallProcedure(String graphId, String procedure, List args, + HashMap> kwargs) { + String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); + return graphQuery(graphId, preparedProcedure); + } + + + /** + * Deletes the entire graph, in multi/exec context + * @param graphId graph to delete + * @return response with the deletion running time statistics + */ + public Response graphDeleteGraph(String graphId){ + graphCaches.remove(graphId); + client.sendCommand(Command.DELETE, graphId); + return getResponse(BuilderFactory.STRING); + } } diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index bf4be21..d8a6374 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -10,6 +10,8 @@ import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; +import com.redislabs.redisgraph.impl.JRedisGraphTransaction; +import com.redislabs.redisgraph.impl.ResultSetImpl; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -494,4 +496,111 @@ public void testEscapedQuery() { Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1=%s and n.s2=%s RETURN n", "S\"\'", "S\\'\\\"")); Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"\\'' RETURN n")); } + + + @Test + public void testMultiExec(){ + JRedisGraphTransaction transaction = api.multi(); + + transaction.set("x", "1"); + transaction.graphQuery("social", "CREATE (:Person {name:'a'})"); + transaction.graphQuery("g", "CREATE (:Person {name:'a'})"); + transaction.incr("x"); + transaction.get("x"); + transaction.graphQuery("social", "MATCH (n:Person) RETURN n"); + transaction.graphDeleteGraph("g"); + transaction.graphCallProcedure("social", "db.labels"); + List results = transaction.exec(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Redis incr command + Assert.assertEquals(Long.class, results.get(3).getClass()); + Assert.assertEquals((long)2, results.get(3)); + + // Redis get command + Assert.assertEquals(String.class, results.get(4).getClass()); + Assert.assertEquals("2", results.get(4)); + + // Graph query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); + + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + + List schemaNames = header.getSchemaNames(); + List schemaTypes = header.getSchemaTypes(); + + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); + + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); + + Assert.assertEquals("n", schemaNames.get(0)); + + Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); + + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "a"); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + + // Graph delete + Assert.assertTrue(((String)results.get(6)).startsWith("Graph removed")); + + + Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); + resultSet = (ResultSet) results.get(7); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + + schemaNames = header.getSchemaNames(); + schemaTypes = header.getSchemaTypes(); + + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); + + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); + + Assert.assertEquals("label", schemaNames.get(0)); + + Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + + } } From 76a3f137dc349dc106c52fa74f53495e8b7f32fd Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 9 Jul 2019 12:54:59 +0300 Subject: [PATCH 004/128] Update config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index abebfaf..6f130e1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: docker: - image: circleci/openjdk:8u171-jdk - - image: redislabs/redisgraph:2.0-edge + - image: redislabs/redisgraph:edge port: 6379:6379 working_directory: ~/repo From 48329d4188a025fc0328010efed1018dfcd5e24a Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 10 Jul 2019 21:47:04 +0300 Subject: [PATCH 005/128] added watch support --- pom.xml | 7 - .../java/com/redislabs/redisgraph/Header.java | 6 +- .../com/redislabs/redisgraph/RedisGraph.java | 125 ++---------- .../redisgraph/RedisGraphContexted.java | 32 +++ .../redisgraph/RedisGraphGeneralContext.java | 13 ++ .../redisgraph/RedisGraphTransaction.java | 91 +++++++++ .../com/redislabs/redisgraph/ResultSet.java | 5 +- .../redisgraph/graph_entities/Edge.java | 2 +- .../graph_entities/GraphEntity.java | 4 +- .../redisgraph/graph_entities/Node.java | 2 +- .../redisgraph/{ => impl}/Utils.java | 11 +- .../impl/api/AbstractRedisGraph.java | 59 ++++++ .../impl/api/ContextedRedisGraph.java | 121 +++++++++++ .../redisgraph/impl/api/RedisGraph.java | 113 ++++++++++ .../impl/api/RedisGraphCacheHolder.java | 8 + .../api/RedisGraphCommand.java} | 6 +- .../RedisGraphTransaction.java} | 56 ++--- .../impl/graph_cache/GraphCache.java | 21 +- .../impl/graph_cache/GraphCacheList.java | 20 +- .../impl/graph_cache/RedisGraphCaches.java | 59 ++++++ .../impl/{ => resultset}/HeaderImpl.java | 2 +- .../impl/{ => resultset}/RecordImpl.java | 2 +- .../impl/{ => resultset}/ResultSetImpl.java | 29 ++- .../impl/{ => resultset}/StatisticsImpl.java | 8 +- .../redisgraph/RedisGraphAPITest.java | 193 ++++++++++++++++-- 25 files changed, 781 insertions(+), 214 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java create mode 100644 src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java create mode 100644 src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java rename src/main/java/com/redislabs/redisgraph/{ => impl}/Utils.java (88%) create mode 100644 src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java create mode 100644 src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java create mode 100644 src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java create mode 100644 src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCacheHolder.java rename src/main/java/com/redislabs/redisgraph/{Command.java => impl/api/RedisGraphCommand.java} (68%) rename src/main/java/com/redislabs/redisgraph/impl/{JRedisGraphTransaction.java => api/RedisGraphTransaction.java} (55%) create mode 100644 src/main/java/com/redislabs/redisgraph/impl/graph_cache/RedisGraphCaches.java rename src/main/java/com/redislabs/redisgraph/impl/{ => resultset}/HeaderImpl.java (98%) rename src/main/java/com/redislabs/redisgraph/impl/{ => resultset}/RecordImpl.java (97%) rename src/main/java/com/redislabs/redisgraph/impl/{ => resultset}/ResultSetImpl.java (88%) rename src/main/java/com/redislabs/redisgraph/impl/{ => resultset}/StatisticsImpl.java (93%) diff --git a/pom.xml b/pom.xml index 10707ce..a83a43c 100644 --- a/pom.xml +++ b/pom.xml @@ -47,13 +47,6 @@ - - - snapshots-repo - https://oss.sonatype.org/content/repositories/snapshots - - - org.apache.commons diff --git a/src/main/java/com/redislabs/redisgraph/Header.java b/src/main/java/com/redislabs/redisgraph/Header.java index 43cf8b3..a8156aa 100644 --- a/src/main/java/com/redislabs/redisgraph/Header.java +++ b/src/main/java/com/redislabs/redisgraph/Header.java @@ -3,16 +3,16 @@ import java.util.List; /** - * Query response header interface. Represents the response schame (column names and types) + * Query response header interface. Represents the response schema (column names and types) */ public interface Header { - public enum ResultSetColumnTypes { + enum ResultSetColumnTypes { COLUMN_UNKNOWN, COLUMN_SCALAR, COLUMN_NODE, - COLUMN_RELATION; + COLUMN_RELATION } diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index c33b44d..90432bd 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -1,86 +1,19 @@ package com.redislabs.redisgraph; -import com.redislabs.redisgraph.impl.JRedisGraphTransaction; -import com.redislabs.redisgraph.impl.graph_cache.GraphCache; -import com.redislabs.redisgraph.impl.ResultSetImpl; -import org.apache.commons.text.translate.AggregateTranslator; -import org.apache.commons.text.translate.CharSequenceTranslator; -import org.apache.commons.text.translate.LookupTranslator; -import redis.clients.jedis.BinaryClient; -import redis.clients.jedis.Client; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.commands.ProtocolCommand; -import redis.clients.jedis.util.Pool; -import redis.clients.jedis.util.SafeEncoder; - import java.io.Closeable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - - -/** - * - */ -public class RedisGraph implements Closeable { - - - - private final Pool client; - private final Map graphCaches = new ConcurrentHashMap<>(); - - /** - * Creates a client running on the local machine - - */ - public RedisGraph() { - this("localhost", 6379); - } - - /** - * Creates a client running on the specific host/post - * - * @param host Redis host - * @param port Redis port - */ - public RedisGraph(String host, int port) { - this( new JedisPool(host, port)); - } - - /** - * Creates a client using provided Jedis pool - * - * @param jedis bring your own Jedis pool - */ - public RedisGraph( Pool jedis) { - - this.client = jedis; - } - - @Override - public void close(){ - this.client.close(); - } +import java.util.List; +import java.util.Map; +public interface RedisGraph extends Closeable { /** * Execute a Cypher query with arguments - * * @param graphId a graph to perform the query on * @param query Cypher query * @param args * @return a result set */ - public ResultSet query(String graphId, String query, Object ...args) { - String preparedQuery = Utils.prepareQuery(query, args); - graphCaches.putIfAbsent(graphId, new GraphCache(graphId, this)); - List rawResponse = null; - try(Jedis conn = getConnection()){ - rawResponse = (List) conn.sendCommand(Command.QUERY, graphId, preparedQuery, "--COMPACT"); - } - return new ResultSetImpl(rawResponse, graphCaches.get(graphId)); - } + ResultSet query(String graphId, String query, Object ...args); /** * Invokes stored procedures without arguments @@ -88,10 +21,7 @@ public ResultSet query(String graphId, String query, Object ...args) { * @param procedure procedure name to invoke * @return result set with the procedure data */ - public ResultSet callProcedure(String graphId, String procedure){ - return callProcedure(graphId, procedure, new ArrayList<>(), new HashMap<>()); - } - + ResultSet callProcedure(String graphId, String procedure); /** * Invokes stored procedure with arguments @@ -100,28 +30,7 @@ public ResultSet callProcedure(String graphId, String procedure){ * @param args procedure arguments * @return result set with the procedure data */ - public ResultSet callProcedure(String graphId, String procedure, List args ){ - return callProcedure(graphId, procedure, args, new HashMap<>()); - } - - /** - * Deletes the entire graph - * @param graphId graph to delete - * @return delete running time statistics - */ - public String deleteGraph(String graphId) { - //clear local state - graphCaches.remove(graphId); - try (Jedis conn = getConnection()) { - return SafeEncoder.encode((byte[]) conn.sendCommand(Command.DELETE, graphId)); - } - - } - - private Jedis getConnection() { - return this.client.getResource(); - } - + ResultSet callProcedure(String graphId, String procedure, List args); /** * Invoke a stored procedure @@ -131,21 +40,13 @@ private Jedis getConnection() { * @param kwargs - procedure output arguments * @return result set with the procedure data */ - public ResultSet callProcedure(String graphId, String procedure, List args , Map> kwargs ){ + ResultSet callProcedure(String graphId, String procedure, List args , Map> kwargs); - String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); - return query(graphId, preparedProcedure); - } - - public JRedisGraphTransaction multi(){ - Jedis jedis = getConnection(); - Client client = jedis.getClient(); - client.multi(); - client.getOne(); - return new JRedisGraphTransaction(client,this, this.graphCaches); - } + /** + * Deletes the entire graph + * @param graphId graph to delete + * @return delete running time statistics + */ + String deleteGraph(String graphId); - public Map getGraphCaches() { - return graphCaches; - } } diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java b/src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java new file mode 100644 index 0000000..5ef1037 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java @@ -0,0 +1,32 @@ +package com.redislabs.redisgraph; + +import redis.clients.jedis.Jedis; + +public interface RedisGraphContexted extends RedisGraph { + + + /** + * Returns implementing class connection context + * @return Jedis connection + */ + Jedis getConnectionContext(); + + /** + * Returns a Redis transactional object, over the connection context, with graph API capabilities + * @return Redis transactional object, over the connection context, with graph API capabilities + */ + RedisGraphTransaction multi(); + + /** + * Perform watch over given Redis keys + * @param keys + * @return "OK" + */ + String watch(String... keys); + + /** + * Removes watch from all keys + * @return + */ + String unwatch(); +} diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java b/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java new file mode 100644 index 0000000..4596ec9 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java @@ -0,0 +1,13 @@ +package com.redislabs.redisgraph; + +import redis.clients.jedis.Jedis; + +public interface RedisGraphGeneralContext extends RedisGraph { + + /** + * Generate a connection bounded api + * @return a connection bounded api + */ + RedisGraphContexted getContextedAPI(); + +} diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java new file mode 100644 index 0000000..c206640 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java @@ -0,0 +1,91 @@ +package com.redislabs.redisgraph; + +import redis.clients.jedis.Response; +import redis.clients.jedis.commands.BasicRedisPipeline; +import redis.clients.jedis.commands.BinaryRedisPipeline; +import redis.clients.jedis.commands.BinaryScriptingCommandsPipeline; +import redis.clients.jedis.commands.ClusterPipeline; +import redis.clients.jedis.commands.MultiKeyBinaryRedisPipeline; +import redis.clients.jedis.commands.MultiKeyCommandsPipeline; +import redis.clients.jedis.commands.RedisPipeline; +import redis.clients.jedis.commands.ScriptingCommandsPipeline; + +import java.io.Closeable; +import java.util.List; +import java.util.Map; + +/** + * An interface which aligned to Jedis transactional interface + */ +public interface RedisGraphTransaction extends + MultiKeyBinaryRedisPipeline, + MultiKeyCommandsPipeline, ClusterPipeline, + BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline, + BasicRedisPipeline, BinaryRedisPipeline, RedisPipeline, Closeable { + /** + * Execute a Cypher query with arguments + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param args + * @return a response which builds the result set with the query answer + */ + Response query(String graphId, String query, Object ...args); + + /** + * Invokes stored procedures without arguments + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @return a response which builds result set with the procedure data + */ + Response callProcedure(String graphId, String procedure); + + /** + * Invokes stored procedure with arguments + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @param args procedure arguments + * @return a response which builds result set with the procedure data + */ + Response callProcedure(String graphId, String procedure, List args); + + /** + * Invoke a stored procedure + * @param graphId a graph to perform the query on + * @param procedure - procedure to execute + * @param args - procedure arguments + * @param kwargs - procedure output arguments + * @return a response which builds result set with the procedure data + */ + Response callProcedure(String graphId, String procedure, List args , Map> kwargs); + + /** + * Deletes the entire graph + * @param graphId graph to delete + * @return a response which builds the delete running time statistics + */ + Response deleteGraph(String graphId); + + + /** + * executes the transaction + * @return a list of the executed transaction commands answers, in case of successful transaction, null otherwise + */ + List exec(); + + /** + * If object is in transaction mode, + * flushes all previously queued commands in a transaction and restores the connection state to normal + */ + void clear(); + + /** + * + * @return + */ + List> execGetResponse(); + + /** + * Flushes all previously queued commands in a transaction and restores the connection state to normal + */ + String discard(); +} diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index 7ac933a..251a4d0 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -1,14 +1,13 @@ package com.redislabs.redisgraph; import java.util.Iterator; -import java.util.List; /** * Hold a query result */ public interface ResultSet extends Iterator { - public enum ResultSetScalarTypes { + enum ResultSetScalarTypes { PROPERTY_UNKNOWN, PROPERTY_NULL, PROPERTY_STRING, @@ -17,7 +16,7 @@ public enum ResultSetScalarTypes { PROPERTY_DOUBLE, } - public int size(); + int size(); Statistics getStatistics(); diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java index fa30d03..f7c0135 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java @@ -8,7 +8,7 @@ */ public class Edge extends GraphEntity { - //memebers + //members private String relationshipType; private int source; private int destination; diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index d2083a6..42cc3f9 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -16,8 +16,8 @@ public abstract class GraphEntity { //members - protected int id; - protected final Map propertyMap = new HashMap<>(); + int id; + final Map propertyMap = new HashMap<>(); //setters & getters diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java index 6ede861..f118964 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java @@ -28,7 +28,7 @@ public void removeLabel(String label) { /** * @param index - label index - * @return the proprty label + * @return the property label * @throws IndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index >= getNumberOfLabels()}) */ diff --git a/src/main/java/com/redislabs/redisgraph/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java similarity index 88% rename from src/main/java/com/redislabs/redisgraph/Utils.java rename to src/main/java/com/redislabs/redisgraph/impl/Utils.java index 2be06d4..b9d1873 100644 --- a/src/main/java/com/redislabs/redisgraph/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -1,9 +1,10 @@ -package com.redislabs.redisgraph; +package com.redislabs.redisgraph.impl; import org.apache.commons.text.translate.AggregateTranslator; import org.apache.commons.text.translate.CharSequenceTranslator; import org.apache.commons.text.translate.LookupTranslator; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -14,8 +15,12 @@ * Utilities class */ public class Utils { + public static final List dummyList = new ArrayList<>(0); + public static final Map> dummyMap = new HashMap<>(0); - public static final CharSequenceTranslator ESCAPE_CHYPER; + + + private static final CharSequenceTranslator ESCAPE_CHYPER; static { final Map escapeJavaMap = new HashMap<>(); escapeJavaMap.put("\'", "\\'"); @@ -28,7 +33,7 @@ public class Utils { * @param str - a string * @return the input string surrounded with quotation marks, if needed */ - public static String quoteString(String str){ + private static String quoteString(String str){ if(str.startsWith("\"") && str.endsWith("\"")){ return str; } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java new file mode 100644 index 0000000..1f33572 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -0,0 +1,59 @@ +package com.redislabs.redisgraph.impl.api; + +import com.redislabs.redisgraph.RedisGraph; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.impl.Utils; +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; +import redis.clients.jedis.Jedis; + +import java.util.List; +import java.util.Map; + +/** + * An abstract class to handle non implementation specific user requests + */ +public abstract class AbstractRedisGraph implements RedisGraph { + + + + /** + * Inherited classes should return a Jedis connection, with respect to their context + * @return Jedis connection + */ + protected abstract Jedis getConnection(); + + /** + * Sends a query to the redis graph. Implementation and context dependent + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @return Result set + */ + protected abstract ResultSet sendQuery(String graphId, String preparedQuery); + + /** + * Execute a Cypher query with arguments + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param args + * @return a result set + */ + public ResultSet query(String graphId, String query, Object ...args) { + String preparedQuery = Utils.prepareQuery(query, args); + return sendQuery(graphId, preparedQuery); + } + + + public ResultSet callProcedure(String graphId, String procedure){ + return callProcedure(graphId, procedure, Utils.dummyList, Utils.dummyMap); + } + + public ResultSet callProcedure(String graphId, String procedure, List args){ + return callProcedure(graphId, procedure, args, Utils.dummyMap); + } + + public ResultSet callProcedure(String graphId, String procedure, List args , Map> kwargs){ + + String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); + return query(graphId, preparedProcedure); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java new file mode 100644 index 0000000..d242503 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -0,0 +1,121 @@ +package com.redislabs.redisgraph.impl.api; + +import com.redislabs.redisgraph.RedisGraphContexted; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; +import redis.clients.jedis.Client; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.util.SafeEncoder; + +import java.util.List; + +/** + * An implementaion of RedisGraphContexted. Allows sending RedisGraph and some Redis commands, + * within a specific connection context + */ +public class ContextedRedisGraph extends AbstractRedisGraph implements RedisGraphContexted, RedisGraphCacheHolder { + + private Jedis connectionContext; + private RedisGraphCaches caches; + + /** + * Generates a new instance with a specific Jedis connection + * @param connectionContext + */ + public ContextedRedisGraph(Jedis connectionContext){ + this.connectionContext = connectionContext; + } + + /** + * Overrides the abstract method. Return the instance only connection + * @return + */ + @Override + protected Jedis getConnection() { + return this.connectionContext; + } + + /** + * Sends the query over the instance only connection + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @return Result set with the query answer + */ + @Override + protected ResultSet sendQuery(String graphId, String preparedQuery) { + Jedis conn = getConnection(); + List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + return new ResultSetImpl(rawResponse, this, graphId, caches.getGraphCache(graphId)); + } + + /** + * @return Returns the instance Jedis connection. + */ + @Override + public Jedis getConnectionContext() { + return this.connectionContext; + } + + /** + * Creates a new RedisGraphTransaction transactional object + * @return new RedisGraphTransaction + */ + @Override + public RedisGraphTransaction multi() { + Jedis jedis = getConnection(); + Client client = jedis.getClient(); + client.multi(); + client.getOne(); + RedisGraphTransaction transaction = new RedisGraphTransaction(client,this); + transaction.setRedisGraphCaches(caches); + return transaction; + } + + /** + * Perfrom watch over given Redis keys + * @param keys + * @return "OK" + */ + @Override + public String watch(String... keys) { + return this.getConnection().watch(keys); + } + + /** + * Removes watch from all keys + * @return + */ + @Override + public String unwatch() { + return this.getConnection().unwatch(); + } + + /** + * Deletes the entire graph + * @param graphId graph to delete + * @return delete running time statistics + */ + @Override + public String deleteGraph(String graphId) { + Object response = getConnection().sendCommand(RedisGraphCommand.DELETE, graphId); + //clear local state + caches.removeGraphCache(graphId); + return SafeEncoder.encode((byte[]) response); + } + + /** + * closes the Jedis connection + */ + @Override + public void close() { + this.connectionContext.close(); + + } + + @Override + public void setRedisGraphCaches(RedisGraphCaches caches) { + this.caches = caches; + } + +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java new file mode 100644 index 0000000..455bab6 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -0,0 +1,113 @@ +package com.redislabs.redisgraph.impl.api; + +import com.redislabs.redisgraph.RedisGraphContexted; +import com.redislabs.redisgraph.RedisGraphGeneralContext; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.util.Pool; +import redis.clients.jedis.util.SafeEncoder; + +import java.util.*; + + + +/** + * + */ +public class RedisGraph extends AbstractRedisGraph implements RedisGraphGeneralContext { + + private final Pool client; + private RedisGraphCaches caches = new RedisGraphCaches(); + + /** + * Creates a client running on the local machine + + */ + public RedisGraph() { + this("localhost", 6379); + } + + /** + * Creates a client running on the specific host/post + * + * @param host Redis host + * @param port Redis port + */ + public RedisGraph(String host, int port) { + this( new JedisPool(host, port)); + } + + /** + * Creates a client using provided Jedis pool + * + * @param jedis bring your own Jedis pool + */ + public RedisGraph( Pool jedis) { + this.client = jedis; + } + + + /** + * Overrides the abstract function. Gets and returns a Jedis connection from the Jedis pool + * @return a Jedis connection + */ + @Override + protected Jedis getConnection() { + return client.getResource(); + } + + /** + * Overrides the abstract function. + * Sends the query from any Jedis connection received from the Jedis pool and closes it once done + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @return Result set with the query answer + */ + @Override + protected ResultSet sendQuery(String graphId, String preparedQuery){ + List rawResponse; + try(Jedis conn = getConnection()){ + rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + } + return new ResultSetImpl(rawResponse, this, graphId, caches.getGraphCache(graphId)); + } + + + /** + * Closes the Jedis pool + */ + @Override + public void close(){ + this.client.close(); + } + + + /** + * Deletes the entire graph + * @param graphId graph to delete + * @return delete running time statistics + */ + @Override + public String deleteGraph(String graphId) { + try (Jedis conn = getConnection()) { + Object response = conn.sendCommand(RedisGraphCommand.DELETE, graphId); + //clear local state + caches.removeGraphCache(graphId); + return SafeEncoder.encode((byte[]) response); + } + } + + /** + * Returns a new ContextedRedisGraph bounded to a Jedis connection from the Jedis pool + * @return ContextedRedisGraph + */ + @Override + public RedisGraphContexted getContextedAPI() { + ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection()); + contextedRedisGraph.setRedisGraphCaches(this.caches); + return contextedRedisGraph; + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCacheHolder.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCacheHolder.java new file mode 100644 index 0000000..97cab72 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCacheHolder.java @@ -0,0 +1,8 @@ +package com.redislabs.redisgraph.impl.api; + +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; + +public interface RedisGraphCacheHolder { + + void setRedisGraphCaches(RedisGraphCaches caches); +} diff --git a/src/main/java/com/redislabs/redisgraph/Command.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java similarity index 68% rename from src/main/java/com/redislabs/redisgraph/Command.java rename to src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java index 35dbd98..3db45d0 100644 --- a/src/main/java/com/redislabs/redisgraph/Command.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java @@ -1,4 +1,4 @@ -package com.redislabs.redisgraph; +package com.redislabs.redisgraph.impl.api; import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.commands.ProtocolCommand; @@ -7,13 +7,13 @@ * * */ -public enum Command implements ProtocolCommand { +public enum RedisGraphCommand implements ProtocolCommand { QUERY("graph.QUERY"), DELETE("graph.DELETE"); private final byte[] raw; - Command(String alt) { + RedisGraphCommand(String alt) { raw = SafeEncoder.encode(alt); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java similarity index 55% rename from src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java rename to src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 5476c6d..786487e 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/JRedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -1,38 +1,33 @@ -package com.redislabs.redisgraph.impl; +package com.redislabs.redisgraph.impl.api; - -import com.redislabs.redisgraph.Command; import com.redislabs.redisgraph.RedisGraph; import com.redislabs.redisgraph.ResultSet; -import com.redislabs.redisgraph.Utils; -import com.redislabs.redisgraph.impl.graph_cache.GraphCache; +import com.redislabs.redisgraph.impl.Utils; +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.Client; -import redis.clients.jedis.Jedis; import redis.clients.jedis.Response; import redis.clients.jedis.Transaction; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; /** * This class is extending Jedis Transaction */ -public class JRedisGraphTransaction extends Transaction { +public class RedisGraphTransaction extends Transaction implements com.redislabs.redisgraph.RedisGraphTransaction, RedisGraphCacheHolder { private final RedisGraph redisGraph; - private final Map graphCaches; + private RedisGraphCaches caches; - public JRedisGraphTransaction(Client client, RedisGraph redisGraph, Map graphCaches){ + public RedisGraphTransaction(Client client, RedisGraph redisGraph){ // init as in Jedis super(client); this.redisGraph = redisGraph; - this.graphCaches = graphCaches; } /** @@ -43,14 +38,13 @@ public JRedisGraphTransaction(Client client, RedisGraph redisGraph, Map graphQuery(String graphId, String query, Object ...args){ + public Response query(String graphId, String query, Object ...args){ String preparedQuery = Utils.prepareQuery(query, args); - graphCaches.putIfAbsent(graphId, new GraphCache(graphId, redisGraph)); - client.sendCommand(Command.QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); return getResponse(new Builder() { @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, graphCaches.get(graphId)); + return new ResultSetImpl((List)o, redisGraph, graphId, caches.getGraphCache(graphId)); } }); } @@ -62,8 +56,8 @@ public ResultSet build(Object o) { * @param procedure procedure name to invoke * @return response with result set with the procedure data */ - public Response graphCallProcedure(String graphId, String procedure){ - return graphCallProcedure(graphId, procedure, new ArrayList<>(), new HashMap<>()); + public Response callProcedure(String graphId, String procedure){ + return callProcedure(graphId, procedure, Utils.dummyList, Utils.dummyMap); } /** @@ -73,8 +67,8 @@ public Response graphCallProcedure(String graphId, String procedure){ * @param args procedure arguments * @return response with result set with the procedure data */ - public Response graphCallProcedure(String graphId, String procedure, List args ){ - return graphCallProcedure(graphId, procedure, args, new HashMap<>()); + public Response callProcedure(String graphId, String procedure, List args ){ + return callProcedure(graphId, procedure, args, Utils.dummyMap); } @@ -86,10 +80,10 @@ public Response graphCallProcedure(String graphId, String procedure, * @param kwargs - procedure output arguments * @return response with result set with the procedure data */ - public Response graphCallProcedure(String graphId, String procedure, List args, - HashMap> kwargs) { + public Response callProcedure(String graphId, String procedure, List args, + Map> kwargs) { String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); - return graphQuery(graphId, preparedProcedure); + return query(graphId, preparedProcedure); } @@ -98,9 +92,17 @@ public Response graphCallProcedure(String graphId, String procedure, * @param graphId graph to delete * @return response with the deletion running time statistics */ - public Response graphDeleteGraph(String graphId){ - graphCaches.remove(graphId); - client.sendCommand(Command.DELETE, graphId); - return getResponse(BuilderFactory.STRING); + public Response deleteGraph(String graphId){ + + client.sendCommand(RedisGraphCommand.DELETE, graphId); + Response response = getResponse(BuilderFactory.STRING); + caches.removeGraphCache(graphId); + return response; } + + @Override + public void setRedisGraphCaches(RedisGraphCaches caches) { + this.caches = caches; + } + } diff --git a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCache.java b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCache.java index 765dff8..565c916 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCache.java +++ b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCache.java @@ -15,36 +15,35 @@ public class GraphCache { /** * * @param graphId - graph Id - * @param redisGraph - a client to use in the cache, for re-validate it by calling procedures */ - public GraphCache(String graphId, RedisGraph redisGraph) { - this.labels = new GraphCacheList(graphId, "db.labels", redisGraph); - this.propertyNames = new GraphCacheList(graphId, "db.propertyKeys", redisGraph); - this.relationshipTypes = new GraphCacheList(graphId, "db.relationshipTypes", redisGraph); + public GraphCache(String graphId) { + this.labels = new GraphCacheList(graphId, "db.labels"); + this.propertyNames = new GraphCacheList(graphId, "db.propertyKeys"); + this.relationshipTypes = new GraphCacheList(graphId, "db.relationshipTypes"); } /** * @param index - index of label * @return requested label */ - public String getLabel(int index) { - return labels.getCachedData(index); + public String getLabel(int index, RedisGraph redisGraph) { + return labels.getCachedData(index, redisGraph); } /** * @param index index of the relationship type * @return requested relationship type */ - public String getRelationshipType(int index) { - return relationshipTypes.getCachedData(index); + public String getRelationshipType(int index, RedisGraph redisGraph) { + return relationshipTypes.getCachedData(index, redisGraph); } /** * @param index index of property name * @return requested property */ - public String getPropertyName(int index) { + public String getPropertyName(int index, RedisGraph redisGraph) { - return propertyNames.getCachedData(index); + return propertyNames.getCachedData(index, redisGraph); } } diff --git a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java index d608f16..7855931 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java +++ b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java @@ -7,17 +7,16 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * Represents a local cache of list of strings. Holds data from a specific procedure, for a specific graph. */ -public class GraphCacheList { +class GraphCacheList { - private Object mutex = new Object(); + private final Object mutex = new Object(); private final String graphId; private final String procedure; - private final RedisGraph redisGraph; private final List data = new CopyOnWriteArrayList<>(); @@ -26,12 +25,10 @@ public class GraphCacheList { * * @param graphId - graph id * @param procedure - exact procedure command - * @param redisGraph - a client to use in the cache, for re-validate it by calling procedures */ - public GraphCacheList(String graphId, String procedure, RedisGraph redisGraph) { + public GraphCacheList(String graphId, String procedure) { this.graphId = graphId; this.procedure = procedure; - this.redisGraph = redisGraph; } @@ -40,23 +37,22 @@ public GraphCacheList(String graphId, String procedure, RedisGraph redisGraph) { * @param index index of data item * @return The string value of the specific procedure response, at the given index. */ - public String getCachedData(int index) { + public String getCachedData(int index, RedisGraph redisGraph) { if (index >= data.size()) { synchronized (mutex){ if (index >= data.size()) { - getProcedureInfo(); + getProcedureInfo(redisGraph); } } } - String s = data.get(index); - return s; + return data.get(index); } /** * Auxiliary method to parse a procedure result set and refresh the cache */ - private void getProcedureInfo() { + private void getProcedureInfo(RedisGraph redisGraph) { ResultSet resultSet = redisGraph.callProcedure(graphId, procedure); List newData = new ArrayList<>(); int i = 0; diff --git a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/RedisGraphCaches.java b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/RedisGraphCaches.java new file mode 100644 index 0000000..528ed34 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/RedisGraphCaches.java @@ -0,0 +1,59 @@ +package com.redislabs.redisgraph.impl.graph_cache; + +import com.redislabs.redisgraph.RedisGraph; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class RedisGraphCaches { + + private final Map graphCaches = new ConcurrentHashMap<>(); + + public GraphCache getGraphCache(String graphId){ + if (!graphCaches.containsKey(graphId)){ + graphCaches.putIfAbsent(graphId, new GraphCache(graphId)); + } + return graphCaches.get(graphId); + } + + /** + * Returns a String which represents the name of the label mapped to the label id + * @param graphId graph to perform the query + * @param index label index + * @param redisGraph RedisGraphAPI implementation + * @return label name + */ + public String getLabel(String graphId, int index, RedisGraph redisGraph) { + return getGraphCache(graphId).getLabel(index, redisGraph); + } + + /** + * Returns a String which represents the name of the relationship mapped to the label id + * @param graphId graph to perform the query + * @param index relationship index + * @param redisGraph RedisGraphAPI implementation + * @return relationship name + */ + public String getRelationshipType(String graphId, int index, RedisGraph redisGraph){ + return getGraphCache(graphId).getRelationshipType(index, redisGraph); + } + + /** + * Returns a String which represents the name of the property mapped to the label id + * @param graphId graph to perform the query + * @param index property index + * @param redisGraph RedisGraphAPI implementation + * @return property name + */ + public String getPropertyName(String graphId, int index, RedisGraph redisGraph){ + return getGraphCache(graphId).getPropertyName(index, redisGraph); + } + + /** + * Removes a graph meta data cache + * @param graphId + */ + public void removeGraphCache(String graphId){ + graphCaches.remove(graphId); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/HeaderImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java similarity index 98% rename from src/main/java/com/redislabs/redisgraph/impl/HeaderImpl.java rename to src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java index 2a7a40f..a9ae068 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/HeaderImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java @@ -1,4 +1,4 @@ -package com.redislabs.redisgraph.impl; +package com.redislabs.redisgraph.impl.resultset; import com.redislabs.redisgraph.Header; import redis.clients.jedis.util.SafeEncoder; diff --git a/src/main/java/com/redislabs/redisgraph/impl/RecordImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java similarity index 97% rename from src/main/java/com/redislabs/redisgraph/impl/RecordImpl.java rename to src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java index 8aca26c..adf68ad 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/RecordImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java @@ -1,4 +1,4 @@ -package com.redislabs.redisgraph.impl; +package com.redislabs.redisgraph.impl.resultset; import java.util.List; import java.util.Objects; diff --git a/src/main/java/com/redislabs/redisgraph/impl/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java similarity index 88% rename from src/main/java/com/redislabs/redisgraph/impl/ResultSetImpl.java rename to src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 9cfc5b8..ec74ec9 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -1,4 +1,4 @@ -package com.redislabs.redisgraph.impl; +package com.redislabs.redisgraph.impl.resultset; import com.redislabs.redisgraph.*; import com.redislabs.redisgraph.graph_entities.Edge; @@ -6,6 +6,7 @@ import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import redis.clients.jedis.util.SafeEncoder; import java.util.ArrayList; @@ -20,15 +21,19 @@ public class ResultSetImpl implements ResultSet { private final List results ; private int position = 0; - private final GraphCache graphCache; + private final RedisGraph redisGraph; + private final String graphId; + private final GraphCache cache; /** * @param rawResponse the raw representation of response is at most 3 lists of objects. * The last list is the statistics list. - * @param graphCache, the graph local cache + * @param redisGraph, the graph local cache */ - public ResultSetImpl(List rawResponse, GraphCache graphCache) { - this.graphCache = graphCache; + public ResultSetImpl(List rawResponse, RedisGraph redisGraph, String graphId, GraphCache cache) { + this.redisGraph = redisGraph; + this.graphId = graphId; + this.cache = cache; if (rawResponse.size() != 3) { header = parseHeader(new ArrayList<>()); @@ -40,7 +45,7 @@ public ResultSetImpl(List rawResponse, GraphCache graphCache) { header = parseHeader((List>) rawResponse.get(0)); results = parseResult((List>) rawResponse.get(1)); - statistics = parseStatistics((List) rawResponse.get(2)); + statistics = parseStatistics(rawResponse.get(2)); } } @@ -130,7 +135,7 @@ private Node deserializeNode(List rawNodeData) { deserializeGraphEntityId(node, rawNodeData.get(0)); List labelsIndices = (List) rawNodeData.get(1); for (long labelIndex : labelsIndices) { - String label = graphCache.getLabel((int) labelIndex); + String label = cache.getLabel((int) labelIndex, redisGraph); node.addLabel(label); } deserializeGraphEntityProperties(node, (List>) rawNodeData.get(2)); @@ -162,7 +167,8 @@ private Edge deserializeEdge(List rawEdgeData) { Edge edge = new Edge(); deserializeGraphEntityId(edge, rawEdgeData.get(0)); - String relationshipType = graphCache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue()); + String relationshipType = cache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue(), + redisGraph); edge.setRelationshipType(relationshipType); edge.setSource((int) (long) rawEdgeData.get(2)); @@ -181,12 +187,13 @@ private Edge deserializeEdge(List rawEdgeData) { * rawProperty.get(1) - property type * rawProperty.get(2) - property value */ - void deserializeGraphEntityProperties(GraphEntity entity, List> rawProperties) { + private void deserializeGraphEntityProperties(GraphEntity entity, List> rawProperties) { for (List rawProperty : rawProperties) { Property property = new Property(); - property.setName(graphCache.getPropertyName(((Long) rawProperty.get(0)).intValue())); + property.setName(cache.getPropertyName(((Long) rawProperty.get(0)).intValue(), + redisGraph)); //trimmed for getting to value using deserializeScalar List propertyScalar = rawProperty.subList(1, rawProperty.size()); @@ -214,7 +221,7 @@ private Object deserializeScalar(List rawScalarData) { case PROPERTY_DOUBLE: return Double.parseDouble(SafeEncoder.encode((byte[]) obj)); case PROPERTY_INTEGER: - return (Integer) ((Long) obj).intValue(); + return ((Long) obj).intValue(); case PROPERTY_STRING: return SafeEncoder.encode((byte[]) obj); case PROPERTY_UNKNOWN: diff --git a/src/main/java/com/redislabs/redisgraph/impl/StatisticsImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java similarity index 93% rename from src/main/java/com/redislabs/redisgraph/impl/StatisticsImpl.java rename to src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java index 68887e1..a6b24af 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/StatisticsImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java @@ -1,4 +1,4 @@ -package com.redislabs.redisgraph.impl; +package com.redislabs.redisgraph.impl.resultset; import java.util.EnumMap; import java.util.List; @@ -18,7 +18,7 @@ public class StatisticsImpl implements Statistics { private final Map statistics; /** - * A raw representation of query exection statistics is a list of strings + * A raw representation of query execution statistics is a list of strings * (byte arrays which need to be de-serialized). * Each string is built in the form of "K:V" where K is statistics label and V is its value. * @param raw a raw representation of the query execution statistics @@ -95,7 +95,7 @@ public int indicesAdded() { /** * - * @return number of lables added after query execution + * @return number of labels added after query execution */ @Override public int labelsAdded() { @@ -134,7 +134,7 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof StatisticsImpl)) return false; StatisticsImpl that = (StatisticsImpl) o; - return Objects.equals(raw, raw) && + return Objects.equals(raw, that.raw) && Objects.equals(getStatistics(), that.getStatistics()); } diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index d8a6374..6c5514e 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -1,6 +1,7 @@ package com.redislabs.redisgraph; +import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; @@ -10,8 +11,8 @@ import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; -import com.redislabs.redisgraph.impl.JRedisGraphTransaction; -import com.redislabs.redisgraph.impl.ResultSetImpl; +import com.redislabs.redisgraph.impl.api.RedisGraph; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -22,7 +23,7 @@ import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; public class RedisGraphAPITest { - RedisGraph api; + private RedisGraphGeneralContext api; public RedisGraphAPITest() { } @@ -35,11 +36,14 @@ public void createApi(){ public void deleteGraph() { api.deleteGraph("social"); - api.close(); + try { + api.close(); + } catch (IOException e) { + e.printStackTrace(); + } } - @Test public void testCreateNode() { // Create a node @@ -59,7 +63,7 @@ public void testCreateNode() { try { resultSet.next(); Assert.fail(); - } catch (NoSuchElementException e) { + } catch (NoSuchElementException ignored) { } } @@ -500,16 +504,16 @@ public void testEscapedQuery() { @Test public void testMultiExec(){ - JRedisGraphTransaction transaction = api.multi(); + RedisGraphTransaction transaction = api.getContextedAPI().multi(); transaction.set("x", "1"); - transaction.graphQuery("social", "CREATE (:Person {name:'a'})"); - transaction.graphQuery("g", "CREATE (:Person {name:'a'})"); + transaction.query("social", "CREATE (:Person {name:'a'})"); + transaction.query("g", "CREATE (:Person {name:'a'})"); transaction.incr("x"); transaction.get("x"); - transaction.graphQuery("social", "MATCH (n:Person) RETURN n"); - transaction.graphDeleteGraph("g"); - transaction.graphCallProcedure("social", "db.labels"); + transaction.query("social", "MATCH (n:Person) RETURN n"); + transaction.deleteGraph("g"); + transaction.callProcedure("social", "db.labels"); List results = transaction.exec(); // Redis set command @@ -603,4 +607,169 @@ record = resultSet.next(); Assert.assertEquals("Person", record.getValue("label")); } + + @Test + public void testContextedAPI(){ + + String name = "roi"; + int age = 32; + double doubleValue = 3.14; + boolean boolValue = true; + + String place = "TLV"; + int since = 2000; + + + + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.PROPERTY_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.PROPERTY_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.PROPERTY_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.PROPERTY_NULL, null); + + Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, since); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("person"); + expectedNode.addProperty(nameProperty); + expectedNode.addProperty(ageProperty); + expectedNode.addProperty(doubleProperty); + expectedNode.addProperty(trueBooleanProperty); + expectedNode.addProperty(nullProperty); + + Edge expectedEdge = new Edge(); + expectedEdge.setId(0); + expectedEdge.setSource(0); + expectedEdge.setDestination(1); + expectedEdge.setRelationshipType("knows"); + expectedEdge.addProperty(placeProperty); + expectedEdge.addProperty(sinceProperty); + expectedEdge.addProperty(doubleProperty); + expectedEdge.addProperty(falseBooleanProperty); + expectedEdge.addProperty(nullProperty); + + RedisGraphContexted c = api.getContextedAPI(); + + Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); + Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); + + ResultSet resultSet = c.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + + "a.name, a.age, a.doubleValue, a.boolValue, a.nullValue, " + + "r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); + Assert.assertNotNull(resultSet); + + + Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(0, resultSet.getStatistics().nodesDeleted()); + Assert.assertEquals(0, resultSet.getStatistics().labelsAdded()); + Assert.assertEquals(0, resultSet.getStatistics().propertiesSet()); + Assert.assertEquals(0, resultSet.getStatistics().relationshipsCreated()); + Assert.assertEquals(0, resultSet.getStatistics().relationshipsDeleted()); + Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); + + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + + Node node = record.getValue(0); + Assert.assertNotNull(node); + + Assert.assertEquals(expectedNode, node); + + node = record.getValue("a"); + Assert.assertEquals(expectedNode, node); + + Edge edge = record.getValue(1); + Assert.assertNotNull(edge); + Assert.assertEquals(expectedEdge, edge); + + edge = record.getValue("r"); + Assert.assertEquals(expectedEdge, edge); + + Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", "a.nullValue", + "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); + + Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, + name, age, doubleValue, true, null, + place, since, doubleValue, false, null), + record.values()); + + Node a = record.getValue("a"); + for (String propertyName : expectedNode.getEntityPropertyNames()){ + Assert.assertEquals(expectedNode.getProperty(propertyName) ,a.getProperty(propertyName)); + } + + Assert.assertEquals( "roi", record.getString(2)); + Assert.assertEquals( "32", record.getString(3)); + Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); + Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); + Assert.assertEquals( "roi", record.getString("a.name")); + Assert.assertEquals( "32", record.getString("a.age")); + + + } + + @Test + public void testWriteTransactionWatch(){ + + RedisGraphContexted c1 = api.getContextedAPI(); + RedisGraphContexted c2 = api.getContextedAPI(); + + c1.watch("social"); + RedisGraphTransaction t1 = c1.multi(); + + + t1.query("social", "CREATE (:Person {name:'a'})"); + c2.query("social", "CREATE (:Person {name:'b'})"); + List returnValue = t1.exec(); + Assert.assertNull(returnValue); + + try { + c1.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + c2.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + @Test + public void testReadTransactionWatch(){ + + RedisGraphContexted c1 = api.getContextedAPI(); + RedisGraphContexted c2 = api.getContextedAPI(); + Assert.assertNotEquals(c1.getConnectionContext(), c2.getConnectionContext()); + c1.query("social", "CREATE (:Person {name:'a'})"); + c1.watch("social"); + RedisGraphTransaction t1 = c1.multi(); + + t1.query("social", "CREATE (:Person {name:'b'})"); + c2.query("social", "MATCH (n) return n"); + List returnValue = t1.exec(); + + Assert.assertNotNull(returnValue); + + try { + c1.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + c2.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } } From 39092e0d13128ad04c7436950ce38487f2d5103f Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 21 Jul 2019 13:37:06 +0300 Subject: [PATCH 006/128] fixed according to PR. changed connection to context connection even in general queries --- pom.xml | 2 +- src/main/java/META-INF/MANIFEST.MF | 6 +++--- .../graph_entities/GraphEntity.java | 4 ++-- .../com/redislabs/redisgraph/impl/Utils.java | 18 +++++++++++++++-- .../impl/api/ContextedRedisGraph.java | 20 +++++++++++++++++-- .../redisgraph/impl/api/RedisGraph.java | 8 ++++---- .../impl/graph_cache/GraphCacheList.java | 5 +---- 7 files changed, 45 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index a83a43c..53bcd96 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ redis.clients jedis - 3.1.0-m4 + 3.1.0-rc org.apache.commons diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF index 425ebf5..7356ba4 100644 --- a/src/main/java/META-INF/MANIFEST.MF +++ b/src/main/java/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -Main-Class: com.redislabs.redisgraph.RedisGraphAPI - +Manifest-Version: 1.0 +Main-Class: com.redislabs.redisgraph.RedisGraph + diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index 42cc3f9..d2083a6 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -16,8 +16,8 @@ public abstract class GraphEntity { //members - int id; - final Map propertyMap = new HashMap<>(); + protected int id; + protected final Map propertyMap = new HashMap<>(); //setters & getters diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index b9d1873..2d0b42c 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -17,6 +17,7 @@ public class Utils { public static final List dummyList = new ArrayList<>(0); public static final Map> dummyMap = new HashMap<>(0); + public static final String compactString = "--COMPACT"; @@ -77,10 +78,23 @@ public static String prepareQuery(String query, Object ...args){ public static String prepareProcedure(String procedure, List args , Map> kwargs){ args = args.stream().map( s -> Utils.quoteString(s)).collect(Collectors.toList()); StringBuilder queryStringBuilder = new StringBuilder(); - queryStringBuilder.append(String.format("CALL %s(%s)", procedure, String.join(",", args))); + queryStringBuilder.append("CALL ").append(procedure).append("("); + int i = 0; + for (; i < args.size() - 1; i++) { + queryStringBuilder.append(args.get(i)).append(","); + } + if (i == args.size()-1) { + queryStringBuilder.append(args.get(i)); + } + queryStringBuilder.append(")"); List kwargsList = kwargs.getOrDefault("y", null); if(kwargsList != null){ - queryStringBuilder.append(String.join(",", kwargsList)); + i = 0; + for (; i < kwargsList.size() - 1; i++) { + queryStringBuilder.append(kwargsList.get(i)).append(","); + + } + queryStringBuilder.append(kwargsList.get(i)); } return queryStringBuilder.toString(); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index d242503..bbe7d27 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -2,6 +2,7 @@ import com.redislabs.redisgraph.RedisGraphContexted; import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Client; @@ -45,7 +46,14 @@ protected Jedis getConnection() { @Override protected ResultSet sendQuery(String graphId, String preparedQuery) { Jedis conn = getConnection(); - List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + List rawResponse; + try { + rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.compactString); + } + catch (Exception e) { + conn.close(); + throw e; + } return new ResultSetImpl(rawResponse, this, graphId, caches.getGraphCache(graphId)); } @@ -98,7 +106,15 @@ public String unwatch() { */ @Override public String deleteGraph(String graphId) { - Object response = getConnection().sendCommand(RedisGraphCommand.DELETE, graphId); + Jedis conn = getConnection(); + Object response; + try { + response = conn.sendCommand(RedisGraphCommand.DELETE, graphId); + } + catch (Exception e) { + conn.close(); + throw e; + } //clear local state caches.removeGraphCache(graphId); return SafeEncoder.encode((byte[]) response); diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index 455bab6..ae23b82 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -3,6 +3,7 @@ import com.redislabs.redisgraph.RedisGraphContexted; import com.redislabs.redisgraph.RedisGraphGeneralContext; import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Jedis; @@ -68,11 +69,10 @@ protected Jedis getConnection() { */ @Override protected ResultSet sendQuery(String graphId, String preparedQuery){ - List rawResponse; - try(Jedis conn = getConnection()){ - rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + try (ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection())) { + contextedRedisGraph.setRedisGraphCaches(caches); + return contextedRedisGraph.sendQuery(graphId, preparedQuery); } - return new ResultSetImpl(rawResponse, this, graphId, caches.getGraphCache(graphId)); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java index 7855931..55035d1 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java +++ b/src/main/java/com/redislabs/redisgraph/impl/graph_cache/GraphCacheList.java @@ -14,13 +14,10 @@ */ class GraphCacheList { - private final Object mutex = new Object(); private final String graphId; private final String procedure; private final List data = new CopyOnWriteArrayList<>(); - - /** * * @param graphId - graph id @@ -39,7 +36,7 @@ public GraphCacheList(String graphId, String procedure) { */ public String getCachedData(int index, RedisGraph redisGraph) { if (index >= data.size()) { - synchronized (mutex){ + synchronized (data){ if (index >= data.size()) { getProcedureInfo(redisGraph); } From 0be41a8631e3faa087e9538127d0756b13fd9db2 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 22 Jul 2019 11:42:13 +0300 Subject: [PATCH 007/128] add some code cleanups --- .../redisgraph/RedisGraphGeneralContext.java | 2 -- .../redisgraph/impl/api/AbstractRedisGraph.java | 1 - .../redislabs/redisgraph/impl/api/RedisGraph.java | 6 ------ .../redisgraph/impl/resultset/ResultSetImpl.java | 15 +++++---------- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java b/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java index 4596ec9..cdf218a 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java @@ -1,7 +1,5 @@ package com.redislabs.redisgraph; -import redis.clients.jedis.Jedis; - public interface RedisGraphGeneralContext extends RedisGraph { /** diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java index 1f33572..3337fcd 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -3,7 +3,6 @@ import com.redislabs.redisgraph.RedisGraph; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.impl.Utils; -import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import redis.clients.jedis.Jedis; import java.util.List; diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index ae23b82..900e32c 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -3,18 +3,12 @@ import com.redislabs.redisgraph.RedisGraphContexted; import com.redislabs.redisgraph.RedisGraphGeneralContext; import com.redislabs.redisgraph.ResultSet; -import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; -import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.util.Pool; import redis.clients.jedis.util.SafeEncoder; -import java.util.*; - - - /** * */ diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index ec74ec9..ff2a9c9 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -6,7 +6,6 @@ import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; -import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import redis.clients.jedis.util.SafeEncoder; import java.util.ArrayList; @@ -22,7 +21,6 @@ public class ResultSetImpl implements ResultSet { private int position = 0; private final RedisGraph redisGraph; - private final String graphId; private final GraphCache cache; /** @@ -30,9 +28,8 @@ public class ResultSetImpl implements ResultSet { * The last list is the statistics list. * @param redisGraph, the graph local cache */ - public ResultSetImpl(List rawResponse, RedisGraph redisGraph, String graphId, GraphCache cache) { + public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache cache) { this.redisGraph = redisGraph; - this.graphId = graphId; this.cache = cache; if (rawResponse.size() != 3) { @@ -78,10 +75,8 @@ private List parseResult(List> rawResultSet) { case COLUMN_RELATION: parsedRow.add(deserializeEdge(obj)); break; - case COLUMN_SCALAR: { + case COLUMN_SCALAR: parsedRow.add(deserializeScalar(obj)); - - } } } @@ -134,8 +129,8 @@ private Node deserializeNode(List rawNodeData) { Node node = new Node(); deserializeGraphEntityId(node, rawNodeData.get(0)); List labelsIndices = (List) rawNodeData.get(1); - for (long labelIndex : labelsIndices) { - String label = cache.getLabel((int) labelIndex, redisGraph); + for (Long labelIndex : labelsIndices) { + String label = cache.getLabel(labelIndex.intValue(), redisGraph); node.addLabel(label); } deserializeGraphEntityProperties(node, (List>) rawNodeData.get(2)); @@ -149,7 +144,7 @@ private Node deserializeNode(List rawNodeData) { * @param rawEntityId raw representation of entity id to be set to the graph entity */ private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityId) { - int id = (int) (long) rawEntityId; + int id = ((Long) rawEntityId).intValue(); graphEntity.setId(id); } From 2b82bac58089c43b7984712241aeff28b4e71edd Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Mon, 22 Jul 2019 11:46:20 +0300 Subject: [PATCH 008/128] fixed according to PR --- pom.xml | 10 +++++----- .../redisgraph/impl/api/ContextedRedisGraph.java | 2 +- .../redislabs/redisgraph/impl/api/RedisGraph.java | 5 ----- .../redisgraph/impl/api/RedisGraphTransaction.java | 2 +- .../redisgraph/impl/resultset/ResultSetImpl.java | 12 +++++++----- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/pom.xml b/pom.xml index 53bcd96..c99fd63 100644 --- a/pom.xml +++ b/pom.xml @@ -77,10 +77,10 @@ - 8 - 8 - 8 - 8 + 10 + 10 + 10 + 10 @@ -179,7 +179,7 @@ org.apache.maven.plugins maven-pmd-plugin - 3.11.0 + 3.12.0 diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index bbe7d27..bdf69c9 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -54,7 +54,7 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { conn.close(); throw e; } - return new ResultSetImpl(rawResponse, this, graphId, caches.getGraphCache(graphId)); + return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } /** diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index ae23b82..66b20f9 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -3,17 +3,12 @@ import com.redislabs.redisgraph.RedisGraphContexted; import com.redislabs.redisgraph.RedisGraphGeneralContext; import com.redislabs.redisgraph.ResultSet; -import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; -import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.util.Pool; import redis.clients.jedis.util.SafeEncoder; -import java.util.*; - - /** * diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 786487e..91c96e8 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -44,7 +44,7 @@ public Response query(String graphId, String query, Object ...args){ return getResponse(new Builder() { @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, graphId, caches.getGraphCache(graphId)); + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); } }); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index ec74ec9..429ab3a 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -6,7 +6,6 @@ import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; -import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import redis.clients.jedis.util.SafeEncoder; import java.util.ArrayList; @@ -22,7 +21,6 @@ public class ResultSetImpl implements ResultSet { private int position = 0; private final RedisGraph redisGraph; - private final String graphId; private final GraphCache cache; /** @@ -30,9 +28,8 @@ public class ResultSetImpl implements ResultSet { * The last list is the statistics list. * @param redisGraph, the graph local cache */ - public ResultSetImpl(List rawResponse, RedisGraph redisGraph, String graphId, GraphCache cache) { + public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache cache) { this.redisGraph = redisGraph; - this.graphId = graphId; this.cache = cache; if (rawResponse.size() != 3) { @@ -80,8 +77,13 @@ private List parseResult(List> rawResultSet) { break; case COLUMN_SCALAR: { parsedRow.add(deserializeScalar(obj)); - + break; } + default: { + parsedRow.add(null); + break; + } + } } From 79c5dc58b82a9e093b51adcdd02d10d16580481b Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 22 Jul 2019 11:52:20 +0300 Subject: [PATCH 009/128] clean code --- .../com/redislabs/redisgraph/graph_entities/Node.java | 4 ++-- src/main/java/com/redislabs/redisgraph/impl/Utils.java | 10 +++++----- .../redisgraph/impl/api/AbstractRedisGraph.java | 4 ++-- .../redisgraph/impl/api/ContextedRedisGraph.java | 4 ++-- .../redisgraph/impl/api/RedisGraphTransaction.java | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java index f118964..91b9a4f 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java @@ -10,7 +10,7 @@ public class Node extends GraphEntity { //members - final private List labels = new ArrayList<>(); + private final List labels = new ArrayList<>(); /** * @param label - a label to be add @@ -32,7 +32,7 @@ public void removeLabel(String label) { * @throws IndexOutOfBoundsException if the index is out of range * ({@code index < 0 || index >= getNumberOfLabels()}) */ - public String getLabel(int index) throws IndexOutOfBoundsException{ + public String getLabel(int index){ return labels.get(index); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index 2d0b42c..bb39c5b 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -15,11 +15,9 @@ * Utilities class */ public class Utils { - public static final List dummyList = new ArrayList<>(0); - public static final Map> dummyMap = new HashMap<>(0); - public static final String compactString = "--COMPACT"; - - + public static final List DUMMY_LIST = new ArrayList<>(0); + public static final Map> DUMMY_MAP = new HashMap<>(0); + public static final String COMPACT_STRING = "--COMPACT"; private static final CharSequenceTranslator ESCAPE_CHYPER; static { @@ -28,6 +26,8 @@ public class Utils { escapeJavaMap.put("\"", "\\\""); ESCAPE_CHYPER = new AggregateTranslator(new LookupTranslator(Collections.unmodifiableMap(escapeJavaMap))); } + + private Utils() {} /** * diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java index 3337fcd..d659b22 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -43,11 +43,11 @@ public ResultSet query(String graphId, String query, Object ...args) { public ResultSet callProcedure(String graphId, String procedure){ - return callProcedure(graphId, procedure, Utils.dummyList, Utils.dummyMap); + return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); } public ResultSet callProcedure(String graphId, String procedure, List args){ - return callProcedure(graphId, procedure, args, Utils.dummyMap); + return callProcedure(graphId, procedure, args, Utils.DUMMY_MAP); } public ResultSet callProcedure(String graphId, String procedure, List args , Map> kwargs){ diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index bbe7d27..a1fa081 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -48,13 +48,13 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { Jedis conn = getConnection(); List rawResponse; try { - rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.compactString); + rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); } catch (Exception e) { conn.close(); throw e; } - return new ResultSetImpl(rawResponse, this, graphId, caches.getGraphCache(graphId)); + return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } /** diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 786487e..21f2a5d 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -57,7 +57,7 @@ public ResultSet build(Object o) { * @return response with result set with the procedure data */ public Response callProcedure(String graphId, String procedure){ - return callProcedure(graphId, procedure, Utils.dummyList, Utils.dummyMap); + return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); } /** @@ -68,7 +68,7 @@ public Response callProcedure(String graphId, String procedure){ * @return response with result set with the procedure data */ public Response callProcedure(String graphId, String procedure, List args ){ - return callProcedure(graphId, procedure, args, Utils.dummyMap); + return callProcedure(graphId, procedure, args, Utils.DUMMY_MAP); } From c979990950976dffc32ab8ddcd30ebb3f76d77c4 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 23 Jul 2019 10:58:11 +0300 Subject: [PATCH 010/128] changed Jedis Version. Minor code fix in ContextedRedisGraph --- pom.xml | 2 +- .../redislabs/redisgraph/impl/api/ContextedRedisGraph.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2f205cd..2b2c133 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ redis.clients jedis - 3.1.0-rc + 3.1.0 org.apache.commons diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index a1fa081..b2fe9f6 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -46,15 +46,14 @@ protected Jedis getConnection() { @Override protected ResultSet sendQuery(String graphId, String preparedQuery) { Jedis conn = getConnection(); - List rawResponse; try { - rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); + List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); + return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } catch (Exception e) { conn.close(); throw e; } - return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } /** From 19053508c207320216efe0f3ef23b36caa7ad8fd Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 23 Jul 2019 11:11:51 +0300 Subject: [PATCH 011/128] Update README.md --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8ae38a7..07bb588 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![license](https://img.shields.io/github/license/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph) +[![GitHub issues](https://img.shields.io/github/release/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph/releases/latest) [![CircleCI](https://circleci.com/gh/RedisGraph/JRedisGraph/tree/master.svg?style=svg)](https://circleci.com/gh/RedisGraph/JRedisGraph/tree/master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph) -[![GitHub issues](https://img.shields.io/github/release/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph/releases/latest) [![Javadocs](https://www.javadoc.io/badge/com.redislabs/jredisgraph.svg)](https://www.javadoc.io/doc/com.redislabs/jredisgraph) [![Codecov](https://codecov.io/gh/RedisGraph/JRedisGraph/branch/master/graph/badge.svg)](https://codecov.io/gh/RedisGraph/JRedisGraph) @@ -16,7 +16,17 @@ RedisGraph Java client com.redislabs jredisgraph - 1.0.4 + 1.0.6 + + + +Or + + + + com.redislabs + jredisgraph + 2.0.0-rc1 ``` From c9f06dfed01bfc9e3291410811135a36472ef2d6 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 23 Jul 2019 11:42:06 +0300 Subject: [PATCH 012/128] changed readme.md --- README.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 07bb588..1c2e177 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ and ``` # Example: Using the Java Client - +## Up to 2.0.0 ```java package com.redislabs.redisgraph; @@ -80,3 +80,59 @@ public class RedisGraphExample { } ``` +## From 2.0.0 + +```java +package com.redislabs.redisgraph; + +import com.redislabs.redisgraph.graph_entities.Edge; +import com.redislabs.redisgraph.graph_entities.Node; +import com.redislabs.redisgraph.impl.api.RedisGraph; + +import java.util.List; + +public class RedisGraphExample { + public static void main(String[] args) { + // general context api. Not bound to graph key or connection + RedisGraphGeneralContext api = new RedisGraph(); + + // send queries to a specific graph called "social" + api.query("social","CREATE (:person{name:'roi',age:32})"); + api.query("social","CREATE (:person{name:%s,age:%d})", "amit", 30); + api.query("social","MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); + + ResultSet resultSet = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); + while(resultSet.hasNext()) { + Record record = resultSet.next(); + // get values + Node a = record.getValue("a"); + Edge r = record.getValue("r"); + + //print record + System.out.println(record.toString()); + } + + // delete graph + api.deleteGraph("social"); + + // get connection context + RedisGraphContexted contextApi = api.getContextedAPI(); + contextApi.query("contextSocial","CREATE (:person{name:'roi',age:32})"); + contextApi.query("contextSocial","CREATE (:person{name:%s,age:%d})", "amit", 30); + contextApi.query("contextSocial", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); + // WATCH/MULTI/EXEC + contextApi.watch("contextSocial"); + RedisGraphTransaction t = contextApi.multi(); + t.query("contextSocial", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); + // support for Redis/Jedis native commands in transaction + t.set("x", "1"); + t.get("x"); + // get multi/exec results + List execResults = t.exec(); + System.out.println(execResults.toString()); + + contextApi.deleteGraph("contextSocial"); + } +} + +``` From 1925927de36da16327f270ffbf07aad2646e339f Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 23 Jul 2019 11:52:15 +0300 Subject: [PATCH 013/128] changed readme.md. Renamed classes & interfaces --- README.md | 26 +++++++++---------- ...hContexted.java => RedisGraphContext.java} | 2 +- ...t.java => RedisGraphContextGenerator.java} | 4 +-- .../impl/api/ContextedRedisGraph.java | 6 ++--- .../redisgraph/impl/api/RedisGraph.java | 8 +++--- .../redisgraph/RedisGraphAPITest.java | 14 +++++----- 6 files changed, 30 insertions(+), 30 deletions(-) rename src/main/java/com/redislabs/redisgraph/{RedisGraphContexted.java => RedisGraphContext.java} (92%) rename src/main/java/com/redislabs/redisgraph/{RedisGraphGeneralContext.java => RedisGraphContextGenerator.java} (56%) diff --git a/README.md b/README.md index 1c2e177..1681a55 100644 --- a/README.md +++ b/README.md @@ -94,14 +94,14 @@ import java.util.List; public class RedisGraphExample { public static void main(String[] args) { // general context api. Not bound to graph key or connection - RedisGraphGeneralContext api = new RedisGraph(); + RedisGraph graph = new RedisGraph(); // send queries to a specific graph called "social" - api.query("social","CREATE (:person{name:'roi',age:32})"); - api.query("social","CREATE (:person{name:%s,age:%d})", "amit", 30); - api.query("social","MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); + graph.query("social","CREATE (:person{name:'roi',age:32})"); + graph.query("social","CREATE (:person{name:%s,age:%d})", "amit", 30); + graph.query("social","MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); - ResultSet resultSet = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); + ResultSet resultSet = graph.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); while(resultSet.hasNext()) { Record record = resultSet.next(); // get values @@ -113,16 +113,16 @@ public class RedisGraphExample { } // delete graph - api.deleteGraph("social"); + graph.deleteGraph("social"); // get connection context - RedisGraphContexted contextApi = api.getContextedAPI(); - contextApi.query("contextSocial","CREATE (:person{name:'roi',age:32})"); - contextApi.query("contextSocial","CREATE (:person{name:%s,age:%d})", "amit", 30); - contextApi.query("contextSocial", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); + RedisGraphContext context = graph.getContext(); + context.query("contextSocial","CREATE (:person{name:'roi',age:32})"); + context.query("contextSocial","CREATE (:person{name:%s,age:%d})", "amit", 30); + context.query("contextSocial", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); // WATCH/MULTI/EXEC - contextApi.watch("contextSocial"); - RedisGraphTransaction t = contextApi.multi(); + context.watch("contextSocial"); + RedisGraphTransaction t = context.multi(); t.query("contextSocial", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); // support for Redis/Jedis native commands in transaction t.set("x", "1"); @@ -131,7 +131,7 @@ public class RedisGraphExample { List execResults = t.exec(); System.out.println(execResults.toString()); - contextApi.deleteGraph("contextSocial"); + context.deleteGraph("contextSocial"); } } diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java b/src/main/java/com/redislabs/redisgraph/RedisGraphContext.java similarity index 92% rename from src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java rename to src/main/java/com/redislabs/redisgraph/RedisGraphContext.java index 5ef1037..db2a5e8 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphContexted.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphContext.java @@ -2,7 +2,7 @@ import redis.clients.jedis.Jedis; -public interface RedisGraphContexted extends RedisGraph { +public interface RedisGraphContext extends RedisGraph { /** diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java b/src/main/java/com/redislabs/redisgraph/RedisGraphContextGenerator.java similarity index 56% rename from src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java rename to src/main/java/com/redislabs/redisgraph/RedisGraphContextGenerator.java index cdf218a..fe3718f 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphGeneralContext.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphContextGenerator.java @@ -1,11 +1,11 @@ package com.redislabs.redisgraph; -public interface RedisGraphGeneralContext extends RedisGraph { +public interface RedisGraphContextGenerator extends RedisGraph { /** * Generate a connection bounded api * @return a connection bounded api */ - RedisGraphContexted getContextedAPI(); + RedisGraphContext getContext(); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index b2fe9f6..b846925 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -1,6 +1,6 @@ package com.redislabs.redisgraph.impl.api; -import com.redislabs.redisgraph.RedisGraphContexted; +import com.redislabs.redisgraph.RedisGraphContext; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; @@ -12,10 +12,10 @@ import java.util.List; /** - * An implementaion of RedisGraphContexted. Allows sending RedisGraph and some Redis commands, + * An implementaion of RedisGraphContext. Allows sending RedisGraph and some Redis commands, * within a specific connection context */ -public class ContextedRedisGraph extends AbstractRedisGraph implements RedisGraphContexted, RedisGraphCacheHolder { +public class ContextedRedisGraph extends AbstractRedisGraph implements RedisGraphContext, RedisGraphCacheHolder { private Jedis connectionContext; private RedisGraphCaches caches; diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index 900e32c..d3bea57 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -1,7 +1,7 @@ package com.redislabs.redisgraph.impl.api; -import com.redislabs.redisgraph.RedisGraphContexted; -import com.redislabs.redisgraph.RedisGraphGeneralContext; +import com.redislabs.redisgraph.RedisGraphContext; +import com.redislabs.redisgraph.RedisGraphContextGenerator; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import redis.clients.jedis.Jedis; @@ -12,7 +12,7 @@ /** * */ -public class RedisGraph extends AbstractRedisGraph implements RedisGraphGeneralContext { +public class RedisGraph extends AbstractRedisGraph implements RedisGraphContextGenerator { private final Pool client; private RedisGraphCaches caches = new RedisGraphCaches(); @@ -99,7 +99,7 @@ public String deleteGraph(String graphId) { * @return ContextedRedisGraph */ @Override - public RedisGraphContexted getContextedAPI() { + public RedisGraphContext getContext() { ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection()); contextedRedisGraph.setRedisGraphCaches(this.caches); return contextedRedisGraph; diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 6c5514e..5173ee3 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -23,7 +23,7 @@ import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; public class RedisGraphAPITest { - private RedisGraphGeneralContext api; + private RedisGraphContextGenerator api; public RedisGraphAPITest() { } @@ -504,7 +504,7 @@ public void testEscapedQuery() { @Test public void testMultiExec(){ - RedisGraphTransaction transaction = api.getContextedAPI().multi(); + RedisGraphTransaction transaction = api.getContext().multi(); transaction.set("x", "1"); transaction.query("social", "CREATE (:Person {name:'a'})"); @@ -651,7 +651,7 @@ public void testContextedAPI(){ expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); - RedisGraphContexted c = api.getContextedAPI(); + RedisGraphContext c = api.getContext(); Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); @@ -719,8 +719,8 @@ public void testContextedAPI(){ @Test public void testWriteTransactionWatch(){ - RedisGraphContexted c1 = api.getContextedAPI(); - RedisGraphContexted c2 = api.getContextedAPI(); + RedisGraphContext c1 = api.getContext(); + RedisGraphContext c2 = api.getContext(); c1.watch("social"); RedisGraphTransaction t1 = c1.multi(); @@ -747,8 +747,8 @@ public void testWriteTransactionWatch(){ @Test public void testReadTransactionWatch(){ - RedisGraphContexted c1 = api.getContextedAPI(); - RedisGraphContexted c2 = api.getContextedAPI(); + RedisGraphContext c1 = api.getContext(); + RedisGraphContext c2 = api.getContext(); Assert.assertNotEquals(c1.getConnectionContext(), c2.getConnectionContext()); c1.query("social", "CREATE (:Person {name:'a'})"); c1.watch("social"); From 9cb17d819407d32e710b0402cac38c9e43ff7881 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 23 Jul 2019 13:03:27 +0300 Subject: [PATCH 014/128] closable objects in examples and tests --- README.md | 40 +-- .../redisgraph/RedisGraphAPITest.java | 263 +++++++++--------- 2 files changed, 156 insertions(+), 147 deletions(-) diff --git a/README.md b/README.md index 1681a55..8d065cf 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.impl.api.RedisGraph; +import java.io.IOException; import java.util.List; public class RedisGraphExample { @@ -115,24 +116,29 @@ public class RedisGraphExample { // delete graph graph.deleteGraph("social"); - // get connection context - RedisGraphContext context = graph.getContext(); - context.query("contextSocial","CREATE (:person{name:'roi',age:32})"); - context.query("contextSocial","CREATE (:person{name:%s,age:%d})", "amit", 30); - context.query("contextSocial", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); - // WATCH/MULTI/EXEC - context.watch("contextSocial"); - RedisGraphTransaction t = context.multi(); - t.query("contextSocial", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); - // support for Redis/Jedis native commands in transaction - t.set("x", "1"); - t.get("x"); - // get multi/exec results - List execResults = t.exec(); - System.out.println(execResults.toString()); - - context.deleteGraph("contextSocial"); + // get connection context - closable object + try(RedisGraphContext context = graph.getContext()) { + context.query("contextSocial","CREATE (:person{name:'roi',age:32})"); + context.query("contextSocial","CREATE (:person{name:%s,age:%d})", "amit", 30); + context.query("contextSocial", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); + // WATCH/MULTI/EXEC + context.watch("contextSocial"); + RedisGraphTransaction t = context.multi(); + t.query("contextSocial", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); + // support for Redis/Jedis native commands in transaction + t.set("x", "1"); + t.get("x"); + // get multi/exec results + List execResults = t.exec(); + System.out.println(execResults.toString()); + + context.deleteGraph("contextSocial"); + } catch (IOException e) { + + } + } } + ``` diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 5173ee3..300d006 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -504,108 +504,111 @@ public void testEscapedQuery() { @Test public void testMultiExec(){ - RedisGraphTransaction transaction = api.getContext().multi(); - - transaction.set("x", "1"); - transaction.query("social", "CREATE (:Person {name:'a'})"); - transaction.query("g", "CREATE (:Person {name:'a'})"); - transaction.incr("x"); - transaction.get("x"); - transaction.query("social", "MATCH (n:Person) RETURN n"); - transaction.deleteGraph("g"); - transaction.callProcedure("social", "db.labels"); - List results = transaction.exec(); - - // Redis set command - Assert.assertEquals(String.class, results.get(0).getClass()); - Assert.assertEquals("OK", results.get(0)); - - // Redis graph command - Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); - ResultSet resultSet = (ResultSet) results.get(1); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - - - Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); - resultSet = (ResultSet) results.get(2); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - - // Redis incr command - Assert.assertEquals(Long.class, results.get(3).getClass()); - Assert.assertEquals((long)2, results.get(3)); - - // Redis get command - Assert.assertEquals(String.class, results.get(4).getClass()); - Assert.assertEquals("2", results.get(4)); - - // Graph query result - Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); - resultSet = (ResultSet) results.get(5); + try (RedisGraphContext c = api.getContext()) { + RedisGraphTransaction transaction = api.getContext().multi(); + + transaction.set("x", "1"); + transaction.query("social", "CREATE (:Person {name:'a'})"); + transaction.query("g", "CREATE (:Person {name:'a'})"); + transaction.incr("x"); + transaction.get("x"); + transaction.query("social", "MATCH (n:Person) RETURN n"); + transaction.deleteGraph("g"); + transaction.callProcedure("social", "db.labels"); + List results = transaction.exec(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Redis incr command + Assert.assertEquals(Long.class, results.get(3).getClass()); + Assert.assertEquals((long)2, results.get(3)); + + // Redis get command + Assert.assertEquals(String.class, results.get(4).getClass()); + Assert.assertEquals("2", results.get(4)); + + // Graph query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); - Assert.assertNotNull(resultSet.getHeader()); - Header header = resultSet.getHeader(); + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); - List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); + List schemaNames = header.getSchemaNames(); + List schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals("n", schemaNames.get(0)); + Assert.assertEquals("n", schemaNames.get(0)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); + Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "a"); - Node expectedNode = new Node(); - expectedNode.setId(0); - expectedNode.addLabel("Person"); - expectedNode.addProperty(nameProperty); - // see that the result were pulled from the right graph - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - Record record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(Arrays.asList("n"), record.keys()); - Assert.assertEquals(expectedNode, record.getValue("n")); - - // Graph delete - Assert.assertTrue(((String)results.get(6)).startsWith("Graph removed")); + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + // Graph delete + Assert.assertTrue(((String)results.get(6)).startsWith("Graph removed")); - Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); - resultSet = (ResultSet) results.get(7); - Assert.assertNotNull(resultSet.getHeader()); - header = resultSet.getHeader(); + Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); + resultSet = (ResultSet) results.get(7); + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); - schemaNames = header.getSchemaNames(); - schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); + schemaNames = header.getSchemaNames(); + schemaTypes = header.getSchemaTypes(); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); - Assert.assertEquals("label", schemaNames.get(0)); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); + Assert.assertEquals("label", schemaNames.get(0)); - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(Arrays.asList("label"), record.keys()); - Assert.assertEquals("Person", record.getValue("label")); + Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + } catch (IOException e) { + e.printStackTrace(); + } } @Test @@ -651,69 +654,69 @@ public void testContextedAPI(){ expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); - RedisGraphContext c = api.getContext(); + try(RedisGraphContext c = api.getContext()) { + Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); + Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); - Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); - Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); - Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + - "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); + ResultSet resultSet = c.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + + "a.name, a.age, a.doubleValue, a.boolValue, a.nullValue, " + + "r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); + Assert.assertNotNull(resultSet); - ResultSet resultSet = c.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + - "a.name, a.age, a.doubleValue, a.boolValue, a.nullValue, " + - "r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); - Assert.assertNotNull(resultSet); + Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(0, resultSet.getStatistics().nodesDeleted()); + Assert.assertEquals(0, resultSet.getStatistics().labelsAdded()); + Assert.assertEquals(0, resultSet.getStatistics().propertiesSet()); + Assert.assertEquals(0, resultSet.getStatistics().relationshipsCreated()); + Assert.assertEquals(0, resultSet.getStatistics().relationshipsDeleted()); + Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); - Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(0, resultSet.getStatistics().nodesDeleted()); - Assert.assertEquals(0, resultSet.getStatistics().labelsAdded()); - Assert.assertEquals(0, resultSet.getStatistics().propertiesSet()); - Assert.assertEquals(0, resultSet.getStatistics().relationshipsCreated()); - Assert.assertEquals(0, resultSet.getStatistics().relationshipsDeleted()); - Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - Record record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); + Node node = record.getValue(0); + Assert.assertNotNull(node); - Node node = record.getValue(0); - Assert.assertNotNull(node); + Assert.assertEquals(expectedNode, node); - Assert.assertEquals(expectedNode, node); + node = record.getValue("a"); + Assert.assertEquals(expectedNode, node); - node = record.getValue("a"); - Assert.assertEquals(expectedNode, node); + Edge edge = record.getValue(1); + Assert.assertNotNull(edge); + Assert.assertEquals(expectedEdge, edge); - Edge edge = record.getValue(1); - Assert.assertNotNull(edge); - Assert.assertEquals(expectedEdge, edge); + edge = record.getValue("r"); + Assert.assertEquals(expectedEdge, edge); - edge = record.getValue("r"); - Assert.assertEquals(expectedEdge, edge); + Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", "a.nullValue", + "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); - Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", "a.nullValue", - "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); + Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, + name, age, doubleValue, true, null, + place, since, doubleValue, false, null), + record.values()); - Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, age, doubleValue, true, null, - place, since, doubleValue, false, null), - record.values()); + Node a = record.getValue("a"); + for (String propertyName : expectedNode.getEntityPropertyNames()){ + Assert.assertEquals(expectedNode.getProperty(propertyName) ,a.getProperty(propertyName)); + } - Node a = record.getValue("a"); - for (String propertyName : expectedNode.getEntityPropertyNames()){ - Assert.assertEquals(expectedNode.getProperty(propertyName) ,a.getProperty(propertyName)); + Assert.assertEquals( "roi", record.getString(2)); + Assert.assertEquals( "32", record.getString(3)); + Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); + Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); + Assert.assertEquals( "roi", record.getString("a.name")); + Assert.assertEquals( "32", record.getString("a.age")); + } catch (IOException e) { + e.printStackTrace(); } - - Assert.assertEquals( "roi", record.getString(2)); - Assert.assertEquals( "32", record.getString(3)); - Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); - Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); - Assert.assertEquals( "roi", record.getString("a.name")); - Assert.assertEquals( "32", record.getString("a.age")); - - } @Test From 023c61d628b4dd61c708ec02938f51b828a9268b Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 23 Jul 2019 13:14:45 +0300 Subject: [PATCH 015/128] removed closable exception --- .../com/redislabs/redisgraph/RedisGraph.java | 3 + .../redisgraph/RedisGraphAPITest.java | 61 +++++-------------- 2 files changed, 19 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index 90432bd..6e3376e 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -1,6 +1,7 @@ package com.redislabs.redisgraph; import java.io.Closeable; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -49,4 +50,6 @@ public interface RedisGraph extends Closeable { */ String deleteGraph(String graphId); + @Override + void close(); } diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 300d006..2daf97f 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -36,11 +36,7 @@ public void createApi(){ public void deleteGraph() { api.deleteGraph("social"); - try { - api.close(); - } catch (IOException e) { - e.printStackTrace(); - } + api.close(); } @@ -606,24 +602,21 @@ record = resultSet.next(); Assert.assertFalse(resultSet.hasNext()); Assert.assertEquals(Arrays.asList("label"), record.keys()); Assert.assertEquals("Person", record.getValue("label")); - } catch (IOException e) { - e.printStackTrace(); } } @Test - public void testContextedAPI(){ + public void testContextedAPI() { String name = "roi"; int age = 32; double doubleValue = 3.14; - boolean boolValue = true; + boolean boolValue = true; String place = "TLV"; int since = 2000; - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, name); Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, age); Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.PROPERTY_DOUBLE, doubleValue); @@ -654,7 +647,7 @@ public void testContextedAPI(){ expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); - try(RedisGraphContext c = api.getContext()) { + try (RedisGraphContext c = api.getContext()) { Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + @@ -704,18 +697,16 @@ public void testContextedAPI(){ record.values()); Node a = record.getValue("a"); - for (String propertyName : expectedNode.getEntityPropertyNames()){ - Assert.assertEquals(expectedNode.getProperty(propertyName) ,a.getProperty(propertyName)); + for (String propertyName : expectedNode.getEntityPropertyNames()) { + Assert.assertEquals(expectedNode.getProperty(propertyName), a.getProperty(propertyName)); } - Assert.assertEquals( "roi", record.getString(2)); - Assert.assertEquals( "32", record.getString(3)); - Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); - Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); - Assert.assertEquals( "roi", record.getString("a.name")); - Assert.assertEquals( "32", record.getString("a.age")); - } catch (IOException e) { - e.printStackTrace(); + Assert.assertEquals("roi", record.getString(2)); + Assert.assertEquals("32", record.getString(3)); + Assert.assertEquals(32L, ((Integer) (record.getValue(3))).longValue()); + Assert.assertEquals(32L, ((Integer) record.getValue("a.age")).longValue()); + Assert.assertEquals("roi", record.getString("a.name")); + Assert.assertEquals("32", record.getString("a.age")); } } @@ -733,18 +724,8 @@ public void testWriteTransactionWatch(){ c2.query("social", "CREATE (:Person {name:'b'})"); List returnValue = t1.exec(); Assert.assertNull(returnValue); - - try { - c1.close(); - } catch (IOException e) { - e.printStackTrace(); - } - try { - c2.close(); - } catch (IOException e) { - e.printStackTrace(); - } - + c1.close(); + c2.close(); } @Test @@ -762,17 +743,7 @@ public void testReadTransactionWatch(){ List returnValue = t1.exec(); Assert.assertNotNull(returnValue); - - try { - c1.close(); - } catch (IOException e) { - e.printStackTrace(); - } - try { - c2.close(); - } catch (IOException e) { - e.printStackTrace(); - } - + c1.close(); + c2.close(); } } From a2b65063b3c4ea10c4328faebafe64ee5b2f9321 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 23 Jul 2019 13:17:32 +0300 Subject: [PATCH 016/128] removed closable exception --- README.md | 5 ----- src/main/java/com/redislabs/redisgraph/RedisGraph.java | 1 - .../java/com/redislabs/redisgraph/RedisGraphAPITest.java | 1 - 3 files changed, 7 deletions(-) diff --git a/README.md b/README.md index 8d065cf..a826bdc 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.impl.api.RedisGraph; -import java.io.IOException; import java.util.List; public class RedisGraphExample { @@ -133,12 +132,8 @@ public class RedisGraphExample { System.out.println(execResults.toString()); context.deleteGraph("contextSocial"); - } catch (IOException e) { - } - } } - ``` diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index 6e3376e..25c4718 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -1,7 +1,6 @@ package com.redislabs.redisgraph; import java.io.Closeable; -import java.io.IOException; import java.util.List; import java.util.Map; diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 2daf97f..59e35e3 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -1,7 +1,6 @@ package com.redislabs.redisgraph; -import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; From fe47c86fd1e56b40a753137027056e88e6b76656 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 23 Jul 2019 13:43:12 +0300 Subject: [PATCH 017/128] add test to Edge.toString() and Node.toString() --- .../redislabs/redisgraph/RedisGraphAPITest.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 59e35e3..7586de0 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -219,6 +219,13 @@ public void testRecord(){ expectedNode.addProperty(doubleProperty); expectedNode.addProperty(trueBooleanProperty); expectedNode.addProperty(nullProperty); + Assert.assertEquals( + "Node{labels=[person], id=0, " + + "propertyMap={name=Property{name='name', type=PROPERTY_STRING, value=roi}, " + + "boolValue=Property{name='boolValue', type=PROPERTY_BOOLEAN, value=true}, " + + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " + + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + + "age=Property{name='age', type=PROPERTY_INTEGER, value=32}}}", expectedNode.toString()); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -230,8 +237,12 @@ public void testRecord(){ expectedEdge.addProperty(doubleProperty); expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); - - + Assert.assertEquals("Edge{relationshipType='knows', source=0, destination=1, id=0, " + + "propertyMap={boolValue=Property{name='boolValue', type=PROPERTY_BOOLEAN, value=false}, " + + "place=Property{name='place', type=PROPERTY_STRING, value=TLV}, " + + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " + + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + + "since=Property{name='since', type=PROPERTY_INTEGER, value=2000}}}", expectedEdge.toString()); Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); From 5e91c3f5656d4dc4ad3f1e526e408bceb9ad2b62 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 23 Jul 2019 13:43:12 +0300 Subject: [PATCH 018/128] add test to Edge.hashCode() and Node.hashCode() --- .../redislabs/redisgraph/RedisGraphAPITest.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 59e35e3..9aa252b 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -219,6 +219,14 @@ public void testRecord(){ expectedNode.addProperty(doubleProperty); expectedNode.addProperty(trueBooleanProperty); expectedNode.addProperty(nullProperty); + Assert.assertEquals( + "Node{labels=[person], id=0, " + + "propertyMap={name=Property{name='name', type=PROPERTY_STRING, value=roi}, " + + "boolValue=Property{name='boolValue', type=PROPERTY_BOOLEAN, value=true}, " + + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " + + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + + "age=Property{name='age', type=PROPERTY_INTEGER, value=32}}}", expectedNode.toString()); + Assert.assertEquals(2013991279, expectedNode.hashCode()); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -230,8 +238,13 @@ public void testRecord(){ expectedEdge.addProperty(doubleProperty); expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); - - + Assert.assertEquals("Edge{relationshipType='knows', source=0, destination=1, id=0, " + + "propertyMap={boolValue=Property{name='boolValue', type=PROPERTY_BOOLEAN, value=false}, " + + "place=Property{name='place', type=PROPERTY_STRING, value=TLV}, " + + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " + + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + + "since=Property{name='since', type=PROPERTY_INTEGER, value=2000}}}", expectedEdge.toString()); + Assert.assertEquals(-1182568484, expectedEdge.hashCode()); Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); From 4882eb7e6eafcb3ceb6ea7790789c76bedb54af7 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 23 Jul 2019 13:52:48 +0300 Subject: [PATCH 019/128] remove unneeded toString() from GraphEntity --- .../redisgraph/graph_entities/GraphEntity.java | 14 +------------- .../redislabs/redisgraph/RedisGraphAPITest.java | 2 -- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index d2083a6..e913921 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -112,17 +112,5 @@ public int hashCode() { return Objects.hash(id, propertyMap); } - - /** - * Default toString implementation. - * @return - */ - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("GraphEntity{"); - sb.append("id=").append(id); - sb.append(", propertyMap=").append(propertyMap); - sb.append('}'); - return sb.toString(); - } + public abstract String toString(); } diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 9aa252b..7586de0 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -226,7 +226,6 @@ public void testRecord(){ + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + "age=Property{name='age', type=PROPERTY_INTEGER, value=32}}}", expectedNode.toString()); - Assert.assertEquals(2013991279, expectedNode.hashCode()); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -244,7 +243,6 @@ public void testRecord(){ + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + "since=Property{name='since', type=PROPERTY_INTEGER, value=2000}}}", expectedEdge.toString()); - Assert.assertEquals(-1182568484, expectedEdge.hashCode()); Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); From 6493589a5c5160508061fe5b2953059023c516ae Mon Sep 17 00:00:00 2001 From: Jeffrey Lovitz Date: Wed, 31 Jul 2019 12:57:53 -0400 Subject: [PATCH 020/128] Update unit tests to not raise libcypher-parser errors --- .../redislabs/redisgraph/RedisGraphAPITest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 7586de0..ce2aa59 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -244,7 +244,7 @@ public void testRecord(){ + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " + "since=Property{name='since', type=PROPERTY_INTEGER, value=2000}}}", expectedEdge.toString()); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); + Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s,age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); @@ -298,9 +298,9 @@ public void testRecord(){ } Assert.assertEquals( "roi", record.getString(2)); - Assert.assertEquals( "32", record.getString(3)); - Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); - Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); + Assert.assertEquals( "32", record.getString(3)); + Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); + Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); Assert.assertEquals( "roi", record.getString("a.name")); Assert.assertEquals( "32", record.getString("a.age")); @@ -502,9 +502,9 @@ record = resultSet.next(); @Test public void testEscapedQuery() { - Assert.assertNotNull(api.query("social", "CREATE (:escaped{s1:%s,s2:%s})", "S\"\'", "S\\'\\\"")); - Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1=%s and n.s2=%s RETURN n", "S\"\'", "S\\'\\\"")); - Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"\\'' RETURN n")); + Assert.assertNotNull(api.query("social", "CREATE (:escaped{s1:%s,s2:%s})", "S\"'", "S'\"")); + Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1=%s and n.s2=%s RETURN n", "S\"'", "S'\"")); + Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"' RETURN n")); } @@ -658,7 +658,7 @@ public void testContextedAPI() { expectedEdge.addProperty(nullProperty); try (RedisGraphContext c = api.getContext()) { - Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s',age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); + Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s,age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); From 2d52128bdfd5a9d99ae49be2c680921823666b8f Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Mon, 12 Aug 2019 10:15:40 +0300 Subject: [PATCH 021/128] added array support --- .../com/redislabs/redisgraph/ResultSet.java | 15 +- .../impl/resultset/ResultSetImpl.java | 27 ++- .../redisgraph/RedisGraphAPITest.java | 189 +++++++++++++++--- 3 files changed, 186 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index 251a4d0..deb5a88 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -8,12 +8,15 @@ public interface ResultSet extends Iterator { enum ResultSetScalarTypes { - PROPERTY_UNKNOWN, - PROPERTY_NULL, - PROPERTY_STRING, - PROPERTY_INTEGER, - PROPERTY_BOOLEAN, - PROPERTY_DOUBLE, + VALUE_UNKNOWN, + VALUE_NULL, + VALUE_STRING, + VALUE_INTEGER, + VALUE_BOOLEAN, + VALUE_DOUBLE, + VALUE_ARRAY, + VALUE_EDGE, + VALUE_NODE } int size(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index fd208b6..5e48440 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -216,22 +216,37 @@ private Object deserializeScalar(List rawScalarData) { ResultSetScalarTypes type = getScalarTypeFromObject(rawScalarData.get(0)); Object obj = rawScalarData.get(1); switch (type) { - case PROPERTY_NULL: + case VALUE_NULL: return null; - case PROPERTY_BOOLEAN: + case VALUE_BOOLEAN: return Boolean.parseBoolean(SafeEncoder.encode((byte[]) obj)); - case PROPERTY_DOUBLE: + case VALUE_DOUBLE: return Double.parseDouble(SafeEncoder.encode((byte[]) obj)); - case PROPERTY_INTEGER: + case VALUE_INTEGER: return ((Long) obj).intValue(); - case PROPERTY_STRING: + case VALUE_STRING: return SafeEncoder.encode((byte[]) obj); - case PROPERTY_UNKNOWN: + case VALUE_ARRAY: + return deserializeArray(obj); + case VALUE_NODE: + return deserializeNode((List) obj); + case VALUE_EDGE: + return deserializeEdge((List) obj); + case VALUE_UNKNOWN: default: return obj; } } + private List deserializeArray(Object rawScalarData) { + List res = new ArrayList<>(); + List> array = (List>) rawScalarData; + for (List arrayValue : array) { + res.add(deserializeScalar(arrayValue)); + } + return res; + } + /** * Auxiliary function to retrieve scalar types * diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index ce2aa59..63fd7c6 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -201,15 +201,15 @@ public void testRecord(){ - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.PROPERTY_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.PROPERTY_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.PROPERTY_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.PROPERTY_NULL, null); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); - Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, since); + Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -221,11 +221,11 @@ public void testRecord(){ expectedNode.addProperty(nullProperty); Assert.assertEquals( "Node{labels=[person], id=0, " - + "propertyMap={name=Property{name='name', type=PROPERTY_STRING, value=roi}, " - + "boolValue=Property{name='boolValue', type=PROPERTY_BOOLEAN, value=true}, " - + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " - + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " - + "age=Property{name='age', type=PROPERTY_INTEGER, value=32}}}", expectedNode.toString()); + + "propertyMap={name=Property{name='name', type=VALUE_STRING, value=roi}, " + + "boolValue=Property{name='boolValue', type=VALUE_BOOLEAN, value=true}, " + + "doubleValue=Property{name='doubleValue', type=VALUE_DOUBLE, value=3.14}, " + + "nullValue=Property{name='nullValue', type=VALUE_NULL, value=null}, " + + "age=Property{name='age', type=VALUE_INTEGER, value=32}}}", expectedNode.toString()); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -238,11 +238,11 @@ public void testRecord(){ expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); Assert.assertEquals("Edge{relationshipType='knows', source=0, destination=1, id=0, " - + "propertyMap={boolValue=Property{name='boolValue', type=PROPERTY_BOOLEAN, value=false}, " - + "place=Property{name='place', type=PROPERTY_STRING, value=TLV}, " - + "doubleValue=Property{name='doubleValue', type=PROPERTY_DOUBLE, value=3.14}, " - + "nullValue=Property{name='nullValue', type=PROPERTY_NULL, value=null}, " - + "since=Property{name='since', type=PROPERTY_INTEGER, value=2000}}}", expectedEdge.toString()); + + "propertyMap={boolValue=Property{name='boolValue', type=VALUE_BOOLEAN, value=false}, " + + "place=Property{name='place', type=VALUE_STRING, value=TLV}, " + + "doubleValue=Property{name='doubleValue', type=VALUE_DOUBLE, value=3.14}, " + + "nullValue=Property{name='nullValue', type=VALUE_NULL, value=null}, " + + "since=Property{name='since', type=VALUE_INTEGER, value=2000}}}", expectedEdge.toString()); Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s,age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); @@ -330,9 +330,9 @@ public void testMultiThread(){ mapToObj(i-> api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")). collect(Collectors.toList()); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); + Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -424,9 +424,9 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); //expected objects init - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); + Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -568,7 +568,7 @@ public void testMultiExec(){ Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -627,15 +627,15 @@ public void testContextedAPI() { int since = 2000; - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.PROPERTY_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.PROPERTY_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.PROPERTY_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.PROPERTY_NULL, null); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); - Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.PROPERTY_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.PROPERTY_INTEGER, since); + Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -756,4 +756,127 @@ public void testReadTransactionWatch(){ c1.close(); c2.close(); } + + @Test + public void testArraySupport() { + + Node expectedANode = new Node(); + expectedANode.setId(0); + expectedANode.addLabel("person"); + Property aNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property aAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); + Property aListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(0,1,2)); + expectedANode.addProperty(aNameProperty); + expectedANode.addProperty(aAgeProperty); + expectedANode.addProperty(aListProperty); + + + Node expectedBNode = new Node(); + expectedBNode.setId(1); + expectedBNode.addLabel("person"); + Property bNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "b"); + Property bAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 30); + Property bListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(3,4,5)); + expectedBNode.addProperty(bNameProperty); + expectedBNode.addProperty(bAgeProperty); + expectedBNode.addProperty(bListProperty); + + + + Assert.assertNotNull(api.query("social", "CREATE (:person{name:'a',age:32,array:[0,1,2]})")); + Assert.assertNotNull(api.query("social", "CREATE (:person{name:'b',age:30,array:[3,4,5]})")); + + + // test array + + ResultSet resultSet = api.query("social", "WITH [0,1,2] as x return x"); + + // check header + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + + List schemaNames = header.getSchemaNames(); + List schemaTypes = header.getSchemaTypes(); + + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); + + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); + + Assert.assertEquals("x", schemaNames.get(0)); + Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); + + // check record + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("x"), record.keys()); + + + List x = record.getValue("x"); + Assert.assertEquals(Arrays.asList(0,1,2), x); + + // test collect + resultSet = api.query("social", "MATCH(n) return collect(n) as x"); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + + schemaNames = header.getSchemaNames(); + schemaTypes = header.getSchemaTypes(); + + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); + + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); + + Assert.assertEquals("x", schemaNames.get(0)); + Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); + + // check record + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("x"), record.keys()); + x = record.getValue("x"); + Assert.assertEquals(Arrays.asList(expectedANode, expectedBNode), x); + + + // test unwind + resultSet = api.query("social", "unwind([0,1,2]) as x return x"); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + + schemaNames = header.getSchemaNames(); + schemaTypes = header.getSchemaTypes(); + + Assert.assertNotNull(schemaNames); + Assert.assertNotNull(schemaTypes); + + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals(1, schemaTypes.size()); + + Assert.assertEquals("x", schemaNames.get(0)); + Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); + + // check record + Assert.assertEquals(3, resultSet.size()); + + for (int i = 0; i < 3; i++) { + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertEquals(Arrays.asList("x"), record.keys()); + Assert.assertEquals(i, (int) record.getValue("x")); + + } + + } } From 12d89f968ea84e47417badb077a796bfca48fdb6 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Mon, 12 Aug 2019 12:32:16 +0300 Subject: [PATCH 022/128] scalar value type is now deprecated moved to value type --- .../com/redislabs/redisgraph/ResultSet.java | 10 ++++ .../redisgraph/graph_entities/Property.java | 30 +++++++++- .../impl/resultset/ResultSetImpl.java | 11 ++-- .../redisgraph/RedisGraphAPITest.java | 58 +++++++++---------- 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index deb5a88..31a6f27 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -7,7 +7,17 @@ */ public interface ResultSet extends Iterator { + @Deprecated enum ResultSetScalarTypes { + PROPERTY_UNKNOWN, + PROPERTY_NULL, + PROPERTY_STRING, + PROPERTY_INTEGER, + PROPERTY_BOOLEAN, + PROPERTY_DOUBLE + } + + enum ResultSetValueTypes { VALUE_UNKNOWN, VALUE_NULL, VALUE_STRING, diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 9a897f8..26163ac 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -12,6 +12,8 @@ public class Property { //members private String name; private ResultSet.ResultSetScalarTypes type; + + private ResultSet.ResultSetValueTypes valueType; private Object value; @@ -29,12 +31,19 @@ public Property() { * @param type * @param value */ + @Deprecated public Property(String name, ResultSet.ResultSetScalarTypes type, Object value) { this.name = name; this.type = type; this.value = value; } + public Property(String name, ResultSet.ResultSetValueTypes type, Object value) { + this.name = name; + this.valueType = type; + this.value = value; + } + //getters & setters /** @@ -54,6 +63,7 @@ public void setName(String name) { /** * @return property type */ + @Deprecated public ResultSet.ResultSetScalarTypes getType() { return type; } @@ -61,10 +71,24 @@ public ResultSet.ResultSetScalarTypes getType() { /** * @param type property type to be set */ + @Deprecated public void setType(ResultSet.ResultSetScalarTypes type) { this.type = type; } + /** + * @return property type + */ + public ResultSet.ResultSetValueTypes getValueType() {return valueType;} + + + /** + * @param type property type to be set + */ + public void setValueType(ResultSet.ResultSetValueTypes type) { + this.valueType = type; + } + /** * @return property value @@ -88,13 +112,13 @@ public boolean equals(Object o) { if (!(o instanceof Property)) return false; Property property = (Property) o; return Objects.equals(name, property.name) && - type == property.type && + valueType == property.valueType && Objects.equals(value, property.value); } @Override public int hashCode() { - return Objects.hash(name, type, value); + return Objects.hash(name, valueType, value); } /** @@ -105,7 +129,7 @@ public int hashCode() { public String toString() { final StringBuilder sb = new StringBuilder("Property{"); sb.append("name='").append(name).append('\''); - sb.append(", type=").append(type); + sb.append(", type=").append(valueType); sb.append(", value=").append(value); sb.append('}'); return sb.toString(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 5e48440..2d658e3 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -199,7 +199,7 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List propertyScalar = rawProperty.subList(1, rawProperty.size()); - property.setType(getScalarTypeFromObject(propertyScalar.get(0))); + property.setValueType(getValueTypeFromObject(propertyScalar.get(0))); property.setValue(deserializeScalar(propertyScalar)); entity.addProperty(property); @@ -213,7 +213,8 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List rawScalarData) { - ResultSetScalarTypes type = getScalarTypeFromObject(rawScalarData.get(0)); + ResultSetValueTypes type = getValueTypeFromObject(rawScalarData.get(0)); + Object obj = rawScalarData.get(1); switch (type) { case VALUE_NULL: @@ -239,8 +240,8 @@ private Object deserializeScalar(List rawScalarData) { } private List deserializeArray(Object rawScalarData) { - List res = new ArrayList<>(); List> array = (List>) rawScalarData; + List res = new ArrayList<>(array.size()); for (List arrayValue : array) { res.add(deserializeScalar(arrayValue)); } @@ -253,8 +254,8 @@ private List deserializeArray(Object rawScalarData) { * @param rawScalarType * @return scalar type */ - private ResultSetScalarTypes getScalarTypeFromObject(Object rawScalarType) { - return ResultSetScalarTypes.values()[((Long) rawScalarType).intValue()]; + private ResultSetValueTypes getValueTypeFromObject(Object rawScalarType) { + return ResultSetValueTypes.values()[((Long) rawScalarType).intValue()]; } @Override diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 63fd7c6..d8c00d8 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -201,15 +201,15 @@ public void testRecord(){ - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); + Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetValueTypes.VALUE_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetValueTypes.VALUE_NULL, null); - Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); + Property placeProperty = new Property("place", ResultSet.ResultSetValueTypes.VALUE_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetValueTypes.VALUE_INTEGER, since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -330,9 +330,9 @@ public void testMultiThread(){ mapToObj(i-> api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")). collect(Collectors.toList()); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "roi"); + Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 32); + Property lastNameProperty =new Property("lastName", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -424,9 +424,9 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); //expected objects init - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "roi"); + Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 32); + Property lastNameProperty =new Property("lastName", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -568,7 +568,7 @@ public void testMultiExec(){ Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -627,15 +627,15 @@ public void testContextedAPI() { int since = 2000; - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); + Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetValueTypes.VALUE_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetValueTypes.VALUE_NULL, null); - Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); + Property placeProperty = new Property("place", ResultSet.ResultSetValueTypes.VALUE_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetValueTypes.VALUE_INTEGER, since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -763,9 +763,9 @@ public void testArraySupport() { Node expectedANode = new Node(); expectedANode.setId(0); expectedANode.addLabel("person"); - Property aNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); - Property aAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); - Property aListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(0,1,2)); + Property aNameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); + Property aAgeProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 32); + Property aListProperty = new Property("array", ResultSet.ResultSetValueTypes.VALUE_ARRAY, Arrays.asList(0,1,2)); expectedANode.addProperty(aNameProperty); expectedANode.addProperty(aAgeProperty); expectedANode.addProperty(aListProperty); @@ -774,9 +774,9 @@ public void testArraySupport() { Node expectedBNode = new Node(); expectedBNode.setId(1); expectedBNode.addLabel("person"); - Property bNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "b"); - Property bAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 30); - Property bListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(3,4,5)); + Property bNameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "b"); + Property bAgeProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 30); + Property bListProperty = new Property("array", ResultSet.ResultSetValueTypes.VALUE_ARRAY, Arrays.asList(3,4,5)); expectedBNode.addProperty(bNameProperty); expectedBNode.addProperty(bAgeProperty); expectedBNode.addProperty(bListProperty); From 6f9a13058e1de6b237a08b2b0bd301fb4be42dfb Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 18 Aug 2019 20:34:23 +0300 Subject: [PATCH 023/128] milder deprecation --- .../com/redislabs/redisgraph/ResultSet.java | 14 +++-- .../redisgraph/graph_entities/Property.java | 37 +++++------- .../impl/resultset/ResultSetImpl.java | 8 +-- .../redisgraph/RedisGraphAPITest.java | 58 +++++++++---------- 4 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index 31a6f27..9224b36 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -7,17 +7,20 @@ */ public interface ResultSet extends Iterator { - @Deprecated + enum ResultSetScalarTypes { + @Deprecated PROPERTY_UNKNOWN, + @Deprecated PROPERTY_NULL, + @Deprecated PROPERTY_STRING, + @Deprecated PROPERTY_INTEGER, + @Deprecated PROPERTY_BOOLEAN, - PROPERTY_DOUBLE - } - - enum ResultSetValueTypes { + @Deprecated + PROPERTY_DOUBLE, VALUE_UNKNOWN, VALUE_NULL, VALUE_STRING, @@ -28,6 +31,7 @@ enum ResultSetValueTypes { VALUE_EDGE, VALUE_NODE } + int size(); diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 26163ac..786051c 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -13,7 +13,6 @@ public class Property { private String name; private ResultSet.ResultSetScalarTypes type; - private ResultSet.ResultSetValueTypes valueType; private Object value; @@ -31,18 +30,12 @@ public Property() { * @param type * @param value */ - @Deprecated public Property(String name, ResultSet.ResultSetScalarTypes type, Object value) { this.name = name; this.type = type; this.value = value; } - public Property(String name, ResultSet.ResultSetValueTypes type, Object value) { - this.name = name; - this.valueType = type; - this.value = value; - } //getters & setters @@ -65,31 +58,31 @@ public void setName(String name) { */ @Deprecated public ResultSet.ResultSetScalarTypes getType() { + if (type.ordinal() >= 6 && type.ordinal() < 12){ + return ResultSet.ResultSetScalarTypes.values()[type.ordinal()-6]; + } return type; } - /** - * @param type property type to be set - */ - @Deprecated - public void setType(ResultSet.ResultSetScalarTypes type) { - this.type = type; + public ResultSet.ResultSetScalarTypes getValueType() { + return type; } - /** - * @return property type - */ - public ResultSet.ResultSetValueTypes getValueType() {return valueType;} /** * @param type property type to be set */ - public void setValueType(ResultSet.ResultSetValueTypes type) { - this.valueType = type; + public void setType(ResultSet.ResultSetScalarTypes type) { + ResultSet.ResultSetScalarTypes actualType = type; + if (type.ordinal() < 6) { + actualType = ResultSet.ResultSetScalarTypes.values()[type.ordinal() + 6]; + } + this.type = actualType; } + /** * @return property value */ @@ -112,13 +105,13 @@ public boolean equals(Object o) { if (!(o instanceof Property)) return false; Property property = (Property) o; return Objects.equals(name, property.name) && - valueType == property.valueType && + type == property.type && Objects.equals(value, property.value); } @Override public int hashCode() { - return Objects.hash(name, valueType, value); + return Objects.hash(name, type, value); } /** @@ -129,7 +122,7 @@ public int hashCode() { public String toString() { final StringBuilder sb = new StringBuilder("Property{"); sb.append("name='").append(name).append('\''); - sb.append(", type=").append(valueType); + sb.append(", type=").append(type); sb.append(", value=").append(value); sb.append('}'); return sb.toString(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 2d658e3..7ee65cf 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -199,7 +199,7 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List propertyScalar = rawProperty.subList(1, rawProperty.size()); - property.setValueType(getValueTypeFromObject(propertyScalar.get(0))); + property.setType(getValueTypeFromObject(propertyScalar.get(0))); property.setValue(deserializeScalar(propertyScalar)); entity.addProperty(property); @@ -213,7 +213,7 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List rawScalarData) { - ResultSetValueTypes type = getValueTypeFromObject(rawScalarData.get(0)); + ResultSetScalarTypes type = getValueTypeFromObject(rawScalarData.get(0)); Object obj = rawScalarData.get(1); switch (type) { @@ -254,8 +254,8 @@ private List deserializeArray(Object rawScalarData) { * @param rawScalarType * @return scalar type */ - private ResultSetValueTypes getValueTypeFromObject(Object rawScalarType) { - return ResultSetValueTypes.values()[((Long) rawScalarType).intValue()]; + private ResultSetScalarTypes getValueTypeFromObject(Object rawScalarType) { + return ResultSetScalarTypes.values()[((Long) rawScalarType).intValue() + 6]; } @Override diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index d8c00d8..63fd7c6 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -201,15 +201,15 @@ public void testRecord(){ - Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetValueTypes.VALUE_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetValueTypes.VALUE_NULL, null); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); - Property placeProperty = new Property("place", ResultSet.ResultSetValueTypes.VALUE_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetValueTypes.VALUE_INTEGER, since); + Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -330,9 +330,9 @@ public void testMultiThread(){ mapToObj(i-> api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")). collect(Collectors.toList()); - Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); + Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -424,9 +424,9 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); //expected objects init - Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); + Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -568,7 +568,7 @@ public void testMultiExec(){ Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -627,15 +627,15 @@ public void testContextedAPI() { int since = 2000; - Property nameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetValueTypes.VALUE_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetValueTypes.VALUE_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetValueTypes.VALUE_NULL, null); + Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); + Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); + Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); + Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); + Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); + Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); - Property placeProperty = new Property("place", ResultSet.ResultSetValueTypes.VALUE_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetValueTypes.VALUE_INTEGER, since); + Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); + Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -763,9 +763,9 @@ public void testArraySupport() { Node expectedANode = new Node(); expectedANode.setId(0); expectedANode.addLabel("person"); - Property aNameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "a"); - Property aAgeProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 32); - Property aListProperty = new Property("array", ResultSet.ResultSetValueTypes.VALUE_ARRAY, Arrays.asList(0,1,2)); + Property aNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property aAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); + Property aListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(0,1,2)); expectedANode.addProperty(aNameProperty); expectedANode.addProperty(aAgeProperty); expectedANode.addProperty(aListProperty); @@ -774,9 +774,9 @@ public void testArraySupport() { Node expectedBNode = new Node(); expectedBNode.setId(1); expectedBNode.addLabel("person"); - Property bNameProperty = new Property("name", ResultSet.ResultSetValueTypes.VALUE_STRING, "b"); - Property bAgeProperty = new Property("age", ResultSet.ResultSetValueTypes.VALUE_INTEGER, 30); - Property bListProperty = new Property("array", ResultSet.ResultSetValueTypes.VALUE_ARRAY, Arrays.asList(3,4,5)); + Property bNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "b"); + Property bAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 30); + Property bListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(3,4,5)); expectedBNode.addProperty(bNameProperty); expectedBNode.addProperty(bAgeProperty); expectedBNode.addProperty(bListProperty); From 91ac3a8443d25d7d4e0b2abec6d9cf59593ab8ac Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 22 Aug 2019 13:12:49 +0300 Subject: [PATCH 024/128] added runtime exceptions --- .../com/redislabs/redisgraph/RedisGraphAPITest.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index ce2aa59..ccaac70 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -12,6 +12,7 @@ import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; +import jdk.nashorn.internal.ir.annotations.Ignore; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -152,10 +153,13 @@ public void testIndex() { Assert.assertFalse(createIndexResult.hasNext()); Assert.assertEquals(1, createIndexResult.getStatistics().indicesAdded()); - ResultSet failCreateIndexResult = api.query("social", "CREATE INDEX ON :person(age1)"); - Assert.assertFalse(failCreateIndexResult.hasNext()); - Assert.assertNull(failCreateIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); - Assert.assertEquals(0, failCreateIndexResult.getStatistics().indicesAdded()); + // since RediSearch as index, those action are allowed + ResultSet createNonExistingIndexResult = api.query("social", "CREATE INDEX ON :person(age1)"); + Assert.assertFalse(createNonExistingIndexResult.hasNext()); + Assert.assertNotNull(createNonExistingIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); + Assert.assertEquals(1, createNonExistingIndexResult.getStatistics().indicesAdded()); + + } @Test From b5953e5dd5aa3dea65fa888acd69dcbc1c484706 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 22 Aug 2019 13:14:49 +0300 Subject: [PATCH 025/128] added runtime exceptions --- src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index ccaac70..79e313d 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -12,7 +12,6 @@ import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; -import jdk.nashorn.internal.ir.annotations.Ignore; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -159,7 +158,6 @@ public void testIndex() { Assert.assertNotNull(createNonExistingIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); Assert.assertEquals(1, createNonExistingIndexResult.getStatistics().indicesAdded()); - } @Test From 1af4700575dd121f0da9ee3b66a7e20df47928d2 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Sun, 25 Aug 2019 15:31:45 +0300 Subject: [PATCH 026/128] add unit tests for Utils --- .../redislabs/redisgraph/impl/UtilsTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java diff --git a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java new file mode 100644 index 0000000..314d9eb --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java @@ -0,0 +1,40 @@ +package com.redislabs.redisgraph.impl; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.IllegalFormatConversionException; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +public class UtilsTest { + + @Test + public void testPrepareProcedure() { + + Assert.assertEquals("CALL prc()", Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), new HashMap<>())); + + Assert.assertEquals("CALL prc(\"a\",\"b\")", Utils.prepareProcedure("prc", Arrays.asList(new String[]{"a", "b"}), new HashMap<>())); + + Map> kwargs = new HashMap<>(); + kwargs.put("y", Arrays.asList(new String[]{"ka", "kb"})); + Assert.assertEquals("CALL prc(\"a\",\"b\")ka,kb", Utils.prepareProcedure("prc", Arrays.asList(new String[]{"a", "b"}), kwargs)); + + Assert.assertEquals("CALL prc()ka,kb", Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), kwargs)); + } + + @Test + public void prepareQuery() { + Assert.assertEquals("query %s %d end of query", Utils.prepareQuery("query %s %d end of query")); + + Assert.assertEquals("query 'a' 33 end of query", Utils.prepareQuery("query %s %d end of query", "a", 33)); + + try { + Assert.assertEquals("CALL prc(\"a\",\"b\")ka,kb", Utils.prepareQuery("query %s %d end of query", "a", "b")); + Assert.fail(); + } catch (IllegalFormatConversionException e) {} + } + +} From 8fdb6bf239672790b6e66b40529334e8acb6be1c Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Mon, 26 Aug 2019 16:38:26 +0300 Subject: [PATCH 027/128] modified exception verification --- .../com/redislabs/redisgraph/impl/UtilsTest.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java index 314d9eb..e6b8228 100644 --- a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java +++ b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java @@ -7,7 +7,9 @@ import java.util.Map; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class UtilsTest { @@ -24,17 +26,19 @@ public void testPrepareProcedure() { Assert.assertEquals("CALL prc()ka,kb", Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), kwargs)); } - + + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + + @Test public void prepareQuery() { Assert.assertEquals("query %s %d end of query", Utils.prepareQuery("query %s %d end of query")); Assert.assertEquals("query 'a' 33 end of query", Utils.prepareQuery("query %s %d end of query", "a", 33)); - - try { - Assert.assertEquals("CALL prc(\"a\",\"b\")ka,kb", Utils.prepareQuery("query %s %d end of query", "a", "b")); - Assert.fail(); - } catch (IllegalFormatConversionException e) {} + + exceptionRule.expect(IllegalFormatConversionException.class); + Assert.assertEquals("CAL prc(\"a\",\"b\")ka,kb", Utils.prepareQuery("query %s %d end of query", "a", "b")); } } From b6acce0c8ca0745fddce14121b7235f06f3c22e6 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 3 Sep 2019 13:13:37 +0300 Subject: [PATCH 028/128] removed deprecation --- .../java/com/redislabs/redisgraph/ResultSet.java | 12 ------------ .../redisgraph/graph_entities/Property.java | 15 +-------------- .../redisgraph/impl/resultset/ResultSetImpl.java | 2 +- 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index 9224b36..f14781e 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -9,18 +9,6 @@ public interface ResultSet extends Iterator { enum ResultSetScalarTypes { - @Deprecated - PROPERTY_UNKNOWN, - @Deprecated - PROPERTY_NULL, - @Deprecated - PROPERTY_STRING, - @Deprecated - PROPERTY_INTEGER, - @Deprecated - PROPERTY_BOOLEAN, - @Deprecated - PROPERTY_DOUBLE, VALUE_UNKNOWN, VALUE_NULL, VALUE_STRING, diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 786051c..19f6884 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -58,27 +58,14 @@ public void setName(String name) { */ @Deprecated public ResultSet.ResultSetScalarTypes getType() { - if (type.ordinal() >= 6 && type.ordinal() < 12){ - return ResultSet.ResultSetScalarTypes.values()[type.ordinal()-6]; - } return type; } - public ResultSet.ResultSetScalarTypes getValueType() { - return type; - } - - - /** * @param type property type to be set */ public void setType(ResultSet.ResultSetScalarTypes type) { - ResultSet.ResultSetScalarTypes actualType = type; - if (type.ordinal() < 6) { - actualType = ResultSet.ResultSetScalarTypes.values()[type.ordinal() + 6]; - } - this.type = actualType; + this.type = type; } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 7ee65cf..cd1b689 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -255,7 +255,7 @@ private List deserializeArray(Object rawScalarData) { * @return scalar type */ private ResultSetScalarTypes getValueTypeFromObject(Object rawScalarType) { - return ResultSetScalarTypes.values()[((Long) rawScalarType).intValue() + 6]; + return ResultSetScalarTypes.values()[((Long) rawScalarType).intValue()]; } @Override From 886bcd0ab6f402dd587ce30f23f8395820a4631b Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 3 Sep 2019 13:19:48 +0300 Subject: [PATCH 029/128] removed deprecation --- .../java/com/redislabs/redisgraph/graph_entities/Property.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 19f6884..1c7d427 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -56,7 +56,6 @@ public void setName(String name) { /** * @return property type */ - @Deprecated public ResultSet.ResultSetScalarTypes getType() { return type; } From 3f3167d6ebf4ecaad8769b90ea7aff485d0d0b33 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 4 Sep 2019 16:39:38 +0300 Subject: [PATCH 030/128] fix license link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a826bdc..276cd0c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![license](https://img.shields.io/github/license/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph) +[![license](https://img.shields.io/github/license/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph/blob/master/LICENSE) [![GitHub issues](https://img.shields.io/github/release/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph/releases/latest) [![CircleCI](https://circleci.com/gh/RedisGraph/JRedisGraph/tree/master.svg?style=svg)](https://circleci.com/gh/RedisGraph/JRedisGraph/tree/master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph) From 126151465ca6b88a453b50548deaac45f6a9f310 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 4 Sep 2019 18:57:01 +0300 Subject: [PATCH 031/128] changed property into a class template --- .../graph_entities/GraphEntity.java | 5 +- .../redisgraph/graph_entities/Property.java | 32 ++------ .../impl/resultset/ResultSetImpl.java | 1 - .../redisgraph/RedisGraphAPITest.java | 78 +++++++++---------- 4 files changed, 47 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index e913921..f40792f 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -42,12 +42,11 @@ public void setId(int id) { /** * Adds a property to the entity, by composing name, type and value to a property object * @param name - * @param type * @param value */ - public void addProperty(String name, ResultSetScalarTypes type, Object value){ + public void addProperty(String name, Object value){ - addProperty(new Property(name, type, value)); + addProperty(new Property(name, value)); } diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 1c7d427..c007555 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -7,13 +7,12 @@ /** * A Graph entity property. Has a name, type, and value */ -public class Property { +public class Property { //members private String name; - private ResultSet.ResultSetScalarTypes type; - private Object value; + private T value; /** @@ -27,12 +26,10 @@ public Property() { * Parameterized constructor * * @param name - * @param type * @param value */ - public Property(String name, ResultSet.ResultSetScalarTypes type, Object value) { + public Property(String name, T value) { this.name = name; - this.type = type; this.value = value; } @@ -53,26 +50,11 @@ public void setName(String name) { this.name = name; } - /** - * @return property type - */ - public ResultSet.ResultSetScalarTypes getType() { - return type; - } - - /** - * @param type property type to be set - */ - public void setType(ResultSet.ResultSetScalarTypes type) { - this.type = type; - } - - /** * @return property value */ - public Object getValue() { + public T getValue() { return value; } @@ -80,7 +62,7 @@ public Object getValue() { /** * @param value property value to be set */ - public void setValue(Object value) { + public void setValue(T value) { this.value = value; } @@ -91,13 +73,12 @@ public boolean equals(Object o) { if (!(o instanceof Property)) return false; Property property = (Property) o; return Objects.equals(name, property.name) && - type == property.type && Objects.equals(value, property.value); } @Override public int hashCode() { - return Objects.hash(name, type, value); + return Objects.hash(name, value); } /** @@ -108,7 +89,6 @@ public int hashCode() { public String toString() { final StringBuilder sb = new StringBuilder("Property{"); sb.append("name='").append(name).append('\''); - sb.append(", type=").append(type); sb.append(", value=").append(value); sb.append('}'); return sb.toString(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index cd1b689..46981f1 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -199,7 +199,6 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List propertyScalar = rawProperty.subList(1, rawProperty.size()); - property.setType(getValueTypeFromObject(propertyScalar.get(0))); property.setValue(deserializeScalar(propertyScalar)); entity.addProperty(property); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index a734ad7..e2be9e4 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -203,15 +203,15 @@ public void testRecord(){ - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); + Property nameProperty = new Property("name", name); + Property ageProperty = new Property("age", age); + Property doubleProperty = new Property("doubleValue", doubleValue); + Property trueBooleanProperty = new Property("boolValue", true); + Property falseBooleanProperty = new Property("boolValue", false); + Property nullProperty = new Property("nullValue", null); - Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); + Property placeProperty = new Property("place", place); + Property sinceProperty = new Property("since", since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -223,11 +223,11 @@ public void testRecord(){ expectedNode.addProperty(nullProperty); Assert.assertEquals( "Node{labels=[person], id=0, " - + "propertyMap={name=Property{name='name', type=VALUE_STRING, value=roi}, " - + "boolValue=Property{name='boolValue', type=VALUE_BOOLEAN, value=true}, " - + "doubleValue=Property{name='doubleValue', type=VALUE_DOUBLE, value=3.14}, " - + "nullValue=Property{name='nullValue', type=VALUE_NULL, value=null}, " - + "age=Property{name='age', type=VALUE_INTEGER, value=32}}}", expectedNode.toString()); + + "propertyMap={name=Property{name='name', value=roi}, " + + "boolValue=Property{name='boolValue', value=true}, " + + "doubleValue=Property{name='doubleValue', value=3.14}, " + + "nullValue=Property{name='nullValue', value=null}, " + + "age=Property{name='age', value=32}}}", expectedNode.toString()); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -240,11 +240,11 @@ public void testRecord(){ expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); Assert.assertEquals("Edge{relationshipType='knows', source=0, destination=1, id=0, " - + "propertyMap={boolValue=Property{name='boolValue', type=VALUE_BOOLEAN, value=false}, " - + "place=Property{name='place', type=VALUE_STRING, value=TLV}, " - + "doubleValue=Property{name='doubleValue', type=VALUE_DOUBLE, value=3.14}, " - + "nullValue=Property{name='nullValue', type=VALUE_NULL, value=null}, " - + "since=Property{name='since', type=VALUE_INTEGER, value=2000}}}", expectedEdge.toString()); + + "propertyMap={boolValue=Property{name='boolValue', value=false}, " + + "place=Property{name='place', value=TLV}, " + + "doubleValue=Property{name='doubleValue', value=3.14}, " + + "nullValue=Property{name='nullValue', value=null}, " + + "since=Property{name='since', value=2000}}}", expectedEdge.toString()); Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s,age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); @@ -332,9 +332,9 @@ public void testMultiThread(){ mapToObj(i-> api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")). collect(Collectors.toList()); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", "roi"); + Property ageProperty = new Property("age", 32); + Property lastNameProperty =new Property("lastName", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -426,9 +426,9 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); //expected objects init - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "roi"); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); - Property lastNameProperty =new Property("lastName", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", "roi"); + Property ageProperty = new Property("age", 32); + Property lastNameProperty =new Property("lastName", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -570,7 +570,7 @@ public void testMultiExec(){ Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); + Property nameProperty = new Property("name", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -629,15 +629,15 @@ public void testContextedAPI() { int since = 2000; - Property nameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, name); - Property ageProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, age); - Property doubleProperty = new Property("doubleValue", ResultSet.ResultSetScalarTypes.VALUE_DOUBLE, doubleValue); - Property trueBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, true); - Property falseBooleanProperty = new Property("boolValue", ResultSet.ResultSetScalarTypes.VALUE_BOOLEAN, false); - Property nullProperty = new Property("nullValue", ResultSet.ResultSetScalarTypes.VALUE_NULL, null); + Property nameProperty = new Property("name", name); + Property ageProperty = new Property("age", age); + Property doubleProperty = new Property("doubleValue", doubleValue); + Property trueBooleanProperty = new Property("boolValue", true); + Property falseBooleanProperty = new Property("boolValue", false); + Property nullProperty = new Property("nullValue", null); - Property placeProperty = new Property("place", ResultSet.ResultSetScalarTypes.VALUE_STRING, place); - Property sinceProperty = new Property("since", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, since); + Property placeProperty = new Property("place", place); + Property sinceProperty = new Property("since", since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -765,9 +765,9 @@ public void testArraySupport() { Node expectedANode = new Node(); expectedANode.setId(0); expectedANode.addLabel("person"); - Property aNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "a"); - Property aAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 32); - Property aListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(0,1,2)); + Property aNameProperty = new Property("name", "a"); + Property aAgeProperty = new Property("age", 32); + Property aListProperty = new Property("array", Arrays.asList(0,1,2)); expectedANode.addProperty(aNameProperty); expectedANode.addProperty(aAgeProperty); expectedANode.addProperty(aListProperty); @@ -776,9 +776,9 @@ public void testArraySupport() { Node expectedBNode = new Node(); expectedBNode.setId(1); expectedBNode.addLabel("person"); - Property bNameProperty = new Property("name", ResultSet.ResultSetScalarTypes.VALUE_STRING, "b"); - Property bAgeProperty = new Property("age", ResultSet.ResultSetScalarTypes.VALUE_INTEGER, 30); - Property bListProperty = new Property("array", ResultSet.ResultSetScalarTypes.VALUE_ARRAY, Arrays.asList(3,4,5)); + Property bNameProperty = new Property("name", "b"); + Property bAgeProperty = new Property("age", 30); + Property bListProperty = new Property("array", Arrays.asList(3,4,5)); expectedBNode.addProperty(bNameProperty); expectedBNode.addProperty(bAgeProperty); expectedBNode.addProperty(bListProperty); From fa4d2c0a575d665ed38ccfe67df5c33eaa8c6db8 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 4 Sep 2019 19:13:17 +0300 Subject: [PATCH 032/128] made response type enum package private. added static get value methid --- .../com/redislabs/redisgraph/ResultSet.java | 14 ----------- .../graph_entities/GraphEntity.java | 3 --- .../impl/resultset/ResultSetImpl.java | 8 +++++-- .../impl/resultset/ResultSetScalarTypes.java | 24 +++++++++++++++++++ 4 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index f14781e..a901594 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -7,20 +7,6 @@ */ public interface ResultSet extends Iterator { - - enum ResultSetScalarTypes { - VALUE_UNKNOWN, - VALUE_NULL, - VALUE_STRING, - VALUE_INTEGER, - VALUE_BOOLEAN, - VALUE_DOUBLE, - VALUE_ARRAY, - VALUE_EDGE, - VALUE_NODE - } - - int size(); Statistics getStatistics(); diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index f40792f..99120ba 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -1,8 +1,5 @@ package com.redislabs.redisgraph.graph_entities; - -import com.redislabs.redisgraph.ResultSet.ResultSetScalarTypes; - import java.util.*; diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 46981f1..6fa57fb 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -1,6 +1,10 @@ package com.redislabs.redisgraph.impl.resultset; -import com.redislabs.redisgraph.*; +import com.redislabs.redisgraph.Header; +import com.redislabs.redisgraph.Record; +import com.redislabs.redisgraph.RedisGraph; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.Statistics; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.GraphEntity; import com.redislabs.redisgraph.graph_entities.Node; @@ -254,7 +258,7 @@ private List deserializeArray(Object rawScalarData) { * @return scalar type */ private ResultSetScalarTypes getValueTypeFromObject(Object rawScalarType) { - return ResultSetScalarTypes.values()[((Long) rawScalarType).intValue()]; + return ResultSetScalarTypes.getValue(((Long) rawScalarType).intValue()); } @Override diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java new file mode 100644 index 0000000..5e3e193 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java @@ -0,0 +1,24 @@ +package com.redislabs.redisgraph.impl.resultset; + +import redis.clients.jedis.exceptions.JedisDataException; + +enum ResultSetScalarTypes { + VALUE_UNKNOWN, + VALUE_NULL, + VALUE_STRING, + VALUE_INTEGER, + VALUE_BOOLEAN, + VALUE_DOUBLE, + VALUE_ARRAY, + VALUE_EDGE, + VALUE_NODE; + + + static ResultSetScalarTypes[] values = values(); + + public static ResultSetScalarTypes getValue(int index) { + if (index < 0 || index > values.length) throw new JedisDataException("Unrecognized response type"); + return values[index]; + } + +} From 1850a9e13cfabd2c07f72d605a53495949319e72 Mon Sep 17 00:00:00 2001 From: Jeffrey Lovitz Date: Tue, 10 Sep 2019 18:53:33 -0400 Subject: [PATCH 033/128] Catch run-time and compile-time server exceptions --- .../redisgraph/impl/api/RedisGraph.java | 3 +++ .../impl/resultset/ResultSetImpl.java | 8 ++++++++ .../redisgraph/RedisGraphAPITest.java | 20 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index d3bea57..82086f4 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -67,6 +67,9 @@ protected ResultSet sendQuery(String graphId, String preparedQuery){ contextedRedisGraph.setRedisGraphCaches(caches); return contextedRedisGraph.sendQuery(graphId, preparedQuery); } + catch (Exception e) { + throw e; + } } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 6fa57fb..9c3c2e8 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -11,6 +11,7 @@ import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.exceptions.JedisDataException; import java.util.ArrayList; import java.util.List; @@ -35,6 +36,13 @@ public class ResultSetImpl implements ResultSet { public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache cache) { this.redisGraph = redisGraph; this.cache = cache; + + // If a run-time error occured, the last member of the rawResponse will be a JedisDataException. + if (rawResponse.get(rawResponse.size()-1) instanceof JedisDataException) { + + throw (JedisDataException)rawResponse.get(rawResponse.size() - 1); + } + if (rawResponse.size() != 3) { header = parseHeader(new ArrayList<>()); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index e2be9e4..a7dd81c 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -881,4 +881,24 @@ record = resultSet.next(); } } + + @Test + public void testErrorReporting() { + Assert.assertNotNull(api.query("social", "CREATE (:person{mixed_prop: 'strval'}), (:person{mixed_prop: 50})")); + + // Issue a query that causes a compile-time error + try { + api.query("social", "RETURN toUpper(5)"); + Assert.fail(); // should be unreachable + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Type mismatch")); + } + + // Issue a query that causes a run-time error + try { + api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Type mismatch")); + } + } } From b0ec1e260eafcaf889087db40deef73da07fa40f Mon Sep 17 00:00:00 2001 From: Jeffrey Lovitz Date: Wed, 11 Sep 2019 11:31:27 -0400 Subject: [PATCH 034/128] Address PR comments --- .../JRedisGraphCompileTimeError.java | 18 +++++++++++++ .../exceptions/JRedisGraphRunTimeError.java | 18 +++++++++++++ .../impl/api/ContextedRedisGraph.java | 8 ++++-- .../redisgraph/impl/api/RedisGraph.java | 3 --- .../impl/resultset/ResultSetImpl.java | 3 ++- .../redisgraph/RedisGraphAPITest.java | 25 +++++++++++-------- 6 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java create mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java new file mode 100644 index 0000000..af58364 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java @@ -0,0 +1,18 @@ +package com.redislabs.redisgraph.exceptions; + +import redis.clients.jedis.exceptions.JedisDataException; + + +public class JRedisGraphCompileTimeError extends JedisDataException { + public JRedisGraphCompileTimeError(String message) { + super(message); + } + + public JRedisGraphCompileTimeError(Throwable cause) { + super(cause); + } + + public JRedisGraphCompileTimeError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java new file mode 100644 index 0000000..d6957fc --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java @@ -0,0 +1,18 @@ +package com.redislabs.redisgraph.exceptions; + +import redis.clients.jedis.exceptions.JedisDataException; + + +public class JRedisGraphRunTimeError extends JedisDataException { + public JRedisGraphRunTimeError(String message) { + super(message); + } + + public JRedisGraphRunTimeError(Throwable cause) { + super(cause); + } + + public JRedisGraphRunTimeError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index b846925..e598013 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -2,17 +2,18 @@ import com.redislabs.redisgraph.RedisGraphContext; import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeError; import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; import redis.clients.jedis.util.SafeEncoder; - +import redis.clients.jedis.exceptions.JedisDataException; import java.util.List; /** - * An implementaion of RedisGraphContext. Allows sending RedisGraph and some Redis commands, + * An implementation of RedisGraphContext. Allows sending RedisGraph and some Redis commands, * within a specific connection context */ public class ContextedRedisGraph extends AbstractRedisGraph implements RedisGraphContext, RedisGraphCacheHolder { @@ -50,6 +51,9 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } + catch (JedisDataException j) { + throw new JRedisGraphCompileTimeError(j); + } catch (Exception e) { conn.close(); throw e; diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index 82086f4..d3bea57 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -67,9 +67,6 @@ protected ResultSet sendQuery(String graphId, String preparedQuery){ contextedRedisGraph.setRedisGraphCaches(caches); return contextedRedisGraph.sendQuery(graphId, preparedQuery); } - catch (Exception e) { - throw e; - } } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 9c3c2e8..fe87764 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -5,6 +5,7 @@ import com.redislabs.redisgraph.RedisGraph; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.Statistics; +import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeError; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.GraphEntity; import com.redislabs.redisgraph.graph_entities.Node; @@ -40,7 +41,7 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache // If a run-time error occured, the last member of the rawResponse will be a JedisDataException. if (rawResponse.get(rawResponse.size()-1) instanceof JedisDataException) { - throw (JedisDataException)rawResponse.get(rawResponse.size() - 1); + throw new JRedisGraphRunTimeError((Throwable) rawResponse.get(rawResponse.size() - 1)); } if (rawResponse.size() != 3) { diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index a7dd81c..fc14f40 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -20,6 +20,11 @@ import com.redislabs.redisgraph.Statistics.Label; import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; +import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeError; +import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeError; +import org.junit.Rule; +import org.junit.rules.ExpectedException; +import redis.clients.jedis.exceptions.JedisDataException; public class RedisGraphAPITest { private RedisGraphContextGenerator api; @@ -882,23 +887,21 @@ record = resultSet.next(); } + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + @Test public void testErrorReporting() { Assert.assertNotNull(api.query("social", "CREATE (:person{mixed_prop: 'strval'}), (:person{mixed_prop: 50})")); + exceptionRule.expect(JRedisGraphCompileTimeError.class); + exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); + // Issue a query that causes a compile-time error - try { - api.query("social", "RETURN toUpper(5)"); - Assert.fail(); // should be unreachable - } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Type mismatch")); - } + api.query("social", "RETURN toUpper(5)"); + exceptionRule.expect(JRedisGraphRunTimeError.class); // Issue a query that causes a run-time error - try { - api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); - } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Type mismatch")); - } + api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } } From 85cc0dcf2ef3ab0c8fba72c98d4a1d5edeafffb3 Mon Sep 17 00:00:00 2001 From: Jeffrey Lovitz Date: Wed, 11 Sep 2019 12:12:49 -0400 Subject: [PATCH 035/128] Fix overly-broad catch logic --- .../redislabs/redisgraph/impl/api/ContextedRedisGraph.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index e598013..cad0c39 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -3,6 +3,7 @@ import com.redislabs.redisgraph.RedisGraphContext; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeError; +import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeError; import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; @@ -51,7 +52,12 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } + catch (JRedisGraphRunTimeError rt) { + conn.close(); + throw rt; + } catch (JedisDataException j) { + conn.close(); throw new JRedisGraphCompileTimeError(j); } catch (Exception e) { From 7f54c562580e009982aa71f04a7d5a971063a702 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 12 Sep 2019 16:11:00 +0300 Subject: [PATCH 036/128] fixed design - connection should stay open on an exception --- .../redislabs/redisgraph/impl/api/ContextedRedisGraph.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index cad0c39..8706f57 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -53,17 +53,11 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } catch (JRedisGraphRunTimeError rt) { - conn.close(); throw rt; } catch (JedisDataException j) { - conn.close(); throw new JRedisGraphCompileTimeError(j); } - catch (Exception e) { - conn.close(); - throw e; - } } /** From c14484e3c96bbe1269b5ce0273dcfd15164f17df Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 12 Sep 2019 16:12:24 +0300 Subject: [PATCH 037/128] moved exception testing to different file. added context connection testing. --- .../redisgraph/RedisGraphAPITest.java | 26 ---- .../exceptions/JRedisGraphErrorTest.java | 129 ++++++++++++++++++ 2 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index fc14f40..22cdf28 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -20,11 +20,6 @@ import com.redislabs.redisgraph.Statistics.Label; import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; -import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeError; -import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeError; -import org.junit.Rule; -import org.junit.rules.ExpectedException; -import redis.clients.jedis.exceptions.JedisDataException; public class RedisGraphAPITest { private RedisGraphContextGenerator api; @@ -589,10 +584,6 @@ public void testMultiExec(){ Assert.assertEquals(Arrays.asList("n"), record.keys()); Assert.assertEquals(expectedNode, record.getValue("n")); - // Graph delete - Assert.assertTrue(((String)results.get(6)).startsWith("Graph removed")); - - Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); resultSet = (ResultSet) results.get(7); @@ -887,21 +878,4 @@ record = resultSet.next(); } - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); - - @Test - public void testErrorReporting() { - Assert.assertNotNull(api.query("social", "CREATE (:person{mixed_prop: 'strval'}), (:person{mixed_prop: 50})")); - - exceptionRule.expect(JRedisGraphCompileTimeError.class); - exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); - - // Issue a query that causes a compile-time error - api.query("social", "RETURN toUpper(5)"); - - exceptionRule.expect(JRedisGraphRunTimeError.class); - // Issue a query that causes a run-time error - api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); - } } diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java new file mode 100644 index 0000000..8ec1c3b --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -0,0 +1,129 @@ +package com.redislabs.redisgraph.exceptions; + +import com.redislabs.redisgraph.RedisGraphContext; +import com.redislabs.redisgraph.RedisGraphContextGenerator; +import com.redislabs.redisgraph.impl.api.RedisGraph; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + + +public class JRedisGraphErrorTest { + + private RedisGraphContextGenerator api; + + @Before + public void createApi(){ + api = new RedisGraph(); + Assert.assertNotNull(api.query("social", "CREATE (:person{mixed_prop: 'strval'}), (:person{mixed_prop: 50})")); + } + @After + public void deleteGraph() { + + api.deleteGraph("social"); + api.close(); + } + + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + + @Test + public void testSyntaxErrorReporting() { + exceptionRule.expect(JRedisGraphCompileTimeError.class); + exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); + + // Issue a query that causes a compile-time error + api.query("social", "RETURN toUpper(5)"); + + } + + @Test + public void testRuntimeErrorReporting() { + exceptionRule.expect(JRedisGraphRunTimeError.class); + exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); + + // Issue a query that causes a run-time error + api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); + } + + @Test + public void testExceptionFlow() { + + try { + // Issue a query that causes a compile-time error + api.query("social", "RETURN toUpper(5)"); + } + catch (Exception e) { + Assert.assertEquals(JRedisGraphCompileTimeError.class, e.getClass()); + Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + } + + // On general api usage, user should get a new connection + + try { + // Issue a query that causes a compile-time error + api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); + } + catch (Exception e) { + Assert.assertEquals(JRedisGraphRunTimeError.class, e.getClass()); + Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + } + + } + + + @Test + public void testContextSyntaxErrorReporting() { + exceptionRule.expect(JRedisGraphCompileTimeError.class); + exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); + RedisGraphContext c = api.getContext(); + + // Issue a query that causes a compile-time error + c.query("social", "RETURN toUpper(5)"); + + } + + @Test + public void testContextRuntimeErrorReporting() { + exceptionRule.expect(JRedisGraphRunTimeError.class); + exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); + + RedisGraphContext c = api.getContext(); + // Issue a query that causes a run-time error + c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); + } + + + + + @Test + public void testContextExceptionFlow() { + + RedisGraphContext c = api.getContext(); + try { + // Issue a query that causes a compile-time error + c.query("social", "RETURN toUpper(5)"); + } + catch (Exception e) { + Assert.assertEquals(JRedisGraphCompileTimeError.class, e.getClass()); + Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + } + + // On contexted api usage, connection should stay open + + try { + // Issue a query that causes a compile-time error + c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); + } + catch (Exception e) { + Assert.assertEquals(JRedisGraphRunTimeError.class, e.getClass()); + Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + } + + } + + +} \ No newline at end of file From c61a5eb458ca5b4df359064355c22cd3fa19d2fe Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 12 Sep 2019 22:20:12 +0300 Subject: [PATCH 038/128] refactor - rename from error to exception. added JDoc --- .../JRedisGraphCompileTimeError.java | 18 --------------- .../JRedisGraphCompileTimeException.java | 21 ++++++++++++++++++ .../exceptions/JRedisGraphRunTimeError.java | 18 --------------- .../JRedisGraphRunTimeException.java | 21 ++++++++++++++++++ .../impl/api/ContextedRedisGraph.java | 8 +++---- .../impl/resultset/ResultSetImpl.java | 4 ++-- .../exceptions/JRedisGraphErrorTest.java | 22 ++++++++----------- 7 files changed, 57 insertions(+), 55 deletions(-) delete mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java create mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java delete mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java create mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java deleted file mode 100644 index af58364..0000000 --- a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeError.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.redislabs.redisgraph.exceptions; - -import redis.clients.jedis.exceptions.JedisDataException; - - -public class JRedisGraphCompileTimeError extends JedisDataException { - public JRedisGraphCompileTimeError(String message) { - super(message); - } - - public JRedisGraphCompileTimeError(Throwable cause) { - super(cause); - } - - public JRedisGraphCompileTimeError(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java new file mode 100644 index 0000000..1574147 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java @@ -0,0 +1,21 @@ +package com.redislabs.redisgraph.exceptions; + +import redis.clients.jedis.exceptions.JedisDataException; + +/** + * RedisGraph query syntax evaluation exception. An instance of JRedisGraphRunTimeException is thrown when RedisGraph + * encounters an error during query syntax evaluation. + */ +public class JRedisGraphCompileTimeException extends JedisDataException { + public JRedisGraphCompileTimeException(String message) { + super(message); + } + + public JRedisGraphCompileTimeException(Throwable cause) { + super(cause); + } + + public JRedisGraphCompileTimeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java deleted file mode 100644 index d6957fc..0000000 --- a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeError.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.redislabs.redisgraph.exceptions; - -import redis.clients.jedis.exceptions.JedisDataException; - - -public class JRedisGraphRunTimeError extends JedisDataException { - public JRedisGraphRunTimeError(String message) { - super(message); - } - - public JRedisGraphRunTimeError(Throwable cause) { - super(cause); - } - - public JRedisGraphRunTimeError(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java new file mode 100644 index 0000000..62d083f --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java @@ -0,0 +1,21 @@ +package com.redislabs.redisgraph.exceptions; + +import redis.clients.jedis.exceptions.JedisDataException; + +/** + * RedisGraph runtime exception. An instance of JRedisGraphRunTimeException is thrown when RedisGraph + * encounters a runtime error during query execution. + */ +public class JRedisGraphRunTimeException extends JedisDataException { + public JRedisGraphRunTimeException(String message) { + super(message); + } + + public JRedisGraphRunTimeException(Throwable cause) { + super(cause); + } + + public JRedisGraphRunTimeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index 8706f57..ab92534 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -2,8 +2,8 @@ import com.redislabs.redisgraph.RedisGraphContext; import com.redislabs.redisgraph.ResultSet; -import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeError; -import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeError; +import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeException; +import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException; import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; @@ -52,11 +52,11 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } - catch (JRedisGraphRunTimeError rt) { + catch (JRedisGraphRunTimeException rt) { throw rt; } catch (JedisDataException j) { - throw new JRedisGraphCompileTimeError(j); + throw new JRedisGraphCompileTimeException(j); } } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index fe87764..fdcdf66 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -5,7 +5,7 @@ import com.redislabs.redisgraph.RedisGraph; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.Statistics; -import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeError; +import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.GraphEntity; import com.redislabs.redisgraph.graph_entities.Node; @@ -41,7 +41,7 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache // If a run-time error occured, the last member of the rawResponse will be a JedisDataException. if (rawResponse.get(rawResponse.size()-1) instanceof JedisDataException) { - throw new JRedisGraphRunTimeError((Throwable) rawResponse.get(rawResponse.size() - 1)); + throw new JRedisGraphRunTimeException((Throwable) rawResponse.get(rawResponse.size() - 1)); } if (rawResponse.size() != 3) { diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index 8ec1c3b..5b0be9e 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -32,7 +32,7 @@ public void deleteGraph() { @Test public void testSyntaxErrorReporting() { - exceptionRule.expect(JRedisGraphCompileTimeError.class); + exceptionRule.expect(JRedisGraphCompileTimeException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); // Issue a query that causes a compile-time error @@ -42,7 +42,7 @@ public void testSyntaxErrorReporting() { @Test public void testRuntimeErrorReporting() { - exceptionRule.expect(JRedisGraphRunTimeError.class); + exceptionRule.expect(JRedisGraphRunTimeException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); // Issue a query that causes a run-time error @@ -57,7 +57,7 @@ public void testExceptionFlow() { api.query("social", "RETURN toUpper(5)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphCompileTimeError.class, e.getClass()); + Assert.assertEquals(JRedisGraphCompileTimeException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -68,7 +68,7 @@ public void testExceptionFlow() { api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphRunTimeError.class, e.getClass()); + Assert.assertEquals(JRedisGraphRunTimeException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -77,7 +77,7 @@ public void testExceptionFlow() { @Test public void testContextSyntaxErrorReporting() { - exceptionRule.expect(JRedisGraphCompileTimeError.class); + exceptionRule.expect(JRedisGraphCompileTimeException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); RedisGraphContext c = api.getContext(); @@ -88,7 +88,7 @@ public void testContextSyntaxErrorReporting() { @Test public void testContextRuntimeErrorReporting() { - exceptionRule.expect(JRedisGraphRunTimeError.class); + exceptionRule.expect(JRedisGraphRunTimeException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); RedisGraphContext c = api.getContext(); @@ -97,8 +97,6 @@ public void testContextRuntimeErrorReporting() { } - - @Test public void testContextExceptionFlow() { @@ -108,7 +106,7 @@ public void testContextExceptionFlow() { c.query("social", "RETURN toUpper(5)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphCompileTimeError.class, e.getClass()); + Assert.assertEquals(JRedisGraphCompileTimeException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -119,11 +117,9 @@ public void testContextExceptionFlow() { c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphRunTimeError.class, e.getClass()); + Assert.assertEquals(JRedisGraphRunTimeException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } } - - -} \ No newline at end of file +} From 9ec317bf547b16128d0c2aaeafe94f0c965aa483 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 14 Oct 2019 23:10:08 +0300 Subject: [PATCH 039/128] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 276cd0c..0d3ea21 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ [![Javadocs](https://www.javadoc.io/badge/com.redislabs/jredisgraph.svg)](https://www.javadoc.io/doc/com.redislabs/jredisgraph) [![Codecov](https://codecov.io/gh/RedisGraph/JRedisGraph/branch/master/graph/badge.svg)](https://codecov.io/gh/RedisGraph/JRedisGraph) +[![Mailing List](https://img.shields.io/badge/Mailing%20List-RedisGraph-blue)](https://groups.google.com/forum/#!forum/redisgraph) +[![Gitter](https://badges.gitter.im/RedisLabs/RedisGraph.svg)](https://gitter.im/RedisLabs/RedisGraph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + # JRedisGraph RedisGraph Java client From 1518a2e323a36dfc8c798791b7405fc975668f10 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 3 Nov 2019 17:51:45 +0200 Subject: [PATCH 040/128] added path support (#52) * added path support * added path builder * added example to readme.md --- README.md | 10 ++ pom.xml | 20 ++- .../redisgraph/graph_entities/Path.java | 118 ++++++++++++++++++ .../impl/resultset/ResultSetImpl.java | 14 ++- .../impl/resultset/ResultSetScalarTypes.java | 3 +- .../redisgraph/RedisGraphAPITest.java | 56 +++++++-- .../redisgraph/graph_entities/PathTest.java | 78 ++++++++++++ .../redisgraph/test/utils/PathBuilder.java | 50 ++++++++ .../test/utils/PathBuilderTest.java | 28 +++++ 9 files changed, 364 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/graph_entities/Path.java create mode 100644 src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java create mode 100644 src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java create mode 100644 src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java diff --git a/README.md b/README.md index 0d3ea21..c2d3332 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ package com.redislabs.redisgraph; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; +import com.redislabs.redisgraph.graph_entities.Path; import com.redislabs.redisgraph.impl.api.RedisGraph; import java.util.List; @@ -115,6 +116,15 @@ public class RedisGraphExample { System.out.println(record.toString()); } + resultSet = graph.query("social", "MATCH p = (:person)-[:knows]->(:person) RETURN p"); + while(resultSet.hasNext()) { + Record record = resultSet.next(); + Path p = record.getValue("p"); + + // More path API at Javadoc. + System.out.println(p.nodeCount()); + } + // delete graph graph.deleteGraph("social"); diff --git a/pom.xml b/pom.xml index 2b2c133..c137ec9 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,25 @@ 1.6.6 test - + + org.junit.jupiter + junit-jupiter + RELEASE + test + + + org.junit.jupiter + junit-jupiter + RELEASE + test + + + nl.jqno.equalsverifier + equalsverifier + 3.1.10 + test + + 8 8 diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java new file mode 100644 index 0000000..fa86484 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java @@ -0,0 +1,118 @@ +package com.redislabs.redisgraph.graph_entities; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * This class represents a path in the graph. + */ +public final class Path { + + private final List nodes; + private final List edges; + + + /** + * Parametrized constructor + * @param nodes - List of nodes. + * @param edges - List of edges. + */ + public Path(List nodes, List edges) { + this.nodes = nodes; + this.edges = edges; + } + + /** + * Returns the nodes of the path. + * @return List of nodes. + */ + public List getNodes() { + return nodes; + } + + /** + * Returns the edges of the path. + * @return List of edges. + */ + public List getEdges() { + return edges; + } + + /** + * Returns the length of the path - number of edges. + * @return Number of edges. + */ + public int length() { + return edges.size(); + } + + /** + * Return the number of nodes in the path. + * @return Number of nodes. + */ + public int nodeCount(){ + return nodes.size(); + } + + /** + * Returns the first node in the path. + * @return First nodes in the path. + * @throws IndexOutOfBoundsException if the path is empty. + */ + public Node firstNode(){ + return nodes.get(0); + } + + /** + * Returns the last node in the path. + * @return Last nodes in the path. + * @throws IndexOutOfBoundsException if the path is empty. + */ + public Node lastNode(){ + return nodes.get(nodes.size() - 1); + } + + /** + * Returns a node with specified index in the path. + * @return Node. + * @throws IndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= nodesCount()}) + */ + public Node getNode(int index){ + return nodes.get(index); + } + + /** + * Returns an edge with specified index in the path. + * @return Edge. + * @throws IndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= length()}) + */ + public Edge getEdge(int index){ + return edges.get(index); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Path path = (Path) o; + return Objects.equals(nodes, path.nodes) && + Objects.equals(edges, path.edges); + } + + @Override + public int hashCode() { + return Objects.hash(nodes, edges); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("Path{"); + sb.append("nodes=").append(nodes); + sb.append(", edges=").append(edges); + sb.append('}'); + return sb.toString(); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index fdcdf66..442573b 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -6,10 +6,7 @@ import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.Statistics; import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException; -import com.redislabs.redisgraph.graph_entities.Edge; -import com.redislabs.redisgraph.graph_entities.GraphEntity; -import com.redislabs.redisgraph.graph_entities.Node; -import com.redislabs.redisgraph.graph_entities.Property; +import com.redislabs.redisgraph.graph_entities.*; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.exceptions.JedisDataException; @@ -245,12 +242,21 @@ private Object deserializeScalar(List rawScalarData) { return deserializeNode((List) obj); case VALUE_EDGE: return deserializeEdge((List) obj); + case VALUE_PATH: + return deserializePath(obj); case VALUE_UNKNOWN: default: return obj; } } + private Path deserializePath(Object rawScalarData) { + List> array = (List>) rawScalarData; + List nodes = (List) deserializeScalar(array.get(0)); + List edges = (List) deserializeScalar(array.get(1)); + return new Path(nodes, edges); + } + private List deserializeArray(Object rawScalarData) { List> array = (List>) rawScalarData; List res = new ArrayList<>(array.size()); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java index 5e3e193..8d40aff 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java @@ -11,7 +11,8 @@ enum ResultSetScalarTypes { VALUE_DOUBLE, VALUE_ARRAY, VALUE_EDGE, - VALUE_NODE; + VALUE_NODE, + VALUE_PATH; static ResultSetScalarTypes[] values = values(); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 22cdf28..abb78a9 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -1,27 +1,26 @@ package com.redislabs.redisgraph; -import java.util.Arrays; -import java.util.List; -import java.util.NoSuchElementException; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; +import com.redislabs.redisgraph.graph_entities.Path; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import com.redislabs.redisgraph.test.utils.PathBuilder; +import org.junit.*; import com.redislabs.redisgraph.Statistics.Label; +import org.junit.rules.ExpectedException; import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; public class RedisGraphAPITest { + private RedisGraphContextGenerator api; public RedisGraphAPITest() { @@ -878,4 +877,47 @@ record = resultSet.next(); } + @Test + public void testPath(){ + List nodes = new ArrayList<>(3); + for(int i =0; i < 3; i++){ + Node node = new Node(); + node.setId(i); + node.addLabel("L1"); + nodes.add(node); + } + + List edges = new ArrayList<>(2); + for(int i =0; i <2; i++){ + Edge edge = new Edge(); + edge.setId(i); + edge.setRelationshipType("R1"); + edge.setSource(i); + edge.setDestination(i + 1); + edges.add(edge); + } + + Set expectedPaths = new HashSet<>(); + + Path path01 = new PathBuilder(2).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)).build(); + Path path12 = new PathBuilder(2).append(nodes.get(1)).append(edges.get(1)).append(nodes.get(2)).build(); + Path path02 = new PathBuilder(3).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)).append(edges.get(1)).append(nodes.get(2)).build(); + + expectedPaths.add(path01); + expectedPaths.add(path12); + expectedPaths.add(path02); + + api.query("social", "CREATE (:L1)-[:R1]->(:L1)-[:R1]->(:L1)"); + + ResultSet resultSet = api.query("social", "MATCH p = (:L1)-[:R1*]->(:L1) RETURN p"); + + Assert.assertEquals(expectedPaths.size(), resultSet.size()); + for(int i =0; i < resultSet.size(); i++){ + Path p = resultSet.next().getValue("p"); + Assert.assertTrue(expectedPaths.contains(p)); + expectedPaths.remove(p); + } + + } + } diff --git a/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java b/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java new file mode 100644 index 0000000..74581b3 --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java @@ -0,0 +1,78 @@ +package com.redislabs.redisgraph.graph_entities; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.*; + +public class PathTest { + + private Node buildNode(int id){ + Node n = new Node(); + n.setId(0); + return n; + } + + private Edge buildEdge(int id, int src, int dst){ + Edge e = new Edge(); + e.setId(id); + e.setSource(src); + e.setDestination(dst); + return e; + } + + private List buildNodeArray(int size) { + List nodes = new ArrayList<>(); + return IntStream.range(0, size).mapToObj(i -> buildNode(i)).collect(Collectors.toList()); + } + + private List buildEdgeArray(int size){ + List nodes = new ArrayList<>(); + return IntStream.range(0, size).mapToObj(i -> buildEdge(i, i, i+1)).collect(Collectors.toList()); + } + + private Path buildPath(int nodeCount){ + return new Path(buildNodeArray(nodeCount), buildEdgeArray(nodeCount-1)); + } + + @Test + public void testEmptyPath(){ + Path path = buildPath(0); + assertEquals(0, path.length()); + assertEquals(0, path.nodeCount()); + assertThrows(IndexOutOfBoundsException.class, ()->path.getNode(0)); + assertThrows(IndexOutOfBoundsException.class, ()->path.getEdge(0)); + } + + @Test + public void testSingleNodePath(){ + Path path = buildPath(1); + assertEquals(0, path.length()); + assertEquals(1, path.nodeCount()); + Node n = new Node(); + n.setId(0); + assertEquals(n, path.firstNode()); + assertEquals(n, path.lastNode()); + assertEquals(n, path.getNode(0)); + } + + @Test + public void testRandomLengthPath(){ + int nodeCount = ThreadLocalRandom.current().nextInt(2, 100 + 1); + Path path = buildPath(nodeCount); + assertEquals(buildNodeArray(nodeCount), path.getNodes()); + assertEquals(buildEdgeArray(nodeCount-1), path.getEdges()); + assertDoesNotThrow(()->path.getEdge(0)); + } + + @Test + public void hashCodeEqualTest(){ + EqualsVerifier.forClass(Path.class).verify(); + } +} \ No newline at end of file diff --git a/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java new file mode 100644 index 0000000..64de9c7 --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java @@ -0,0 +1,50 @@ +package com.redislabs.redisgraph.test.utils; + +import com.redislabs.redisgraph.graph_entities.Edge; +import com.redislabs.redisgraph.graph_entities.Node; +import com.redislabs.redisgraph.graph_entities.Path; + +import java.util.ArrayList; +import java.util.List; + +public final class PathBuilder{ + private final List nodes; + private final List edges; + private Class currentAppendClass; + + public PathBuilder() { + this.nodes = new ArrayList<>(0); + this.edges = new ArrayList<>(0); + currentAppendClass = Node.class; + } + + public PathBuilder(int nodesCount){ + nodes = new ArrayList<>(nodesCount); + edges = new ArrayList<>(nodesCount-1 >= 0 ? nodesCount -1 : 0); + currentAppendClass = Node.class; + } + + public PathBuilder append(Object object){ + Class c = object.getClass(); + if(!currentAppendClass.equals(c)) throw new IllegalArgumentException("Path Builder expected " + currentAppendClass.getSimpleName() + " but was " + c.getSimpleName()); + if(c.equals(Node.class)) return appendNode((Node)object); + else return appendEdge((Edge)object); + } + + private PathBuilder appendEdge(Edge edge) { + edges.add(edge); + currentAppendClass = Node.class; + return this; + } + + private PathBuilder appendNode(Node node){ + nodes.add(node); + currentAppendClass = Edge.class; + return this; + } + + public Path build(){ + if(nodes.size() != edges.size() + 1) throw new IllegalArgumentException("Path builder nodes count should be edge count + 1"); + return new Path(nodes, edges); + } +} diff --git a/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java new file mode 100644 index 0000000..01751eb --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java @@ -0,0 +1,28 @@ +package com.redislabs.redisgraph.test.utils; + +import com.redislabs.redisgraph.graph_entities.Edge; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class PathBuilderTest { + + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + + @Test + public void testPathBuilderSizeException(){ + exceptionRule.expect(IllegalArgumentException.class); + exceptionRule.expectMessage("Path builder nodes count should be edge count + 1"); + PathBuilder builder = new PathBuilder(0); + builder.build(); + } + + @Test + public void testPathBuilderArgumentsException(){ + exceptionRule.expect(IllegalArgumentException.class); + exceptionRule.expectMessage("Path Builder expected Node but was Edge"); + PathBuilder builder = new PathBuilder(0); + builder.append(new Edge()); + } +} From 5ef0b2cfbcdeb2480decd3dd21064952b4a30ea0 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Sun, 24 Nov 2019 22:00:07 +0200 Subject: [PATCH 041/128] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c2d3332..9419c0a 100644 --- a/README.md +++ b/README.md @@ -150,3 +150,6 @@ public class RedisGraphExample { } ``` + +## License +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FRedisGraph%2FJRedisGraph.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FRedisGraph%2FJRedisGraph?ref=badge_large) From a2b420277205e43615299da57df7663423651b7e Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 26 Nov 2019 06:41:49 +0200 Subject: [PATCH 042/128] added params support (#54) --- README.md | 12 +++-- .../com/redislabs/redisgraph/RedisGraph.java | 20 +++++++ .../com/redislabs/redisgraph/impl/Utils.java | 53 +++++++++++++++++-- .../impl/api/AbstractRedisGraph.java | 24 +++++++++ .../redisgraph/RedisGraphAPITest.java | 33 +++++++++++- .../exceptions/JRedisGraphErrorTest.java | 16 ++++++ .../redislabs/redisgraph/impl/UtilsTest.java | 35 ++++++++++-- 7 files changed, 177 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 9419c0a..8c33a32 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,13 @@ public class RedisGraphExample { // general context api. Not bound to graph key or connection RedisGraph graph = new RedisGraph(); - // send queries to a specific graph called "social" - graph.query("social","CREATE (:person{name:'roi',age:32})"); - graph.query("social","CREATE (:person{name:%s,age:%d})", "amit", 30); + Map params = new HashMap<>(); + params.put("age", 30); + params.put("name", "amit"); + + // send queries to a specific graph called "social" + graph.query("social","CREATE (:person{name:'roi',age:32})"); + graph.query("social","CREATE (:person{name:$name,age:$age})", params); graph.query("social","MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); ResultSet resultSet = graph.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); @@ -131,7 +135,7 @@ public class RedisGraphExample { // get connection context - closable object try(RedisGraphContext context = graph.getContext()) { context.query("contextSocial","CREATE (:person{name:'roi',age:32})"); - context.query("contextSocial","CREATE (:person{name:%s,age:%d})", "amit", 30); + context.query("social","CREATE (:person{name:$name,age:$age})", params); context.query("contextSocial", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); // WATCH/MULTI/EXEC context.watch("contextSocial"); diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index 25c4718..e672666 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -6,15 +6,35 @@ public interface RedisGraph extends Closeable { + /** + * Execute a Cypher query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a result set + */ + ResultSet query(String graphId, String query); + + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on * @param query Cypher query * @param args * @return a result set + * @deprecated use {@link #query(String, String, Map)} instead. */ + @Deprecated ResultSet query(String graphId, String query, Object ...args); + /** + * Executes a cypher query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a result set. + */ + ResultSet query(String graphId, String query, Map params); + /** * Invokes stored procedures without arguments * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index bb39c5b..dbc746a 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -4,11 +4,7 @@ import org.apache.commons.text.translate.CharSequenceTranslator; import org.apache.commons.text.translate.LookupTranslator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -50,12 +46,15 @@ private static String quoteString(String str){ return sb.toString(); } + /** * Prepare and formats a query and query arguments * @param query - query * @param args - query arguments * @return formatted query + * @deprecated use {@link #prepareQuery(String, Map)} instead. */ + @Deprecated public static String prepareQuery(String query, Object ...args){ if(args.length > 0) { for(int i=0; i params){ + StringBuilder sb = new StringBuilder("CYPHER "); + for(Map.Entry entry : params.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + sb.append(key).append('='); + sb.append(valueToString(value)); + sb.append(' '); + } + sb.append(query); + return sb.toString(); + } + + private static String arrayToString(Object[] arr) { + StringBuilder sb = new StringBuilder().append('['); + sb.append(String.join(", ", Arrays.stream(arr).map(obj->valueToString(obj)).collect(Collectors.toList()))); + sb.append(']'); + return sb.toString(); + } + + private static String valueToString(Object value) { + if(value == null) + return "null"; + if(String.class.isInstance(value)){ + return quoteString((String) value); + } + + if(value.getClass().isArray()){ + return arrayToString((Object[]) value); + + } + if(List.class.isInstance(value)){ + List list = (List)value; + return arrayToString(list.toArray()); + } + return value.toString(); + } + /** * Prepare and format a procedure call and its arguments * @param procedure - procedure to invoke diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java index d659b22..dec71f5 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -29,18 +29,42 @@ public abstract class AbstractRedisGraph implements RedisGraph { */ protected abstract ResultSet sendQuery(String graphId, String preparedQuery); + /** + * Execute a Cypher query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a result set + */ + public ResultSet query(String graphId, String query) { + return sendQuery(graphId, query); + } + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on * @param query Cypher query * @param args * @return a result set + * @deprecated use {@link #query(String, String, Map)} instead. */ + @Deprecated public ResultSet query(String graphId, String query, Object ...args) { String preparedQuery = Utils.prepareQuery(query, args); return sendQuery(graphId, preparedQuery); } + /** + * Executes a cypher query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a result set. + */ + public ResultSet query(String graphId, String query, Map params) { + String preparedQuery = Utils.prepareQuery(query, params); + return sendQuery(graphId, preparedQuery); + } + public ResultSet callProcedure(String graphId, String procedure){ return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index abb78a9..0e8a2b6 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -245,7 +245,13 @@ public void testRecord(){ + "nullValue=Property{name='nullValue', value=null}, " + "since=Property{name='since', value=2000}}}", expectedEdge.toString()); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:%s,age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); + Map params = new HashMap<>(); + params.put("name", name); + params.put("age", age); + params.put("boolValue", boolValue); + params.put("doubleValue", doubleValue); + + Assert.assertNotNull(api.query("social", "CREATE (:person{name:$name,age:$age, doubleValue:$doubleValue, boolValue:$boolValue, nullValue:null})", params)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); @@ -654,8 +660,13 @@ public void testContextedAPI() { expectedEdge.addProperty(falseBooleanProperty); expectedEdge.addProperty(nullProperty); + Map params = new HashMap<>(); + params.put("name", name); + params.put("age", age); + params.put("boolValue", boolValue); + params.put("doubleValue", doubleValue); try (RedisGraphContext c = api.getContext()) { - Assert.assertNotNull(c.query("social", "CREATE (:person{name:%s,age:%d, doubleValue:%f, boolValue:%b, nullValue:null})", name, age, doubleValue, boolValue)); + Assert.assertNotNull(c.query("social", "CREATE (:person{name:$name, age:$age, doubleValue:$doubleValue, boolValue:$boolValue, nullValue:null})", params)); Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); @@ -920,4 +931,22 @@ public void testPath(){ } + @Test + public void testParameters(){ + Object[] parameters = {1, 2.3, true, false, null, "str", Arrays.asList(1,2,3), new Integer[]{1,2,3}}; + Map param = new HashMap<>(); + for (int i=0; i < parameters.length; i++) { + Object expected = parameters[i]; + param.put("param", expected); + ResultSet resultSet = api.query("social", "RETURN $param", param); + Assert.assertEquals(1, resultSet.size()); + Record r = resultSet.next(); + Object o = r.getValue(0); + if(i == parameters.length-1) { + expected = Arrays.asList((Object[])expected); + } + Assert.assertEquals(expected, o); + } + } + } diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index 5b0be9e..c7a6862 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -10,6 +10,8 @@ import org.junit.Test; import org.junit.rules.ExpectedException; +import java.util.HashMap; + public class JRedisGraphErrorTest { @@ -86,6 +88,20 @@ public void testContextSyntaxErrorReporting() { } + @Test + public void testMissingParametersSyntaxErrorReporting(){ + exceptionRule.expect(JRedisGraphCompileTimeException.class); + exceptionRule.expectMessage("Missing parameters"); + api.query("social","RETURN $param"); + } + + @Test + public void testMissingParametersSyntaxErrorReporting2(){ + exceptionRule.expect(JRedisGraphCompileTimeException.class); + exceptionRule.expectMessage("Missing parameters"); + api.query("social","RETURN $param", new HashMap<>()); + } + @Test public void testContextRuntimeErrorReporting() { exceptionRule.expect(JRedisGraphRunTimeException.class); diff --git a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java index e6b8228..9caed94 100644 --- a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java +++ b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java @@ -1,10 +1,6 @@ package com.redislabs.redisgraph.impl; -import java.util.Arrays; -import java.util.HashMap; -import java.util.IllegalFormatConversionException; -import java.util.List; -import java.util.Map; +import java.util.*; import org.junit.Assert; import org.junit.Rule; @@ -41,4 +37,33 @@ public void prepareQuery() { Assert.assertEquals("CAL prc(\"a\",\"b\")ka,kb", Utils.prepareQuery("query %s %d end of query", "a", "b")); } + @Test + public void testParamsPrep(){ + Map params = new HashMap<>(); + params.put("param", 1); + Assert.assertEquals("CYPHER param=1 RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", 2.3); + Assert.assertEquals("CYPHER param=2.3 RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", true); + Assert.assertEquals("CYPHER param=true RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", false); + Assert.assertEquals("CYPHER param=false RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", null); + Assert.assertEquals("CYPHER param=null RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "str"); + Assert.assertEquals("CYPHER param=\"str\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + Integer arr[] = {1,2,3}; + params.put("param", arr); + Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); + List list = Arrays.asList(1,2,3); + params.put("param", list); + Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); + String strArr[] = {"1", "2", "3"}; + params.put("param", strArr); + Assert.assertEquals("CYPHER param=[\"1\", \"2\", \"3\"] RETURN $param", Utils.prepareQuery("RETURN $param", params)); + List stringList = Arrays.asList("1", "2", "3"); + params.put("param", stringList); + Assert.assertEquals("CYPHER param=[\"1\", \"2\", \"3\"] RETURN $param", Utils.prepareQuery("RETURN $param", params)); + } + } From 26553596908cf7ce8ebd53fd68e829db5c259b61 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 15 Dec 2019 10:18:24 +0200 Subject: [PATCH 043/128] comply to 1.99.7 index operations reponses (#56) * comply to 1.99.7 index operations reponses * comply to 1.99.7 index create and delete response --- .../java/com/redislabs/redisgraph/Statistics.java | 5 ++++- .../redisgraph/impl/resultset/StatisticsImpl.java | 3 +++ .../com/redislabs/redisgraph/RedisGraphAPITest.java | 11 ++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/Statistics.java b/src/main/java/com/redislabs/redisgraph/Statistics.java index 10f4772..7c8f286 100644 --- a/src/main/java/com/redislabs/redisgraph/Statistics.java +++ b/src/main/java/com/redislabs/redisgraph/Statistics.java @@ -8,7 +8,8 @@ public interface Statistics { */ enum Label{ LABELS_ADDED("Labels added"), - INDICES_ADDED("Indices added"), + INDICES_ADDED("Indices created"), + INDICES_DELETED("Indices deleted"), NODES_CREATED("Nodes created"), NODES_DELETED("Nodes deleted"), RELATIONSHIPS_DELETED("Relationships deleted"), @@ -54,6 +55,8 @@ public static Label getEnum(String value) { int nodesDeleted(); int indicesAdded(); + + int indicesDeleted(); int labelsAdded(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java index a6b24af..064bb1c 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java @@ -93,6 +93,9 @@ public int indicesAdded() { } + @Override + public int indicesDeleted() {return getIntValue(Label.INDICES_DELETED);} + /** * * @return number of labels added after query execution diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 0e8a2b6..9e2c691 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -15,7 +15,6 @@ import org.junit.*; import com.redislabs.redisgraph.Statistics.Label; -import org.junit.rules.ExpectedException; import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; @@ -157,6 +156,16 @@ public void testIndex() { Assert.assertNotNull(createNonExistingIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); Assert.assertEquals(1, createNonExistingIndexResult.getStatistics().indicesAdded()); + ResultSet createExistingIndexResult = api.query("social", "CREATE INDEX ON :person(age)"); + Assert.assertFalse(createExistingIndexResult.hasNext()); + Assert.assertNotNull(createExistingIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); + Assert.assertEquals(0, createExistingIndexResult.getStatistics().indicesAdded()); + + ResultSet deleteExistingIndexResult = api.query("social", "DROP INDEX ON :person(age)"); + Assert.assertFalse(deleteExistingIndexResult.hasNext()); + Assert.assertNotNull(deleteExistingIndexResult.getStatistics().getStringValue(Label.INDICES_DELETED)); + Assert.assertEquals(1, deleteExistingIndexResult.getStatistics().indicesDeleted()); + } @Test From 6565719f9557ddd566f519c0a14d42b94c121773 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 15 Dec 2019 13:48:33 +0200 Subject: [PATCH 044/128] changed circle ci not to deploy forked PR (#53) * changed circle ci not to deploy forked PR * replaced codecov package --- .circleci/config.yml | 26 ++++++++++++++++++-------- pom.xml | 35 +++++++++++++++++------------------ 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6f130e1..d51fe5e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,15 +2,25 @@ # # Check https://circleci.com/docs/2.0/language-java/ for more details # -version: 2 +version: 2.1 +commands: + early_return_for_forked_pull_requests: + description: >- + If this build is from a fork, stop executing the current job and return success. + This is useful to avoid steps that will fail due to missing credentials. + steps: + - run: + name: Early return if this build is from a forked PR + command: | + if [ -n "$CIRCLE_PR_NUMBER" ]; then + echo "Nothing to do for forked PRs, so marking this step successful" + circleci step halt + fi jobs: build: docker: - image: circleci/openjdk:8u171-jdk - - image: redislabs/redisgraph:edge - port: 6379:6379 - working_directory: ~/repo environment: @@ -38,12 +48,12 @@ jobs: # run tests! # - run: mvn pmd:check - - run: mvn integration-test + - run: mvn integration-test - - run: mvn cobertura:cobertura + - early_return_for_forked_pull_requests - - run: bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN} - + - run: bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN} + - run: mvn -s .circleci.settings.xml -DskipTests deploy workflows: diff --git a/pom.xml b/pom.xml index c137ec9..c595090 100644 --- a/pom.xml +++ b/pom.xml @@ -114,24 +114,23 @@ - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - html - xml - - - - - - maven-compiler-plugin - 3.0 - - 1.8 - 1.8 - + org.jacoco + jacoco-maven-plugin + 0.8.5 + + + + prepare-agent + + + + report + test + + report + + + org.sonatype.plugins From ef421f5a2ef89455bd1f4d26b787144fe7010731 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Thu, 26 Dec 2019 11:29:02 +0200 Subject: [PATCH 045/128] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c33a32..7e9e859 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Or com.redislabs jredisgraph - 2.0.0-rc1 + 2.0.0-rc3 ``` From 34b41f8fc50e6d09ebae9402c77107045ddfebf7 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 8 Mar 2020 10:34:47 +0200 Subject: [PATCH 046/128] Added the new parameterized query API to transaction (#61) --- README.md | 2 +- .../redisgraph/RedisGraphTransaction.java | 21 +++++++++- .../impl/api/RedisGraphTransaction.java | 39 +++++++++++++++++++ .../redisgraph/RedisGraphAPITest.java | 4 +- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7e9e859..27f67f5 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ public class RedisGraphExample { // WATCH/MULTI/EXEC context.watch("contextSocial"); RedisGraphTransaction t = context.multi(); - t.query("contextSocial", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); + t.query("contextSocial", "MATCH (a:person)-[r:knows]->(b:person{name:$name,age:$age}) RETURN a, r, b", params); // support for Redis/Jedis native commands in transaction t.set("x", "1"); t.get("x"); diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java index c206640..fbde12c 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java @@ -22,15 +22,34 @@ public interface RedisGraphTransaction extends MultiKeyCommandsPipeline, ClusterPipeline, BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline, BasicRedisPipeline, BinaryRedisPipeline, RedisPipeline, Closeable { + /** + * Execute a Cypher query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query); + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on * @param query Cypher query * @param args - * @return a response which builds the result set with the query answer + * @return a response which builds the result set with the query answer. + * @deprecated use {@link #query(String, String, Map)} instead. */ + @Deprecated Response query(String graphId, String query, Object ...args); + /** + * Executes a cypher query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query, Map params); + /** * Invokes stored procedures without arguments * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 88660cc..11fca09 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -30,6 +30,23 @@ public RedisGraphTransaction(Client client, RedisGraph redisGraph){ this.redisGraph = redisGraph; } + /** + * Execute a Cypher query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query) { + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Execute a Cypher query with arguments * @@ -37,7 +54,10 @@ public RedisGraphTransaction(Client client, RedisGraph redisGraph){ * @param query Cypher query * @param args * @return response with a result set + * @deprecated use {@link #query(String, String, Map)} instead. */ + @Deprecated + @Override public Response query(String graphId, String query, Object ...args){ String preparedQuery = Utils.prepareQuery(query, args); client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); @@ -49,6 +69,25 @@ public ResultSet build(Object o) { }); } + /** + * Executes a cypher query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query, Map params) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Invokes stored procedures without arguments, in multi/exec context diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 9e2c691..d5217b5 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -765,7 +765,9 @@ public void testReadTransactionWatch(){ c1.watch("social"); RedisGraphTransaction t1 = c1.multi(); - t1.query("social", "CREATE (:Person {name:'b'})"); + Map params = new HashMap<>(); + params.put("name", 'b'); + t1.query("social", "CREATE (:Person {name:$name})", params); c2.query("social", "MATCH (n) return n"); List returnValue = t1.exec(); From 3ec13b0142c04f32dd57b6afe6f07b964ece1627 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 10 Mar 2020 10:45:15 +0200 Subject: [PATCH 047/128] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 27f67f5..43caeaa 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,12 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph) [![Javadocs](https://www.javadoc.io/badge/com.redislabs/jredisgraph.svg)](https://www.javadoc.io/doc/com.redislabs/jredisgraph) [![Codecov](https://codecov.io/gh/RedisGraph/JRedisGraph/branch/master/graph/badge.svg)](https://codecov.io/gh/RedisGraph/JRedisGraph) +[![Known Vulnerabilities](https://snyk.io/test/github/RedisGraph/JRedisGraph/badge.svg?targetFile=pom.xml)](https://snyk.io/test/github/RedisGraph/JRedisGraph?targetFile=pom.xml) +# JRedisGraph [![Mailing List](https://img.shields.io/badge/Mailing%20List-RedisGraph-blue)](https://groups.google.com/forum/#!forum/redisgraph) [![Gitter](https://badges.gitter.im/RedisLabs/RedisGraph.svg)](https://gitter.im/RedisLabs/RedisGraph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -# JRedisGraph RedisGraph Java client From 6a805dcfa5d7cb7868a674d2389ea87dd927e91e Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 11 Mar 2020 10:04:23 +0100 Subject: [PATCH 048/128] fix: upgrade redis.clients:jedis from 3.1.0 to 3.2.0 (#66) Snyk has created this PR to upgrade redis.clients:jedis from 3.1.0 to 3.2.0. See this package in NPM: https://www.npmjs.com/package/redis.clients:jedis See this project in Snyk: https://app.snyk.io/org/gkorland/project/bf05955d-de0e-4973-a40c-38a21033b8fd?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c595090..2e2afd0 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ redis.clients jedis - 3.1.0 + 3.2.0 org.apache.commons From ef6203527eaf73f58eea1714708952935051cc33 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 11 Mar 2020 10:05:33 +0100 Subject: [PATCH 049/128] fix: upgrade org.apache.commons:commons-text from 1.6 to 1.8 (#65) Snyk has created this PR to upgrade org.apache.commons:commons-text from 1.6 to 1.8. See this package in NPM: https://www.npmjs.com/package/org.apache.commons:commons-text See this project in Snyk: https://app.snyk.io/org/gkorland/project/bf05955d-de0e-4973-a40c-38a21033b8fd?utm_source=github&utm_medium=upgrade-pr Co-authored-by: Guy Korland --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2e2afd0..0fc8a40 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ org.apache.commons commons-text - 1.6 + 1.8 org.slf4j From 9a64906b2a6eb023949b5db48b25d9993e059669 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 11 Mar 2020 10:06:48 +0100 Subject: [PATCH 050/128] fix: upgrade org.apache.commons:commons-pool2 from 2.0 to 2.8.0 (#64) Snyk has created this PR to upgrade org.apache.commons:commons-pool2 from 2.0 to 2.8.0. See this package in NPM: https://www.npmjs.com/package/org.apache.commons:commons-pool2 See this project in Snyk: https://app.snyk.io/org/gkorland/project/bf05955d-de0e-4973-a40c-38a21033b8fd?utm_source=github&utm_medium=upgrade-pr Co-authored-by: Guy Korland --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0fc8a40..693bc36 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ org.apache.commons commons-pool2 - 2.0 + 2.8.0 junit From 7a8552d295deb0579d91866ea4c75ee7f8384d15 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 11 Mar 2020 15:22:19 +0200 Subject: [PATCH 051/128] Update README.md (#62) * Update README.md * version bump fixed README.md --- README.md | 42 ++---------------------------------------- pom.xml | 2 +- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 43caeaa..f0ab10b 100644 --- a/README.md +++ b/README.md @@ -20,24 +20,12 @@ RedisGraph Java client com.redislabs jredisgraph - 1.0.6 - - - -Or - - - - com.redislabs - jredisgraph - 2.0.0-rc3 + 2.0.0 ``` ### Snapshots -To be used with RedisGraph 2.0 (not officially released) - ```xml @@ -54,38 +42,12 @@ and com.redislabs jredisgraph - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT ``` # Example: Using the Java Client -## Up to 2.0.0 -```java -package com.redislabs.redisgraph; - -public class RedisGraphExample { - public static void main(String[] args) { - - RedisGraphAPI api = new RedisGraphAPI("social"); - - api.query("CREATE (:person{name:'roi',age:32})"); - api.query("CREATE (:person{name:%s,age:%d})", "amit", 30); - - api.query("MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); - - ResultSet resultSet = api.query("MATCH (a:person)-[:knows]->(b:person) RETURN a, b"); - - while(resultSet.hasNext()){ - Record record = resultSet.next(); - System.out.println(record.getString("a.name")); - } - } -} - -``` -## From 2.0.0 - ```java package com.redislabs.redisgraph; diff --git a/pom.xml b/pom.xml index 693bc36..959d45c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT JRedisGraph Official client for Redis-Graph From 53dddb8a580cf75dd925549bda1703da5128c001 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 11 Mar 2020 18:19:44 +0200 Subject: [PATCH 052/128] bump version --- README.md | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f0ab10b..84751bf 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.0.0 + 2.0.1 ``` @@ -42,7 +42,7 @@ and com.redislabs jredisgraph - 2.0.1-SNAPSHOT + 2.0.2-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 959d45c..5495455 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.0.1-SNAPSHOT + 2.0.2-SNAPSHOT JRedisGraph Official client for Redis-Graph From eea7ee6d7c8396b02b8bd8acf61a64f74b334a4e Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 19 Mar 2020 13:08:19 +0200 Subject: [PATCH 053/128] missing parameter is now runtime error (#67) * missing parameter is now runtime error * version bump to comply to 2.0.8 --- pom.xml | 2 +- .../redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 5495455..839721a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT JRedisGraph Official client for Redis-Graph diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index c7a6862..443588c 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -90,14 +90,14 @@ public void testContextSyntaxErrorReporting() { @Test public void testMissingParametersSyntaxErrorReporting(){ - exceptionRule.expect(JRedisGraphCompileTimeException.class); + exceptionRule.expect(JRedisGraphRunTimeException.class); exceptionRule.expectMessage("Missing parameters"); api.query("social","RETURN $param"); } @Test public void testMissingParametersSyntaxErrorReporting2(){ - exceptionRule.expect(JRedisGraphCompileTimeException.class); + exceptionRule.expect(JRedisGraphRunTimeException.class); exceptionRule.expectMessage("Missing parameters"); api.query("social","RETURN $param", new HashMap<>()); } From 8ea95af3bd8466e01222fd8f48506acc50b505b7 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Thu, 19 Mar 2020 14:50:45 +0200 Subject: [PATCH 054/128] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 839721a..5495455 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.0.3-SNAPSHOT + 2.0.2-SNAPSHOT JRedisGraph Official client for Redis-Graph From 2576ce871634f200072554947bf60fa11eda5346 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 19 Mar 2020 15:00:27 +0200 Subject: [PATCH 055/128] Update README.md (#68) * Update README.md * Update pom.xml Co-authored-by: Guy Korland --- README.md | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84751bf..483be15 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.0.1 + 2.0.2 ``` @@ -42,7 +42,7 @@ and com.redislabs jredisgraph - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 5495455..839721a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT JRedisGraph Official client for Redis-Graph From 4745ab6129028412c6ea860ef31d5d87cc9e4d14 Mon Sep 17 00:00:00 2001 From: Jeffrey Lovitz Date: Tue, 7 Apr 2020 16:17:08 -0400 Subject: [PATCH 056/128] Add Optional test, remove invalid assertions from tests (#70) * Add Optional test, remove invalid assertions from tests * Remove test accesses to getSchemaTypes API --- .../redisgraph/RedisGraphAPITest.java | 109 ++++++++---------- 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index d5217b5..44b4453 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -181,21 +181,15 @@ public void testHeader(){ Header header = queryResult.getHeader(); List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); Assert.assertEquals(3, schemaNames.size()); - Assert.assertEquals(3, schemaTypes.size()); Assert.assertEquals("a", schemaNames.get(0)); Assert.assertEquals("r", schemaNames.get(1)); Assert.assertEquals("a.age", schemaNames.get(2)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Assert.assertEquals(COLUMN_RELATION, schemaTypes.get(1)); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(2)); } @@ -368,17 +362,11 @@ public void testMultiThread(){ Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); Assert.assertEquals(3, schemaNames.size()); - Assert.assertEquals(3, schemaTypes.size()); Assert.assertEquals("a", schemaNames.get(0)); Assert.assertEquals("r", schemaNames.get(1)); Assert.assertEquals("a.age", schemaNames.get(2)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Assert.assertEquals(COLUMN_RELATION, schemaTypes.get(1)); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(2)); Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); Record record = resultSet.next(); @@ -413,15 +401,10 @@ public void testMultiThread(){ Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); Assert.assertEquals(2, schemaNames.size()); - Assert.assertEquals(2, schemaTypes.size()); Assert.assertEquals("a", schemaNames.get(0)); Assert.assertEquals("r", schemaNames.get(1)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Assert.assertEquals(COLUMN_RELATION, schemaTypes.get(1)); Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); Record record = resultSet.next(); @@ -462,15 +445,10 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); Assert.assertEquals(2, schemaNames.size()); - Assert.assertEquals(2, schemaTypes.size()); Assert.assertEquals("a", schemaNames.get(0)); Assert.assertEquals("r", schemaNames.get(1)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Assert.assertEquals(COLUMN_RELATION, schemaTypes.get(1)); Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); Record record = resultSet.next(); @@ -497,15 +475,10 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(resultSet.getHeader()); header = resultSet.getHeader(); schemaNames = header.getSchemaNames(); - schemaTypes = header.getSchemaTypes(); Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); Assert.assertEquals(2, schemaNames.size()); - Assert.assertEquals(2, schemaTypes.size()); Assert.assertEquals("a", schemaNames.get(0)); Assert.assertEquals("r", schemaNames.get(1)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Assert.assertEquals(COLUMN_RELATION, schemaTypes.get(1)); Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); record = resultSet.next(); @@ -572,18 +545,10 @@ public void testMultiExec(){ List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals("n", schemaNames.get(0)); - Assert.assertEquals(COLUMN_NODE, schemaTypes.get(0)); - Property nameProperty = new Property("name", "a"); Node expectedNode = new Node(); @@ -606,18 +571,10 @@ public void testMultiExec(){ schemaNames = header.getSchemaNames(); - schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals("label", schemaNames.get(0)); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); - Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); record = resultSet.next(); @@ -816,16 +773,9 @@ public void testArraySupport() { List schemaNames = header.getSchemaNames(); - List schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals("x", schemaNames.get(0)); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); // check record Assert.assertEquals(1, resultSet.size()); @@ -846,16 +796,9 @@ public void testArraySupport() { schemaNames = header.getSchemaNames(); - schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals("x", schemaNames.get(0)); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); // check record Assert.assertEquals(1, resultSet.size()); @@ -875,16 +818,9 @@ record = resultSet.next(); schemaNames = header.getSchemaNames(); - schemaTypes = header.getSchemaTypes(); - Assert.assertNotNull(schemaNames); - Assert.assertNotNull(schemaTypes); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals(1, schemaTypes.size()); - Assert.assertEquals("x", schemaNames.get(0)); - Assert.assertEquals(COLUMN_SCALAR, schemaTypes.get(0)); // check record Assert.assertEquals(3, resultSet.size()); @@ -960,4 +896,49 @@ public void testParameters(){ } } + @Test + public void testNullGraphEntities() { + // Create two nodes connected by a single outgoing edge. + Assert.assertNotNull(api.query("social", "CREATE (:L)-[:E]->(:L2)")); + // Test a query that produces 1 record with 3 null values. + ResultSet resultSet = api.query("social", "OPTIONAL MATCH (a:NONEXISTENT)-[e]->(b) RETURN a, e, b"); + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList(null, null, null), record.values()); + + // Test a query that produces 2 records, with 2 null values in the second. + resultSet = api.query("social", "MATCH (a) OPTIONAL MATCH (a)-[e]->(b) RETURN a, e, b ORDER BY ID(a)"); + Assert.assertEquals(2, resultSet.size()); + record = resultSet.next(); + Assert.assertEquals(3, record.size()); + + Assert.assertNotNull(record.getValue(0)); + Assert.assertNotNull(record.getValue(1)); + Assert.assertNotNull(record.getValue(2)); + + record = resultSet.next(); + Assert.assertEquals(3, record.size()); + + Assert.assertNotNull(record.getValue(0)); + Assert.assertNull(record.getValue(1)); + Assert.assertNull(record.getValue(2)); + + // Test a query that produces 2 records, the first containing a path and the second containing a null value. + resultSet = api.query("social", "MATCH (a) OPTIONAL MATCH p = (a)-[e]->(b) RETURN p"); + Assert.assertEquals(2, resultSet.size()); + record = resultSet.next(); + Assert.assertEquals(1, record.size()); + + Object path = record.getValue(0); + Assert.assertNotNull(record.getValue(0)); + + record = resultSet.next(); + Assert.assertEquals(1, record.size()); + + path = record.getValue(0); + Assert.assertNull(record.getValue(0)); + + } } From a6869a14bf0b912f791e6ec6c53c06fb186f800d Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Fri, 24 Apr 2020 10:20:44 +0300 Subject: [PATCH 057/128] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 483be15..9543e63 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Known Vulnerabilities](https://snyk.io/test/github/RedisGraph/JRedisGraph/badge.svg?targetFile=pom.xml)](https://snyk.io/test/github/RedisGraph/JRedisGraph?targetFile=pom.xml) # JRedisGraph -[![Mailing List](https://img.shields.io/badge/Mailing%20List-RedisGraph-blue)](https://groups.google.com/forum/#!forum/redisgraph) +[![Forum](https://img.shields.io/badge/Forum-RedisGraph-blue)](https://forum.redislabs.com/c/modules/redisgraph) [![Gitter](https://badges.gitter.im/RedisLabs/RedisGraph.svg)](https://gitter.im/RedisLabs/RedisGraph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) RedisGraph Java client From d62f0c77b9a2d669d7ec6d1271d8ca8fc08c5557 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Fri, 24 Apr 2020 10:23:22 +0300 Subject: [PATCH 058/128] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9543e63..9bb0943 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ and ``` -# Example: Using the Java Client +## Example: Using the Java Client ```java package com.redislabs.redisgraph; From e2c7e0a280fca77dcd0615f184909f540aecdfd9 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 27 May 2020 05:48:12 -0700 Subject: [PATCH 059/128] changed returned integer values to be long. (#73) * changed returned integer values to be long. entities values and ids are long * Update RedisGraphAPITest.java Co-authored-by: Guy Korland --- .../redisgraph/graph_entities/Edge.java | 12 ++--- .../graph_entities/GraphEntity.java | 34 ++++--------- .../redisgraph/graph_entities/Property.java | 8 ++- .../impl/resultset/ResultSetImpl.java | 8 +-- .../redisgraph/RedisGraphAPITest.java | 51 ++++++++++++------- 5 files changed, 59 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java index f7c0135..6eebdf8 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java @@ -10,8 +10,8 @@ public class Edge extends GraphEntity { //members private String relationshipType; - private int source; - private int destination; + private long source; + private long destination; //getters & setters @@ -34,14 +34,14 @@ public void setRelationshipType(String relationshipType) { /** * @return The id of the source node */ - public int getSource() { + public long getSource() { return source; } /** * @param source - The id of the source node to be set */ - public void setSource(int source) { + public void setSource(long source) { this.source = source; } @@ -49,7 +49,7 @@ public void setSource(int source) { * * @return the id of the destination node */ - public int getDestination() { + public long getDestination() { return destination; } @@ -57,7 +57,7 @@ public int getDestination() { * * @param destination - The id of the destination node to be set */ - public void setDestination(int destination) { + public void setDestination(long destination) { this.destination = destination; } diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index 99120ba..61b9dbe 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -8,90 +8,78 @@ * A graph entity has an id and a set of properties. The properties are mapped and accessed by their names. */ public abstract class GraphEntity { - - - //members - - protected int id; + protected long id; protected final Map propertyMap = new HashMap<>(); //setters & getters /** - * * @return entity id */ - public int getId() { + public long getId() { return id; } /** - * * @param id - entity id to be set */ - public void setId(int id) { + public void setId(long id) { this.id = id; } /** * Adds a property to the entity, by composing name, type and value to a property object + * * @param name * @param value */ - public void addProperty(String name, Object value){ - + public void addProperty(String name, Object value) { addProperty(new Property(name, value)); - } /** - * * @return Entity's property names, as a Set */ - public Set getEntityPropertyNames(){ + public Set getEntityPropertyNames() { return propertyMap.keySet(); } /** * Add a property to the entity + * * @param property */ - public void addProperty (Property property){ + public void addProperty(Property property) { propertyMap.put(property.getName(), property); } /** - * * @return number of properties */ - public int getNumberOfProperties(){ + public int getNumberOfProperties() { return propertyMap.size(); } /** - * * @param propertyName - property name as lookup key (String) * @return property object, or null if key is not found */ - public Property getProperty(String propertyName){ + public Property getProperty(String propertyName) { return propertyMap.get(propertyName); } /** - * * @param name - the name of the property to be removed */ - public void removeProperty(String name){ - + public void removeProperty(String name) { propertyMap.remove(name); - } @Override diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index c007555..2f481d0 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -11,7 +11,6 @@ public class Property { //members private String name; - private T value; @@ -66,6 +65,11 @@ public void setValue(T value) { this.value = value; } + private boolean valueEquals(Object value1, Object value2) { + if(value1 instanceof Integer) value1 = Long.valueOf(((Integer) value1).longValue()); + if(value2 instanceof Integer) value2 = Long.valueOf(((Integer) value2).longValue()); + return Objects.equals(value1, value2); + } @Override public boolean equals(Object o) { @@ -73,7 +77,7 @@ public boolean equals(Object o) { if (!(o instanceof Property)) return false; Property property = (Property) o; return Objects.equals(name, property.name) && - Objects.equals(value, property.value); + valueEquals(value, property.value); } @Override diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 442573b..7b4a70b 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -161,7 +161,7 @@ private Node deserializeNode(List rawNodeData) { * @param rawEntityId raw representation of entity id to be set to the graph entity */ private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityId) { - int id = ((Long) rawEntityId).intValue(); + long id = (Long) rawEntityId; graphEntity.setId(id); } @@ -183,8 +183,8 @@ private Edge deserializeEdge(List rawEdgeData) { redisGraph); edge.setRelationshipType(relationshipType); - edge.setSource((int) (long) rawEdgeData.get(2)); - edge.setDestination((int) (long) rawEdgeData.get(3)); + edge.setSource( (long) rawEdgeData.get(2)); + edge.setDestination( (long) rawEdgeData.get(3)); deserializeGraphEntityProperties(edge, (List>) rawEdgeData.get(4)); @@ -233,7 +233,7 @@ private Object deserializeScalar(List rawScalarData) { case VALUE_DOUBLE: return Double.parseDouble(SafeEncoder.encode((byte[]) obj)); case VALUE_INTEGER: - return ((Long) obj).intValue(); + return (Long) obj; case VALUE_STRING: return SafeEncoder.encode((byte[]) obj); case VALUE_ARRAY: diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 44b4453..48c0f03 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -298,8 +298,8 @@ public void testRecord(){ "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, age, doubleValue, true, null, - place, since, doubleValue, false, null), + name, (long)age, doubleValue, true, null, + place, (long)since, doubleValue, false, null), record.values()); Node a = record.getValue("a"); @@ -309,8 +309,8 @@ public void testRecord(){ Assert.assertEquals( "roi", record.getString(2)); Assert.assertEquals( "32", record.getString(3)); - Assert.assertEquals( 32L, ((Integer)(record.getValue(3))).longValue()); - Assert.assertEquals( 32L, ((Integer)record.getValue("a.age")).longValue()); + Assert.assertEquals( 32L, ((Long)record.getValue(3)).longValue()); + Assert.assertEquals( 32L, ((Long)record.getValue("a.age")).longValue()); Assert.assertEquals( "roi", record.getString("a.name")); Assert.assertEquals( "32", record.getString("a.age")); @@ -372,7 +372,7 @@ public void testMultiThread(){ Record record = resultSet.next(); Assert.assertFalse(resultSet.hasNext()); Assert.assertEquals(Arrays.asList("a", "r", "a.age"), record.keys()); - Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, 32), record.values()); + Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, 32L), record.values()); } //test for update in local cache @@ -530,7 +530,7 @@ public void testMultiExec(){ // Redis incr command Assert.assertEquals(Long.class, results.get(3).getClass()); - Assert.assertEquals((long)2, results.get(3)); + Assert.assertEquals(2L, results.get(3)); // Redis get command Assert.assertEquals(String.class, results.get(4).getClass()); @@ -676,8 +676,8 @@ public void testContextedAPI() { "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, age, doubleValue, true, null, - place, since, doubleValue, false, null), + name, (long)age, doubleValue, true, null, + place, (long)since, doubleValue, false, null), record.values()); Node a = record.getValue("a"); @@ -687,8 +687,8 @@ public void testContextedAPI() { Assert.assertEquals("roi", record.getString(2)); Assert.assertEquals("32", record.getString(3)); - Assert.assertEquals(32L, ((Integer) (record.getValue(3))).longValue()); - Assert.assertEquals(32L, ((Integer) record.getValue("a.age")).longValue()); + Assert.assertEquals(32L, ((Long) (record.getValue(3))).longValue()); + Assert.assertEquals(32L, ((Long) record.getValue("a.age")).longValue()); Assert.assertEquals("roi", record.getString("a.name")); Assert.assertEquals("32", record.getString("a.age")); } @@ -741,7 +741,7 @@ public void testArraySupport() { expectedANode.addLabel("person"); Property aNameProperty = new Property("name", "a"); Property aAgeProperty = new Property("age", 32); - Property aListProperty = new Property("array", Arrays.asList(0,1,2)); + Property aListProperty = new Property("array", Arrays.asList(0L, 1L, 2L)); expectedANode.addProperty(aNameProperty); expectedANode.addProperty(aAgeProperty); expectedANode.addProperty(aListProperty); @@ -752,7 +752,7 @@ public void testArraySupport() { expectedBNode.addLabel("person"); Property bNameProperty = new Property("name", "b"); Property bAgeProperty = new Property("age", 30); - Property bListProperty = new Property("array", Arrays.asList(3,4,5)); + Property bListProperty = new Property("array", Arrays.asList(3L, 4L, 5L)); expectedBNode.addProperty(bNameProperty); expectedBNode.addProperty(bAgeProperty); expectedBNode.addProperty(bListProperty); @@ -786,7 +786,7 @@ public void testArraySupport() { List x = record.getValue("x"); - Assert.assertEquals(Arrays.asList(0,1,2), x); + Assert.assertEquals(Arrays.asList(0L, 1L, 2L), x); // test collect resultSet = api.query("social", "MATCH(n) return collect(n) as x"); @@ -825,11 +825,11 @@ record = resultSet.next(); // check record Assert.assertEquals(3, resultSet.size()); - for (int i = 0; i < 3; i++) { + for (long i = 0; i < 3; i++) { Assert.assertTrue(resultSet.hasNext()); record = resultSet.next(); Assert.assertEquals(Arrays.asList("x"), record.keys()); - Assert.assertEquals(i, (int) record.getValue("x")); + Assert.assertEquals(i, (long)record.getValue("x")); } @@ -881,14 +881,16 @@ public void testPath(){ @Test public void testParameters(){ Object[] parameters = {1, 2.3, true, false, null, "str", Arrays.asList(1,2,3), new Integer[]{1,2,3}}; - Map param = new HashMap<>(); + Object[] expected_anwsers = {1L, 2.3, true, false, null, "str", Arrays.asList(1L, 2L, 3L), new Long[]{1L, 2L, 3L}}; + Map params = new HashMap<>(); for (int i=0; i < parameters.length; i++) { - Object expected = parameters[i]; - param.put("param", expected); - ResultSet resultSet = api.query("social", "RETURN $param", param); + Object param = parameters[i]; + params.put("param", param); + ResultSet resultSet = api.query("social", "RETURN $param", params); Assert.assertEquals(1, resultSet.size()); Record r = resultSet.next(); Object o = r.getValue(0); + Object expected = expected_anwsers[i]; if(i == parameters.length-1) { expected = Arrays.asList((Object[])expected); } @@ -941,4 +943,15 @@ record = resultSet.next(); Assert.assertNull(record.getValue(0)); } + + @Test + public void test64bitnumber(){ + long value = 1 << 40; + Map params = new HashMap(); + params.put("val", value); + ResultSet resultSet = api.query("social","CREATE (n {val:$val}) RETURN n.val", params); + Assert.assertEquals(1, resultSet.size()); + Record r = resultSet.next(); + Assert.assertEquals(Long.valueOf(value), r.getValue(0)); + } } From c182099e4596819a124dd337ba26f1d24f6fca5d Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 27 May 2020 22:40:34 +0300 Subject: [PATCH 060/128] fix: upgrade redis.clients:jedis from 3.2.0 to 3.3.0 (#71) Snyk has created this PR to upgrade redis.clients:jedis from 3.2.0 to 3.3.0. See this package in NPM: https://www.npmjs.com/package/redis.clients:jedis See this project in Snyk: https://app.snyk.io/org/dvirdukhan/project/cb2ca151-454d-4bfd-a328-6d77a935177b?utm_source=github&utm_medium=upgrade-pr Co-authored-by: Guy Korland --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 839721a..fed7794 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ redis.clients jedis - 3.2.0 + 3.3.0 org.apache.commons From 076d6fb081caed36f17e997e394854040bcbdb3c Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 28 May 2020 00:55:13 -0700 Subject: [PATCH 061/128] Update ResultSetScalarTypes.java (#74) --- .../redisgraph/impl/resultset/ResultSetScalarTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java index 8d40aff..e9c04e4 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java @@ -6,7 +6,7 @@ enum ResultSetScalarTypes { VALUE_UNKNOWN, VALUE_NULL, VALUE_STRING, - VALUE_INTEGER, + VALUE_INTEGER, // 64 bit long. VALUE_BOOLEAN, VALUE_DOUBLE, VALUE_ARRAY, From 2283cb8b9244e16fee231375e04d516d530213db Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 22 Jul 2020 09:34:54 +0300 Subject: [PATCH 062/128] cached execution statistics (#75) * cached execution statistics * Update RedisGraphAPITest.java * Update RedisGraphAPITest.java Co-authored-by: Guy Korland --- .../com/redislabs/redisgraph/Statistics.java | 3 ++ .../impl/resultset/StatisticsImpl.java | 9 ++++++ .../redisgraph/RedisGraphAPITest.java | 28 +++++++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/Statistics.java b/src/main/java/com/redislabs/redisgraph/Statistics.java index 7c8f286..9d7453f 100644 --- a/src/main/java/com/redislabs/redisgraph/Statistics.java +++ b/src/main/java/com/redislabs/redisgraph/Statistics.java @@ -15,6 +15,7 @@ enum Label{ RELATIONSHIPS_DELETED("Relationships deleted"), PROPERTIES_SET("Properties set"), RELATIONSHIPS_CREATED("Relationships created"), + CACHED_EXECUTION("Cached execution"), QUERY_INTERNAL_EXECUTION_TIME("Query internal execution time"); private final String text; @@ -65,4 +66,6 @@ public static Label getEnum(String value) { int relationshipsCreated(); int propertiesSet(); + + boolean cachedExecution(); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java index 064bb1c..727ec53 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java @@ -132,6 +132,15 @@ public int propertiesSet() { return getIntValue(Label.PROPERTIES_SET); } + /** + * + * @return The execution plan was cached on RedisGraph. + */ + @Override + public boolean cachedExecution() { + return getIntValue(Label.CACHED_EXECUTION) == 1; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 48c0f03..e3e97ce 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -642,7 +642,6 @@ public void testContextedAPI() { "r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); Assert.assertNotNull(resultSet); - Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); Assert.assertEquals(0, resultSet.getStatistics().nodesDeleted()); Assert.assertEquals(0, resultSet.getStatistics().labelsAdded()); @@ -651,7 +650,6 @@ public void testContextedAPI() { Assert.assertEquals(0, resultSet.getStatistics().relationshipsDeleted()); Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); - Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); Record record = resultSet.next(); @@ -947,11 +945,35 @@ record = resultSet.next(); @Test public void test64bitnumber(){ long value = 1 << 40; - Map params = new HashMap(); + Map params = new HashMap<>(); params.put("val", value); ResultSet resultSet = api.query("social","CREATE (n {val:$val}) RETURN n.val", params); Assert.assertEquals(1, resultSet.size()); Record r = resultSet.next(); Assert.assertEquals(Long.valueOf(value), r.getValue(0)); } + + @Test + public void testCachedExecution() { + api.query("social", "CREATE (:N {val:1}), (:N {val:2})"); + + // First time should not be loaded from execution cache + Map params = new HashMap<>(); + params.put("val", 1L); + ResultSet resultSet = api.query("social","MATCH (n:N {val:$val}) RETURN n.val", params); + Assert.assertEquals(1, resultSet.size()); + Record r = resultSet.next(); + Assert.assertEquals(params.get("val"), r.getValue(0)); + Assert.assertFalse(resultSet.getStatistics().cachedExecution()); + + // Run in loop many times to make sure the query will be loaded + // from cache at least once + for (int i = 0 ; i < 64; i++){ + resultSet = api.query("social","MATCH (n:N {val:$val}) RETURN n.val", params); + } + Assert.assertEquals(1, resultSet.size()); + r = resultSet.next(); + Assert.assertEquals(params.get("val"), r.getValue(0)); + Assert.assertTrue(resultSet.getStatistics().cachedExecution()); + } } From 24f633bfd6cd1165bf48aeaa731caaefe608f89a Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Thu, 23 Jul 2020 16:29:58 +0300 Subject: [PATCH 063/128] Cleanups (#77) * Code cleanups * replace range check with catching IndexOutOfBoundsException --- .../graph_entities/GraphEntity.java | 2 +- .../redisgraph/graph_entities/Path.java | 1 - .../redisgraph/graph_entities/Property.java | 2 - .../impl/resultset/ResultSetImpl.java | 18 +++-- .../impl/resultset/ResultSetScalarTypes.java | 8 ++- .../redisgraph/RedisGraphAPITest.java | 68 +++++++++---------- .../redisgraph/graph_entities/PathTest.java | 3 - 7 files changed, 45 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index 61b9dbe..e86e302 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -10,7 +10,7 @@ public abstract class GraphEntity { //members protected long id; - protected final Map propertyMap = new HashMap<>(); + protected final Map> propertyMap = new HashMap<>(); //setters & getters diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java index fa86484..a77eaea 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Path.java @@ -1,6 +1,5 @@ package com.redislabs.redisgraph.graph_entities; -import java.util.ArrayList; import java.util.List; import java.util.Objects; diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 2f481d0..4be4a7a 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -1,7 +1,5 @@ package com.redislabs.redisgraph.graph_entities; -import com.redislabs.redisgraph.ResultSet; - import java.util.Objects; /** diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 7b4a70b..b852c5b 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -29,13 +29,14 @@ public class ResultSetImpl implements ResultSet { /** * @param rawResponse the raw representation of response is at most 3 lists of objects. * The last list is the statistics list. - * @param redisGraph, the graph local cache + * @param redisGraph the graph connection + * @param cache the graph local cache */ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache cache) { this.redisGraph = redisGraph; this.cache = cache; - // If a run-time error occured, the last member of the rawResponse will be a JedisDataException. + // If a run-time error occurred, the last member of the rawResponse will be a JedisDataException. if (rawResponse.get(rawResponse.size()-1) instanceof JedisDataException) { throw new JRedisGraphRunTimeException((Throwable) rawResponse.get(rawResponse.size() - 1)); @@ -45,8 +46,8 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache header = parseHeader(new ArrayList<>()); results = new ArrayList<>(); - statistics = rawResponse.size()> 0 ? parseStatistics(rawResponse.get(rawResponse.size() - 1)) : - parseStatistics(new ArrayList()); + statistics = rawResponse.isEmpty() ? parseStatistics(new ArrayList()) : + parseStatistics(rawResponse.get(rawResponse.size() - 1)) ; } else { @@ -85,15 +86,12 @@ private List parseResult(List> rawResultSet) { case COLUMN_RELATION: parsedRow.add(deserializeEdge(obj)); break; - case COLUMN_SCALAR: { + case COLUMN_SCALAR: parsedRow.add(deserializeScalar(obj)); break; - } - default: { + default: parsedRow.add(null); break; - } - } } @@ -203,7 +201,7 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List rawProperty : rawProperties) { - Property property = new Property(); + Property property = new Property<>(); property.setName(cache.getPropertyName(((Long) rawProperty.get(0)).intValue(), redisGraph)); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java index e9c04e4..2f23ca8 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java @@ -14,12 +14,14 @@ enum ResultSetScalarTypes { VALUE_NODE, VALUE_PATH; - - static ResultSetScalarTypes[] values = values(); + private static final ResultSetScalarTypes[] values = values(); public static ResultSetScalarTypes getValue(int index) { - if (index < 0 || index > values.length) throw new JedisDataException("Unrecognized response type"); + try { return values[index]; + } catch(IndexOutOfBoundsException e) { + throw new JedisDataException("Unrecognized response type"); + } } } diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index e3e97ce..7d42997 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -203,17 +203,15 @@ public void testRecord(){ String place = "TLV"; int since = 2000; + Property nameProperty = new Property<>("name", name); + Property ageProperty = new Property<>("age", age); + Property doubleProperty = new Property<>("doubleValue", doubleValue); + Property trueBooleanProperty = new Property<>("boolValue", true); + Property falseBooleanProperty = new Property<>("boolValue", false); + Property nullProperty = new Property<>("nullValue", null); - - Property nameProperty = new Property("name", name); - Property ageProperty = new Property("age", age); - Property doubleProperty = new Property("doubleValue", doubleValue); - Property trueBooleanProperty = new Property("boolValue", true); - Property falseBooleanProperty = new Property("boolValue", false); - Property nullProperty = new Property("nullValue", null); - - Property placeProperty = new Property("place", place); - Property sinceProperty = new Property("since", since); + Property placeProperty = new Property<>("place", place); + Property sinceProperty = new Property<>("since", since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -340,9 +338,9 @@ public void testMultiThread(){ mapToObj(i-> api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")). collect(Collectors.toList()); - Property nameProperty = new Property("name", "roi"); - Property ageProperty = new Property("age", 32); - Property lastNameProperty =new Property("lastName", "a"); + Property nameProperty = new Property<>("name", "roi"); + Property ageProperty = new Property<>("age", 32); + Property lastNameProperty =new Property<>("lastName", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -423,9 +421,9 @@ public void testAdditionToProcedures(){ Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); //expected objects init - Property nameProperty = new Property("name", "roi"); - Property ageProperty = new Property("age", 32); - Property lastNameProperty =new Property("lastName", "a"); + Property nameProperty = new Property<>("name", "roi"); + Property ageProperty = new Property<>("age", 32); + Property lastNameProperty =new Property<>("lastName", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -549,7 +547,7 @@ public void testMultiExec(){ Assert.assertEquals(1, schemaNames.size()); Assert.assertEquals("n", schemaNames.get(0)); - Property nameProperty = new Property("name", "a"); + Property nameProperty = new Property<>("name", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -596,15 +594,15 @@ public void testContextedAPI() { int since = 2000; - Property nameProperty = new Property("name", name); - Property ageProperty = new Property("age", age); - Property doubleProperty = new Property("doubleValue", doubleValue); - Property trueBooleanProperty = new Property("boolValue", true); - Property falseBooleanProperty = new Property("boolValue", false); - Property nullProperty = new Property("nullValue", null); + Property nameProperty = new Property<>("name", name); + Property ageProperty = new Property<>("age", age); + Property doubleProperty = new Property<>("doubleValue", doubleValue); + Property trueBooleanProperty = new Property<>("boolValue", true); + Property falseBooleanProperty = new Property<>("boolValue", false); + Property nullProperty = new Property<>("nullValue", null); - Property placeProperty = new Property("place", place); - Property sinceProperty = new Property("since", since); + Property placeProperty = new Property<>("place", place); + Property sinceProperty = new Property<>("since", since); Node expectedNode = new Node(); expectedNode.setId(0); @@ -737,9 +735,9 @@ public void testArraySupport() { Node expectedANode = new Node(); expectedANode.setId(0); expectedANode.addLabel("person"); - Property aNameProperty = new Property("name", "a"); - Property aAgeProperty = new Property("age", 32); - Property aListProperty = new Property("array", Arrays.asList(0L, 1L, 2L)); + Property aNameProperty = new Property<>("name", "a"); + Property aAgeProperty = new Property<>("age", 32); + Property> aListProperty = new Property<>("array", Arrays.asList(0L, 1L, 2L)); expectedANode.addProperty(aNameProperty); expectedANode.addProperty(aAgeProperty); expectedANode.addProperty(aListProperty); @@ -748,9 +746,9 @@ public void testArraySupport() { Node expectedBNode = new Node(); expectedBNode.setId(1); expectedBNode.addLabel("person"); - Property bNameProperty = new Property("name", "b"); - Property bAgeProperty = new Property("age", 30); - Property bListProperty = new Property("array", Arrays.asList(3L, 4L, 5L)); + Property bNameProperty = new Property<>("name", "b"); + Property bAgeProperty = new Property<>("age", 30); + Property> bListProperty = new Property<>("array", Arrays.asList(3L, 4L, 5L)); expectedBNode.addProperty(bNameProperty); expectedBNode.addProperty(bAgeProperty); expectedBNode.addProperty(bListProperty); @@ -783,7 +781,7 @@ public void testArraySupport() { Assert.assertEquals(Arrays.asList("x"), record.keys()); - List x = record.getValue("x"); + List x = record.getValue("x"); Assert.assertEquals(Arrays.asList(0L, 1L, 2L), x); // test collect @@ -928,18 +926,14 @@ record = resultSet.next(); // Test a query that produces 2 records, the first containing a path and the second containing a null value. resultSet = api.query("social", "MATCH (a) OPTIONAL MATCH p = (a)-[e]->(b) RETURN p"); Assert.assertEquals(2, resultSet.size()); + record = resultSet.next(); Assert.assertEquals(1, record.size()); - - Object path = record.getValue(0); Assert.assertNotNull(record.getValue(0)); record = resultSet.next(); Assert.assertEquals(1, record.size()); - - path = record.getValue(0); Assert.assertNull(record.getValue(0)); - } @Test diff --git a/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java b/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java index 74581b3..ee65e68 100644 --- a/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java +++ b/src/test/java/com/redislabs/redisgraph/graph_entities/PathTest.java @@ -3,7 +3,6 @@ import nl.jqno.equalsverifier.EqualsVerifier; import org.junit.Test; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -28,12 +27,10 @@ private Edge buildEdge(int id, int src, int dst){ } private List buildNodeArray(int size) { - List nodes = new ArrayList<>(); return IntStream.range(0, size).mapToObj(i -> buildNode(i)).collect(Collectors.toList()); } private List buildEdgeArray(int size){ - List nodes = new ArrayList<>(); return IntStream.range(0, size).mapToObj(i -> buildEdge(i, i, i+1)).collect(Collectors.toList()); } From 9e45ebbc5a227c2263c2a65e3ea2f1719513dd72 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Thu, 23 Jul 2020 16:44:38 +0300 Subject: [PATCH 064/128] Bump version to 2.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fed7794..5550300 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.0.3-SNAPSHOT + 2.1.0-SNAPSHOT JRedisGraph Official client for Redis-Graph From d79565ca9227861644ba78a99d62e8c9c1e85472 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Thu, 23 Jul 2020 20:09:45 +0300 Subject: [PATCH 065/128] bump version to 2.2.0-SNAPSHOT (#78) --- README.md | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9bb0943..1d91d64 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.0.2 + 2.1.0 ``` @@ -42,7 +42,7 @@ and com.redislabs jredisgraph - 2.0.3-SNAPSHOT + 2.2.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 5550300..84e9a90 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT JRedisGraph Official client for Redis-Graph From c1bd3e43e81e52b17659de21e42fe09d4839a836 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 17 Aug 2020 12:50:11 +0300 Subject: [PATCH 066/128] fix: upgrade org.apache.commons:commons-text from 1.8 to 1.9 (#80) Snyk has created this PR to upgrade org.apache.commons:commons-text from 1.8 to 1.9. See this package in Maven Repository: https://mvnrepository.com/artifact/org.apache.commons/commons-text/ See this project in Snyk: https://app.snyk.io/org/dvirdukhan/project/cb2ca151-454d-4bfd-a328-6d77a935177b?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 84e9a90..91d9d73 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ org.apache.commons commons-text - 1.8 + 1.9 org.slf4j From 5c0ba229c8bafc2b007431a52e6b6fd13aab5ac3 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 19 Aug 2020 14:20:41 +0300 Subject: [PATCH 067/128] Few code cleanups (#79) * Few code cleanups * Add HeaderImpl test * pom cleanup Co-authored-by: DvirDukhan --- README.md | 10 +++---- pom.xml | 29 ++++++++----------- .../com/redislabs/redisgraph/impl/Utils.java | 12 ++++---- .../impl/api/AbstractRedisGraph.java | 2 -- .../impl/api/ContextedRedisGraph.java | 2 +- .../redisgraph/impl/api/RedisGraph.java | 2 +- .../redisgraph/impl/resultset/HeaderImpl.java | 4 +-- .../redisgraph/RedisGraphAPITest.java | 13 +++++---- 8 files changed, 35 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 1d91d64..06b8432 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,12 @@ public class RedisGraphExample { RedisGraph graph = new RedisGraph(); Map params = new HashMap<>(); - params.put("age", 30); - params.put("name", "amit"); + params.put("age", 30); + params.put("name", "amit"); - // send queries to a specific graph called "social" - graph.query("social","CREATE (:person{name:'roi',age:32})"); - graph.query("social","CREATE (:person{name:$name,age:$age})", params); + // send queries to a specific graph called "social" + graph.query("social","CREATE (:person{name:'roi',age:32})"); + graph.query("social","CREATE (:person{name:$name,age:$age})", params); graph.query("social","MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); ResultSet resultSet = graph.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a, r, b"); diff --git a/pom.xml b/pom.xml index 91d9d73..51108c2 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ JRedisGraph Official client for Redis-Graph - https://oss.redislabs.com/redisgraph + https://redisgraph.io RedisLabs @@ -18,16 +18,16 @@ CircleCI - https://circleci.com/gh/RedisLabs/JRedisGraph + https://circleci.com/gh/RedisGraph/JRedisGraph - https://github.com/RedisLabs/JRedisGraph/issues + https://github.com/RedisGraph/JRedisGraph/issues Github - https://github.com/RedisLabs/JRedisGraph - scm:git:git://github.com/RedisLabs/JRedisGraph.git - scm:git:git@github.com:RedisLabs/JRedisGraph.git + https://github.com/RedisGraph/JRedisGraph + scm:git:git://github.com/RedisGraph/JRedisGraph.git + scm:git:git@github.com:RedisGraph/JRedisGraph.git @@ -48,17 +48,6 @@ - - org.apache.commons - commons-pool2 - 2.8.0 - - - junit - junit - 4.12 - test - redis.clients jedis @@ -69,6 +58,12 @@ commons-text 1.9 + + junit + junit + 4.12 + test + org.slf4j slf4j-simple diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index dbc746a..7216ac4 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -88,7 +88,7 @@ public static String prepareQuery(String query, Map params){ private static String arrayToString(Object[] arr) { StringBuilder sb = new StringBuilder().append('['); - sb.append(String.join(", ", Arrays.stream(arr).map(obj->valueToString(obj)).collect(Collectors.toList()))); + sb.append(String.join(", ", Arrays.stream(arr).map(Utils::valueToString).collect(Collectors.toList()))); sb.append(']'); return sb.toString(); } @@ -119,22 +119,22 @@ private static String valueToString(Object value) { * @return formatter procedure call */ public static String prepareProcedure(String procedure, List args , Map> kwargs){ - args = args.stream().map( s -> Utils.quoteString(s)).collect(Collectors.toList()); + args = args.stream().map( Utils::quoteString).collect(Collectors.toList()); StringBuilder queryStringBuilder = new StringBuilder(); - queryStringBuilder.append("CALL ").append(procedure).append("("); + queryStringBuilder.append("CALL ").append(procedure).append('('); int i = 0; for (; i < args.size() - 1; i++) { - queryStringBuilder.append(args.get(i)).append(","); + queryStringBuilder.append(args.get(i)).append(','); } if (i == args.size()-1) { queryStringBuilder.append(args.get(i)); } - queryStringBuilder.append(")"); + queryStringBuilder.append(')'); List kwargsList = kwargs.getOrDefault("y", null); if(kwargsList != null){ i = 0; for (; i < kwargsList.size() - 1; i++) { - queryStringBuilder.append(kwargsList.get(i)).append(","); + queryStringBuilder.append(kwargsList.get(i)).append(','); } queryStringBuilder.append(kwargsList.get(i)); diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java index dec71f5..982bca5 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -13,8 +13,6 @@ */ public abstract class AbstractRedisGraph implements RedisGraph { - - /** * Inherited classes should return a Jedis connection, with respect to their context * @return Jedis connection diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index ab92534..9d4478d 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -19,7 +19,7 @@ */ public class ContextedRedisGraph extends AbstractRedisGraph implements RedisGraphContext, RedisGraphCacheHolder { - private Jedis connectionContext; + private final Jedis connectionContext; private RedisGraphCaches caches; /** diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index d3bea57..5737205 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -15,7 +15,7 @@ public class RedisGraph extends AbstractRedisGraph implements RedisGraphContextGenerator { private final Pool client; - private RedisGraphCaches caches = new RedisGraphCaches(); + private final RedisGraphCaches caches = new RedisGraphCaches(); /** * Creates a client running on the local machine diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java index a9ae068..c4e6c1e 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/HeaderImpl.java @@ -36,7 +36,7 @@ public HeaderImpl(List> raw) { */ @Override public List getSchemaNames() { - if (schemaNames.size() == 0) { + if (schemaNames.isEmpty()) { buildSchema(); } return schemaNames; @@ -47,7 +47,7 @@ public List getSchemaNames() { */ @Override public List getSchemaTypes() { - if (schemaTypes.size() == 0) { + if (schemaTypes.isEmpty()) { buildSchema(); } return schemaTypes; diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 7d42997..51d5eac 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -177,15 +177,17 @@ public void testHeader(){ ResultSet queryResult = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age"); - Assert.assertNotNull(queryResult.getHeader()); Header header = queryResult.getHeader(); - + Assert.assertNotNull(header); + Assert.assertEquals("HeaderImpl{" + + "schemaTypes=[COLUMN_SCALAR, COLUMN_SCALAR, COLUMN_SCALAR], " + + "schemaNames=[a, r, a.age]}", header.toString()); +// Assert.assertEquals(-1901778507, header.hashCode()); + List schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); - Assert.assertEquals(3, schemaNames.size()); - Assert.assertEquals("a", schemaNames.get(0)); Assert.assertEquals("r", schemaNames.get(1)); Assert.assertEquals("a.age", schemaNames.get(2)); @@ -315,6 +317,7 @@ public void testRecord(){ } + @Ignore @Test public void tinyTestMultiThread(){ ResultSet resultSet = api.query("social", "CREATE ({name:'roi',age:32})"); @@ -340,7 +343,7 @@ public void testMultiThread(){ Property nameProperty = new Property<>("name", "roi"); Property ageProperty = new Property<>("age", 32); - Property lastNameProperty =new Property<>("lastName", "a"); + Property lastNameProperty = new Property<>("lastName", "a"); Node expectedNode = new Node(); expectedNode.setId(0); From 4cf34bb314bb15e5e7a7b33019620f3049158405 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Oct 2020 09:54:55 +0300 Subject: [PATCH 068/128] Bump junit from 4.12 to 4.13.1 (#85) Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 51108c2..4a83586 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ junit junit - 4.12 + 4.13.1 test From dda3619afc3d075d1f8efc90bef710a89cb345fc Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 18 Oct 2020 13:12:59 +0300 Subject: [PATCH 069/128] fix character handling in params (#84) * fix charecter handling in params * added char test --- src/main/java/com/redislabs/redisgraph/impl/Utils.java | 3 +++ src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index 7216ac4..5b7fd6e 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -99,6 +99,9 @@ private static String valueToString(Object value) { if(String.class.isInstance(value)){ return quoteString((String) value); } + if(Character.class.isInstance((value))){ + return quoteString(((Character)value).toString()); + } if(value.getClass().isArray()){ return arrayToString((Object[]) value); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 51d5eac..f1f3a60 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -879,8 +879,8 @@ public void testPath(){ @Test public void testParameters(){ - Object[] parameters = {1, 2.3, true, false, null, "str", Arrays.asList(1,2,3), new Integer[]{1,2,3}}; - Object[] expected_anwsers = {1L, 2.3, true, false, null, "str", Arrays.asList(1L, 2L, 3L), new Long[]{1L, 2L, 3L}}; + Object[] parameters = {1, 2.3, true, false, null, "str", 'a', "b" ,Arrays.asList(1,2,3), new Integer[]{1,2,3}}; + Object[] expected_anwsers = {1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), new Long[]{1L, 2L, 3L}}; Map params = new HashMap<>(); for (int i=0; i < parameters.length; i++) { Object param = parameters[i]; From 6d7ead9425f8b0197bd78fe971c109ca12541099 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 27 Oct 2020 16:30:04 +0200 Subject: [PATCH 070/128] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06b8432..3e5b9cb 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ # JRedisGraph [![Forum](https://img.shields.io/badge/Forum-RedisGraph-blue)](https://forum.redislabs.com/c/modules/redisgraph) -[![Gitter](https://badges.gitter.im/RedisLabs/RedisGraph.svg)](https://gitter.im/RedisLabs/RedisGraph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Discord](https://img.shields.io/discord/697882427875393627?style=flat-square)](https://discord.gg/gWBRT6P) RedisGraph Java client From a44d01a74a340255f3fe735f352348e870f98d53 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 28 Oct 2020 09:15:00 +0200 Subject: [PATCH 071/128] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3e5b9cb..1849176 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph) [![Javadocs](https://www.javadoc.io/badge/com.redislabs/jredisgraph.svg)](https://www.javadoc.io/doc/com.redislabs/jredisgraph) [![Codecov](https://codecov.io/gh/RedisGraph/JRedisGraph/branch/master/graph/badge.svg)](https://codecov.io/gh/RedisGraph/JRedisGraph) +[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/RedisGraph/JRedisGraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/RedisGraph/JRedisGraph/context:java) [![Known Vulnerabilities](https://snyk.io/test/github/RedisGraph/JRedisGraph/badge.svg?targetFile=pom.xml)](https://snyk.io/test/github/RedisGraph/JRedisGraph?targetFile=pom.xml) # JRedisGraph From a0f077f12378619ad56b28d44c6b57bfaf783a86 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 2 Nov 2020 12:11:09 +0200 Subject: [PATCH 072/128] Fix #87 always add quotes to string params and escape (#88) * Fix #87 always add quotes to string params and escape * replace with instanceof --- .../com/redislabs/redisgraph/impl/Utils.java | 23 +++++++------------ .../redislabs/redisgraph/impl/UtilsTest.java | 8 +++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index 5b7fd6e..cdb1d83 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -31,18 +31,10 @@ private Utils() {} * @return the input string surrounded with quotation marks, if needed */ private static String quoteString(String str){ - if(str.startsWith("\"") && str.endsWith("\"")){ - return str; - } - StringBuilder sb = new StringBuilder(str.length()+2); - if(str.charAt(0)!='"'){ - sb.append('"'); - } - sb.append(str); - if (str.charAt(str.length()-1)!= '"'){ - sb.append('"'); - } + sb.append('"'); + sb.append(str.replace("\"","\\\"")); + sb.append('"'); return sb.toString(); } @@ -96,18 +88,19 @@ private static String arrayToString(Object[] arr) { private static String valueToString(Object value) { if(value == null) return "null"; - if(String.class.isInstance(value)){ + + if(value instanceof String){ return quoteString((String) value); } - if(Character.class.isInstance((value))){ + if(value instanceof Character){ return quoteString(((Character)value).toString()); } - if(value.getClass().isArray()){ + if(value instanceof Object[]){ return arrayToString((Object[]) value); } - if(List.class.isInstance(value)){ + if(value instanceof List){ List list = (List)value; return arrayToString(list.toArray()); } diff --git a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java index 9caed94..2129f61 100644 --- a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java +++ b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java @@ -40,6 +40,12 @@ public void prepareQuery() { @Test public void testParamsPrep(){ Map params = new HashMap<>(); + params.put("param", ""); + Assert.assertEquals("CYPHER param=\"\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "\""); + Assert.assertEquals("CYPHER param=\"\\\"\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "\"st"); + Assert.assertEquals("CYPHER param=\"\\\"st\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); params.put("param", 1); Assert.assertEquals("CYPHER param=1 RETURN $param", Utils.prepareQuery("RETURN $param", params)); params.put("param", 2.3); @@ -52,6 +58,8 @@ public void testParamsPrep(){ Assert.assertEquals("CYPHER param=null RETURN $param", Utils.prepareQuery("RETURN $param", params)); params.put("param", "str"); Assert.assertEquals("CYPHER param=\"str\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "s\"tr"); + Assert.assertEquals("CYPHER param=\"s\\\"tr\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); Integer arr[] = {1,2,3}; params.put("param", arr); Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); From 91ad26397577d8a465654fe2bbff4b6c702f6d7a Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 2 Nov 2020 12:34:27 +0200 Subject: [PATCH 073/128] Bump version --- README.md | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1849176..f14dace 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.1.0 + 2.2.0 ``` @@ -43,7 +43,7 @@ and com.redislabs jredisgraph - 2.2.0-SNAPSHOT + 2.3.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 4a83586..e4605d4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.2.0-SNAPSHOT + 2.3.0-SNAPSHOT JRedisGraph Official client for Redis-Graph From b0adafaf40993bd5378173dfa048120d9f71c0d0 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 29 Nov 2020 16:46:55 +0200 Subject: [PATCH 074/128] removed null properties (#94) --- .../redisgraph/RedisGraphAPITest.java | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index f1f3a60..8570355 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -210,7 +210,6 @@ public void testRecord(){ Property doubleProperty = new Property<>("doubleValue", doubleValue); Property trueBooleanProperty = new Property<>("boolValue", true); Property falseBooleanProperty = new Property<>("boolValue", false); - Property nullProperty = new Property<>("nullValue", null); Property placeProperty = new Property<>("place", place); Property sinceProperty = new Property<>("since", since); @@ -222,13 +221,11 @@ public void testRecord(){ expectedNode.addProperty(ageProperty); expectedNode.addProperty(doubleProperty); expectedNode.addProperty(trueBooleanProperty); - expectedNode.addProperty(nullProperty); Assert.assertEquals( "Node{labels=[person], id=0, " + "propertyMap={name=Property{name='name', value=roi}, " + "boolValue=Property{name='boolValue', value=true}, " + "doubleValue=Property{name='doubleValue', value=3.14}, " - + "nullValue=Property{name='nullValue', value=null}, " + "age=Property{name='age', value=32}}}", expectedNode.toString()); Edge expectedEdge = new Edge(); @@ -240,12 +237,10 @@ public void testRecord(){ expectedEdge.addProperty(sinceProperty); expectedEdge.addProperty(doubleProperty); expectedEdge.addProperty(falseBooleanProperty); - expectedEdge.addProperty(nullProperty); Assert.assertEquals("Edge{relationshipType='knows', source=0, destination=1, id=0, " + "propertyMap={boolValue=Property{name='boolValue', value=false}, " + "place=Property{name='place', value=TLV}, " + "doubleValue=Property{name='doubleValue', value=3.14}, " - + "nullValue=Property{name='nullValue', value=null}, " + "since=Property{name='since', value=2000}}}", expectedEdge.toString()); Map params = new HashMap<>(); @@ -254,14 +249,14 @@ public void testRecord(){ params.put("boolValue", boolValue); params.put("doubleValue", doubleValue); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:$name,age:$age, doubleValue:$doubleValue, boolValue:$boolValue, nullValue:null})", params)); + Assert.assertNotNull(api.query("social", "CREATE (:person{name:$name,age:$age, doubleValue:$doubleValue, boolValue:$boolValue})", params)); Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + - "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false}]->(b)")); ResultSet resultSet = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + - "a.name, a.age, a.doubleValue, a.boolValue, a.nullValue, " + - "r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); + "a.name, a.age, a.doubleValue, a.boolValue, " + + "r.place, r.since, r.doubleValue, r.boolValue"); Assert.assertNotNull(resultSet); @@ -294,12 +289,12 @@ public void testRecord(){ edge = record.getValue("r"); Assert.assertEquals(expectedEdge, edge); - Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", "a.nullValue", - "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); + Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", + "r.place", "r.since", "r.doubleValue", "r.boolValue"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, (long)age, doubleValue, true, null, - place, (long)since, doubleValue, false, null), + name, (long)age, doubleValue, true, + place, (long)since, doubleValue, false), record.values()); Node a = record.getValue("a"); @@ -602,7 +597,6 @@ public void testContextedAPI() { Property doubleProperty = new Property<>("doubleValue", doubleValue); Property trueBooleanProperty = new Property<>("boolValue", true); Property falseBooleanProperty = new Property<>("boolValue", false); - Property nullProperty = new Property<>("nullValue", null); Property placeProperty = new Property<>("place", place); Property sinceProperty = new Property<>("since", since); @@ -614,7 +608,6 @@ public void testContextedAPI() { expectedNode.addProperty(ageProperty); expectedNode.addProperty(doubleProperty); expectedNode.addProperty(trueBooleanProperty); - expectedNode.addProperty(nullProperty); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -625,7 +618,6 @@ public void testContextedAPI() { expectedEdge.addProperty(sinceProperty); expectedEdge.addProperty(doubleProperty); expectedEdge.addProperty(falseBooleanProperty); - expectedEdge.addProperty(nullProperty); Map params = new HashMap<>(); params.put("name", name); @@ -633,14 +625,14 @@ public void testContextedAPI() { params.put("boolValue", boolValue); params.put("doubleValue", doubleValue); try (RedisGraphContext c = api.getContext()) { - Assert.assertNotNull(c.query("social", "CREATE (:person{name:$name, age:$age, doubleValue:$doubleValue, boolValue:$boolValue, nullValue:null})", params)); + Assert.assertNotNull(c.query("social", "CREATE (:person{name:$name, age:$age, doubleValue:$doubleValue, boolValue:$boolValue})", params)); Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + - "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false}]->(b)")); ResultSet resultSet = c.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + - "a.name, a.age, a.doubleValue, a.boolValue, a.nullValue, " + - "r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); + "a.name, a.age, a.doubleValue, a.boolValue, " + + "r.place, r.since, r.doubleValue, r.boolValue"); Assert.assertNotNull(resultSet); Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); @@ -671,12 +663,12 @@ public void testContextedAPI() { edge = record.getValue("r"); Assert.assertEquals(expectedEdge, edge); - Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", "a.nullValue", - "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue"), record.keys()); + Assert.assertEquals(Arrays.asList("a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", + "r.place", "r.since", "r.doubleValue", "r.boolValue"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, (long)age, doubleValue, true, null, - place, (long)since, doubleValue, false, null), + name, (long)age, doubleValue, true, + place, (long)since, doubleValue, false), record.values()); Node a = record.getValue("a"); From 89a975c102206bb54a3e3f1ce5cfdd30342aed12 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 23 Dec 2020 00:19:07 +0200 Subject: [PATCH 075/128] public ctors (#96) --- .../com/redislabs/redisgraph/impl/resultset/RecordImpl.java | 2 +- .../com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java index adf68ad..31bec44 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/RecordImpl.java @@ -10,7 +10,7 @@ public class RecordImpl implements Record { private final List header; private final List values; - RecordImpl(List header, List values){ + public RecordImpl(List header, List values){ this.header=header; this.values = values; } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java index 727ec53..1f58fe5 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/StatisticsImpl.java @@ -23,7 +23,7 @@ public class StatisticsImpl implements Statistics { * Each string is built in the form of "K:V" where K is statistics label and V is its value. * @param raw a raw representation of the query execution statistics */ - StatisticsImpl(List raw){ + public StatisticsImpl(List raw){ this.raw = raw; this.statistics = new EnumMap<>(Statistics.Label.class); // lazy loaded } From 42a5498fe35a9e3b74bdf1b4aecd945d1c03b13d Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 28 Dec 2020 13:46:32 +0200 Subject: [PATCH 076/128] Upgrade jedis to 3.4.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e4605d4..93f8c92 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.3.0 + 3.4.1 org.apache.commons From 7f07535bf161efaed20e592c980495b75e126e72 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 29 Dec 2020 14:05:23 +0200 Subject: [PATCH 077/128] results set is iterable --- .../com/redislabs/redisgraph/ResultSet.java | 2 +- .../impl/resultset/ResultSetImpl.java | 11 ++++ .../redislabs/redisgraph/testIterable.java | 66 +++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/redislabs/redisgraph/testIterable.java diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index a901594..d86ff19 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -5,7 +5,7 @@ /** * Hold a query result */ -public interface ResultSet extends Iterator { +public interface ResultSet extends Iterable, Iterator { int size(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index b852c5b..f27aa34 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -12,11 +12,13 @@ import redis.clients.jedis.exceptions.JedisDataException; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; public class ResultSetImpl implements ResultSet { + private final Header header; private final Statistics statistics; @@ -275,11 +277,13 @@ private ResultSetScalarTypes getValueTypeFromObject(Object rawScalarType) { } @Override + @Deprecated public boolean hasNext() { return position < results.size(); } @Override + @Deprecated public Record next() { if (!hasNext()) throw new NoSuchElementException(); @@ -316,4 +320,11 @@ public String toString() { sb.append('}'); return sb.toString(); } + + + @Override + public Iterator iterator() { + // TODO Auto-generated method stub + return results.iterator(); + } } diff --git a/src/test/java/com/redislabs/redisgraph/testIterable.java b/src/test/java/com/redislabs/redisgraph/testIterable.java new file mode 100644 index 0000000..8af8cf5 --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/testIterable.java @@ -0,0 +1,66 @@ +package com.redislabs.redisgraph; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.redislabs.redisgraph.impl.api.RedisGraph; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class testIterable { + + private RedisGraphContextGenerator api; + + @Before + public void createApi() { + // api = new RedisGraph(); + api = new RedisGraph(); + } + + @After + public void deleteGraph() { + + api.deleteGraph("social"); + api.close(); + } + + @Test + public void testRecordsIterator() { + api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); + + ResultSet rs = api.query("social", "MATCH(n) RETURN n"); + int count = 0; + while (rs.hasNext()) { + rs.next(); + count++; + } + assertEquals(rs.size(), count); + } + + @Test + public void testRecordsIterable() { + api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); + + ResultSet rs = api.query("social", "MATCH(n) RETURN n"); + int count = 0; + for(Record row: rs) { + count++; + } + assertEquals(rs.size(), count); + } + + @Test + public void testRecordsIteratorAndIterable() { + api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); + + ResultSet rs = api.query("social", "MATCH(n) RETURN n"); + rs.next(); + int count = 0; + for(Record row: rs) { + count++; + } + assertEquals(rs.size(), count); + } + +} From 9fab930db33298a8e5efca563457d421bdbc0f55 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Tue, 29 Dec 2020 14:14:11 +0200 Subject: [PATCH 078/128] renamed test class for maven locate --- .../redisgraph/{testIterable.java => IterableTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/test/java/com/redislabs/redisgraph/{testIterable.java => IterableTest.java} (93%) diff --git a/src/test/java/com/redislabs/redisgraph/testIterable.java b/src/test/java/com/redislabs/redisgraph/IterableTest.java similarity index 93% rename from src/test/java/com/redislabs/redisgraph/testIterable.java rename to src/test/java/com/redislabs/redisgraph/IterableTest.java index 8af8cf5..8ca962f 100644 --- a/src/test/java/com/redislabs/redisgraph/testIterable.java +++ b/src/test/java/com/redislabs/redisgraph/IterableTest.java @@ -8,7 +8,7 @@ import org.junit.Before; import org.junit.Test; -public class testIterable { +public class IterableTest { private RedisGraphContextGenerator api; From af71310694b6689aeadb6726f2c16a8d057e0695 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Wed, 13 Jan 2021 00:33:21 +0600 Subject: [PATCH 079/128] Support query timeout (#98) * Support query timeout * snapshot repo Co-authored-by: Guy Korland --- pom.xml | 9 +++- .../com/redislabs/redisgraph/RedisGraph.java | 18 ++++++++ .../redisgraph/RedisGraphTransaction.java | 20 +++++++++ .../com/redislabs/redisgraph/impl/Utils.java | 1 + .../impl/api/AbstractRedisGraph.java | 34 +++++++++++++++ .../impl/api/ContextedRedisGraph.java | 23 ++++++++++ .../redisgraph/impl/api/RedisGraph.java | 15 +++++++ .../impl/api/RedisGraphTransaction.java | 42 +++++++++++++++++++ .../redisgraph/RedisGraphAPITest.java | 36 +++++++--------- .../exceptions/JRedisGraphErrorTest.java | 8 ++++ 10 files changed, 185 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index 93f8c92..e16e3d8 100644 --- a/pom.xml +++ b/pom.xml @@ -47,11 +47,18 @@ + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + + redis.clients jedis - 3.4.1 + 3.5.0-SNAPSHOT org.apache.commons diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index e672666..3a2ae19 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -14,6 +14,14 @@ public interface RedisGraph extends Closeable { */ ResultSet query(String graphId, String query); + /** + * Execute a Cypher query with timeout. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a result set + */ + ResultSet query(String graphId, String query, long timeout); /** * Execute a Cypher query with arguments @@ -35,6 +43,16 @@ public interface RedisGraph extends Closeable { */ ResultSet query(String graphId, String query, Map params); + /** + * Executes a cypher query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a result set. + */ + ResultSet query(String graphId, String query, Map params, long timeout); + /** * Invokes stored procedures without arguments * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java index fbde12c..08259fe 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java @@ -22,6 +22,7 @@ public interface RedisGraphTransaction extends MultiKeyCommandsPipeline, ClusterPipeline, BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline, BasicRedisPipeline, BinaryRedisPipeline, RedisPipeline, Closeable { + /** * Execute a Cypher query. * @param graphId a graph to perform the query on @@ -30,6 +31,15 @@ public interface RedisGraphTransaction extends */ Response query(String graphId, String query); + /** + * Execute a Cypher query with timeout. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query, long timeout); + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on @@ -50,6 +60,16 @@ public interface RedisGraphTransaction extends */ Response query(String graphId, String query, Map params); + /** + * Executes a cypher query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query, Map params, long timeout); + /** * Invokes stored procedures without arguments * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index cdb1d83..cdcff78 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -14,6 +14,7 @@ public class Utils { public static final List DUMMY_LIST = new ArrayList<>(0); public static final Map> DUMMY_MAP = new HashMap<>(0); public static final String COMPACT_STRING = "--COMPACT"; + public static final String TIMEOUT_STRING = "TIMEOUT"; private static final CharSequenceTranslator ESCAPE_CHYPER; static { diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java index 982bca5..e1149e0 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -27,6 +27,15 @@ public abstract class AbstractRedisGraph implements RedisGraph { */ protected abstract ResultSet sendQuery(String graphId, String preparedQuery); + /** + * Sends a query to the redis graph.Implementation and context dependent + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @param timeout + * @return Result set + */ + protected abstract ResultSet sendQuery(String graphId, String preparedQuery, long timeout); + /** * Execute a Cypher query. * @param graphId a graph to perform the query on @@ -37,6 +46,18 @@ public ResultSet query(String graphId, String query) { return sendQuery(graphId, query); } + /** + * Execute a Cypher query with timeout. + * @param graphId a graph to perform the query on + * @param timeout + * @param query Cypher query + * @return a result set + */ + @Override + public ResultSet query(String graphId, String query, long timeout) { + return sendQuery(graphId, query, timeout); + } + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on @@ -63,6 +84,19 @@ public ResultSet query(String graphId, String query, Map params) return sendQuery(graphId, preparedQuery); } + /** + * Executes a cypher query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param timeout + * @param query Cypher query. + * @param params parameters map. + * @return a result set. + */ + @Override + public ResultSet query(String graphId, String query, Map params, long timeout) { + String preparedQuery = Utils.prepareQuery(query, params); + return sendQuery(graphId, preparedQuery, timeout); + } public ResultSet callProcedure(String graphId, String procedure){ return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index 9d4478d..fb9fce9 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -60,6 +60,29 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { } } + /** + * Sends the query over the instance only connection + * @param graphId graph to be queried + * @param timeout + * @param preparedQuery prepared query + * @return Result set with the query answer + */ + @Override + protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout) { + Jedis conn = getConnection(); + try { + List rawResponse = (List) conn.sendBlockingCommand(RedisGraphCommand.QUERY, + graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); + } + catch (JRedisGraphRunTimeException rt) { + throw rt; + } + catch (JedisDataException j) { + throw new JRedisGraphCompileTimeException(j); + } + } + /** * @return Returns the instance Jedis connection. */ diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index 5737205..c2f4cc2 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -69,6 +69,21 @@ protected ResultSet sendQuery(String graphId, String preparedQuery){ } } + /** + * Overrides the abstract function. + * Sends the query from any Jedis connection received from the Jedis pool and closes it once done + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @param timeout + * @return Result set with the query answer + */ + @Override + protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout){ + try (ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection())) { + contextedRedisGraph.setRedisGraphCaches(caches); + return contextedRedisGraph.sendQuery(graphId, preparedQuery, timeout); + } + } /** * Closes the Jedis pool diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 11fca09..c96c749 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -47,6 +47,26 @@ public ResultSet build(Object o) { }); } + /** + * Execute a Cypher query with timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query, long timeout) { + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Execute a Cypher query with arguments * @@ -88,6 +108,28 @@ public ResultSet build(Object o) { }); } + /** + * Executes a cypher query with parameters and timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query, Map params, long timeout) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } /** * Invokes stored procedures without arguments, in multi/exec context diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 8570355..9e3769a 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -1,22 +1,20 @@ package com.redislabs.redisgraph; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - +import com.redislabs.redisgraph.Statistics.Label; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Path; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; +import com.redislabs.redisgraph.impl.resultset.RecordImpl; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import com.redislabs.redisgraph.test.utils.PathBuilder; -import org.junit.*; +import redis.clients.jedis.exceptions.JedisDataException; -import com.redislabs.redisgraph.Statistics.Label; - -import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.*; public class RedisGraphAPITest { @@ -29,20 +27,18 @@ public RedisGraphAPITest() { public void createApi(){ api = new RedisGraph(); } + @After public void deleteGraph() { - api.deleteGraph("social"); api.close(); } - @Test public void testCreateNode() { // Create a node ResultSet resultSet = api.query("social", "CREATE ({name:'roi',age:32})"); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); Assert.assertNull(resultSet.getStatistics().getStringValue(Label.NODES_DELETED)); Assert.assertNull(resultSet.getStatistics().getStringValue(Label.RELATIONSHIPS_CREATED)); @@ -116,8 +112,6 @@ public void testDeleteNodes(){ Assert.assertNotNull(deleteResult.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); - - } @Test @@ -192,7 +186,6 @@ public void testHeader(){ Assert.assertEquals("r", schemaNames.get(1)); Assert.assertEquals("a.age", schemaNames.get(2)); - } @Test @@ -311,7 +304,6 @@ public void testRecord(){ } - @Ignore @Test public void tinyTestMultiThread(){ @@ -322,9 +314,7 @@ public void tinyTestMultiThread(){ mapToObj( j-> api.query("social", "MATCH (a:person) RETURN a")). collect(Collectors.toList()); - } - } @Test @@ -484,7 +474,6 @@ record = resultSet.next(); } - @Test public void testEscapedQuery() { Assert.assertNotNull(api.query("social", "CREATE (:escaped{s1:%s,s2:%s})", "S\"'", "S'\"")); @@ -492,7 +481,6 @@ public void testEscapedQuery() { Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"' RETURN n")); } - @Test public void testMultiExec(){ try (RedisGraphContext c = api.getContext()) { @@ -965,4 +953,12 @@ public void testCachedExecution() { Assert.assertEquals(params.get("val"), r.getValue(0)); Assert.assertTrue(resultSet.getStatistics().cachedExecution()); } + + @Test + public void timeoutArgument() { + ResultSet rs = api.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L); + Assert.assertEquals(1, rs.size()); + Record r = rs.next(); + Assert.assertEquals(Long.valueOf(100), r.getValue(0)); + } } diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index 443588c..18b2c21 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -138,4 +138,12 @@ public void testContextExceptionFlow() { } } + + @Test + public void timeoutExcpetion() { + exceptionRule.expect(JRedisGraphRunTimeException.class); + exceptionRule.expectMessage("Query timed out"); + + api.query("social", "UNWIND range(0,100000) AS x WITH x AS x WHERE x = 10000 RETURN x", 1L); + } } From 76dee5b8723a150c793994dab12e37b4efc15211 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 13 Jan 2021 10:47:19 +0200 Subject: [PATCH 080/128] map support --- .../impl/resultset/ResultSetImpl.java | 19 +++++++++++---- .../impl/resultset/ResultSetScalarTypes.java | 3 ++- .../redisgraph/RedisGraphAPITest.java | 23 +++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index f27aa34..ccbce15 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -11,11 +11,7 @@ import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.exceptions.JedisDataException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; +import java.util.*; public class ResultSetImpl implements ResultSet { @@ -244,12 +240,25 @@ private Object deserializeScalar(List rawScalarData) { return deserializeEdge((List) obj); case VALUE_PATH: return deserializePath(obj); + case VALUE_MAP: + return deserializeMap(obj); case VALUE_UNKNOWN: default: return obj; } } + private Map deserializeMap(Object rawScalarData) { + List> keyTypeValueEntries = (List>) rawScalarData; + Map map = new HashMap<>(); + for(List keyTypeValueEntry : keyTypeValueEntries) { + String key = SafeEncoder.encode((byte[])keyTypeValueEntry.get(0)); + Object value = deserializeScalar((List)keyTypeValueEntry.get(1)); + map.put(key, value); + } + return map; + } + private Path deserializePath(Object rawScalarData) { List> array = (List>) rawScalarData; List nodes = (List) deserializeScalar(array.get(0)); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java index 2f23ca8..e0ad7fa 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java @@ -12,7 +12,8 @@ enum ResultSetScalarTypes { VALUE_ARRAY, VALUE_EDGE, VALUE_NODE, - VALUE_PATH; + VALUE_PATH, + VALUE_MAP; private static final ResultSetScalarTypes[] values = values(); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 8570355..6a345e1 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -965,4 +965,27 @@ public void testCachedExecution() { Assert.assertEquals(params.get("val"), r.getValue(0)); Assert.assertTrue(resultSet.getStatistics().cachedExecution()); } + + @Test + public void testMapDataType() { + Map expexted = new HashMap<>(); + expexted.put("a", (long)1); + expexted.put("b", "str"); + expexted.put("c", null); + List d = new ArrayList<>(); + d.add((long)1); + d.add((long)2); + d.add((long)3); + expexted.put("d", d); + expexted.put("e", true); + Mapf = new HashMap<>(); + f.put("x", (long)1); + f.put("y", (long)2); + expexted.put("f", f); + ResultSet res = api.query("social", "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"); + Assert.assertEquals(1, res.size()); + Record r = res.next(); + Map actual = r.getValue(0); + Assert.assertEquals(expexted, actual); + } } From c185ae9458c1737c8dcfffa3bfcfca193a72d56b Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 13 Jan 2021 15:03:08 +0200 Subject: [PATCH 081/128] fixed typo --- .../redislabs/redisgraph/RedisGraphAPITest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index aef2b18..e0c4f09 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -956,25 +956,25 @@ public void testCachedExecution() { @Test public void testMapDataType() { - Map expexted = new HashMap<>(); - expexted.put("a", (long)1); - expexted.put("b", "str"); - expexted.put("c", null); + Map expected = new HashMap<>(); + expected.put("a", (long)1); + expected.put("b", "str"); + expected.put("c", null); List d = new ArrayList<>(); d.add((long)1); d.add((long)2); d.add((long)3); - expexted.put("d", d); - expexted.put("e", true); + expected.put("d", d); + expected.put("e", true); Mapf = new HashMap<>(); f.put("x", (long)1); f.put("y", (long)2); - expexted.put("f", f); + expected.put("f", f); ResultSet res = api.query("social", "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"); Assert.assertEquals(1, res.size()); Record r = res.next(); Map actual = r.getValue(0); - Assert.assertEquals(expexted, actual); + Assert.assertEquals(expected, actual); } @Test From edcfa2fe7ad185f8c0d2dfe7ea68015eef961bd2 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Wed, 20 Jan 2021 13:38:26 +0600 Subject: [PATCH 082/128] Jedis 3.5.0 is released officially (#103) --- pom.xml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index e16e3d8..33c5ed9 100644 --- a/pom.xml +++ b/pom.xml @@ -47,18 +47,11 @@ - - - - snapshots-repo - https://oss.sonatype.org/content/repositories/snapshots - - redis.clients jedis - 3.5.0-SNAPSHOT + 3.5.0 org.apache.commons From 8efc13171fdb99e3233383b8e81a406444e3fb64 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sat, 23 Jan 2021 23:32:41 +0200 Subject: [PATCH 083/128] changed according to new format --- .../impl/resultset/ResultSetImpl.java | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index ccbce15..b5b2082 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -14,11 +14,11 @@ import java.util.*; public class ResultSetImpl implements ResultSet { - + private final Header header; private final Statistics statistics; - private final List results ; + private final List results; private int position = 0; private final RedisGraph redisGraph; @@ -27,15 +27,15 @@ public class ResultSetImpl implements ResultSet { /** * @param rawResponse the raw representation of response is at most 3 lists of objects. * The last list is the statistics list. - * @param redisGraph the graph connection - * @param cache the graph local cache + * @param redisGraph the graph connection + * @param cache the graph local cache */ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache cache) { this.redisGraph = redisGraph; this.cache = cache; // If a run-time error occurred, the last member of the rawResponse will be a JedisDataException. - if (rawResponse.get(rawResponse.size()-1) instanceof JedisDataException) { + if (rawResponse.get(rawResponse.size() - 1) instanceof JedisDataException) { throw new JRedisGraphRunTimeException((Throwable) rawResponse.get(rawResponse.size() - 1)); } @@ -44,8 +44,8 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache header = parseHeader(new ArrayList<>()); results = new ArrayList<>(); - statistics = rawResponse.isEmpty() ? parseStatistics(new ArrayList()) : - parseStatistics(rawResponse.get(rawResponse.size() - 1)) ; + statistics = rawResponse.isEmpty() ? parseStatistics(new ArrayList()) : + parseStatistics(rawResponse.get(rawResponse.size() - 1)); } else { @@ -57,7 +57,6 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache /** - * * @param rawResultSet - raw result set representation * @return parsed result set */ @@ -84,10 +83,10 @@ private List parseResult(List> rawResultSet) { case COLUMN_RELATION: parsedRow.add(deserializeEdge(obj)); break; - case COLUMN_SCALAR: + case COLUMN_SCALAR: parsedRow.add(deserializeScalar(obj)); break; - default: + default: parsedRow.add(null); break; } @@ -102,7 +101,6 @@ private List parseResult(List> rawResultSet) { } /** - * * @param rawStatistics raw statistics representation * @return parsed statistics */ @@ -112,7 +110,6 @@ private StatisticsImpl parseStatistics(Object rawStatistics) { /** - * * @param rawHeader - raw header representation * @return parsed header */ @@ -176,11 +173,11 @@ private Edge deserializeEdge(List rawEdgeData) { deserializeGraphEntityId(edge, rawEdgeData.get(0)); String relationshipType = cache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue(), - redisGraph); + redisGraph); edge.setRelationshipType(relationshipType); - edge.setSource( (long) rawEdgeData.get(2)); - edge.setDestination( (long) rawEdgeData.get(3)); + edge.setSource((long) rawEdgeData.get(2)); + edge.setDestination((long) rawEdgeData.get(3)); deserializeGraphEntityProperties(edge, (List>) rawEdgeData.get(4)); @@ -201,7 +198,7 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List rawProperty : rawProperties) { Property property = new Property<>(); property.setName(cache.getPropertyName(((Long) rawProperty.get(0)).intValue(), - redisGraph)); + redisGraph)); //trimmed for getting to value using deserializeScalar List propertyScalar = rawProperty.subList(1, rawProperty.size()); @@ -249,11 +246,11 @@ private Object deserializeScalar(List rawScalarData) { } private Map deserializeMap(Object rawScalarData) { - List> keyTypeValueEntries = (List>) rawScalarData; + List keyTypeValueEntries = (List) rawScalarData; Map map = new HashMap<>(); - for(List keyTypeValueEntry : keyTypeValueEntries) { - String key = SafeEncoder.encode((byte[])keyTypeValueEntry.get(0)); - Object value = deserializeScalar((List)keyTypeValueEntry.get(1)); + for (int i = 0; i < keyTypeValueEntries.size(); i += 2) { + String key = SafeEncoder.encode((byte[]) keyTypeValueEntries.get(i)); + Object value = deserializeScalar((List) keyTypeValueEntries.get(i + 1)); map.put(key, value); } return map; @@ -331,9 +328,9 @@ public String toString() { } - @Override - public Iterator iterator() { - // TODO Auto-generated method stub - return results.iterator(); - } + @Override + public Iterator iterator() { + // TODO Auto-generated method stub + return results.iterator(); + } } From 4802ba2c370203299ca8439b6a932c579d266703 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Sun, 24 Jan 2021 09:48:03 +0200 Subject: [PATCH 084/128] update jedis 3.5.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33c5ed9..9868383 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.5.0 + 3.5.1 org.apache.commons From 541eed4435c8af6aed0ead0f562a5b2514377fca Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Sun, 28 Feb 2021 20:13:27 +0200 Subject: [PATCH 085/128] Create release-drafter-config.yml (#109) * Create release-drafter-config.yml * [add] Added missing workflow config to release drafter automation * [add] Added missing workflow config to release drafter automation Co-authored-by: filipecosta90 --- .github/release-drafter-config.yml | 21 +++++++++++++++++++++ .github/workflows/release-drafter.yml | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 .github/release-drafter-config.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml new file mode 100644 index 0000000..0eb1ee3 --- /dev/null +++ b/.github/release-drafter-config.yml @@ -0,0 +1,21 @@ +name-template: 'Version $NEXT_PATCH_VERSION' +tag-template: 'v$NEXT_PATCH_VERSION' +categories: + - title: 'Features' + labels: + - 'feature' + - 'enhancement' + - title: 'Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: 'Maintenance' + label: 'chore' +change-template: '- $TITLE (#$NUMBER)' +exclude-labels: + - 'skip-changelog' +template: | + ## Changes + + $CHANGES diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..caac3ca --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,20 @@ +name: Release Drafter + +on: + push: + # branches to consider in the event; optional, defaults to all + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml + config-name: release-drafter-config.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + From ed0c37c6708709ec0a27140897ac1a496b586010 Mon Sep 17 00:00:00 2001 From: Jeffrey Lovitz Date: Mon, 1 Mar 2021 03:18:12 -0500 Subject: [PATCH 086/128] Don't use separate error classes for run-time and compile-time exceptions (#108) Co-authored-by: DvirDukhan --- .../JRedisGraphCompileTimeException.java | 21 ------------------ .../exceptions/JRedisGraphException.java | 21 ++++++++++++++++++ .../JRedisGraphRunTimeException.java | 21 ------------------ .../impl/api/ContextedRedisGraph.java | 11 +++++----- .../impl/resultset/ResultSetImpl.java | 4 ++-- .../exceptions/JRedisGraphErrorTest.java | 22 +++++++++---------- 6 files changed, 39 insertions(+), 61 deletions(-) delete mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java create mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java delete mode 100644 src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java deleted file mode 100644 index 1574147..0000000 --- a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphCompileTimeException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redislabs.redisgraph.exceptions; - -import redis.clients.jedis.exceptions.JedisDataException; - -/** - * RedisGraph query syntax evaluation exception. An instance of JRedisGraphRunTimeException is thrown when RedisGraph - * encounters an error during query syntax evaluation. - */ -public class JRedisGraphCompileTimeException extends JedisDataException { - public JRedisGraphCompileTimeException(String message) { - super(message); - } - - public JRedisGraphCompileTimeException(Throwable cause) { - super(cause); - } - - public JRedisGraphCompileTimeException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java new file mode 100644 index 0000000..db31104 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java @@ -0,0 +1,21 @@ +package com.redislabs.redisgraph.exceptions; + +import redis.clients.jedis.exceptions.JedisDataException; + +/** + * RedisGraph query evaluation exception. An instance of JRedisGraphException is thrown when RedisGraph + * encounters an error during query evaluation. + */ +public class JRedisGraphException extends JedisDataException { + public JRedisGraphException(String message) { + super(message); + } + + public JRedisGraphException(Throwable cause) { + super(cause); + } + + public JRedisGraphException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java deleted file mode 100644 index 62d083f..0000000 --- a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphRunTimeException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redislabs.redisgraph.exceptions; - -import redis.clients.jedis.exceptions.JedisDataException; - -/** - * RedisGraph runtime exception. An instance of JRedisGraphRunTimeException is thrown when RedisGraph - * encounters a runtime error during query execution. - */ -public class JRedisGraphRunTimeException extends JedisDataException { - public JRedisGraphRunTimeException(String message) { - super(message); - } - - public JRedisGraphRunTimeException(Throwable cause) { - super(cause); - } - - public JRedisGraphRunTimeException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index fb9fce9..7918c37 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -2,8 +2,7 @@ import com.redislabs.redisgraph.RedisGraphContext; import com.redislabs.redisgraph.ResultSet; -import com.redislabs.redisgraph.exceptions.JRedisGraphCompileTimeException; -import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException; +import com.redislabs.redisgraph.exceptions.JRedisGraphException; import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; @@ -52,11 +51,11 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } - catch (JRedisGraphRunTimeException rt) { + catch (JRedisGraphException rt) { throw rt; } catch (JedisDataException j) { - throw new JRedisGraphCompileTimeException(j); + throw new JRedisGraphException(j); } } @@ -75,11 +74,11 @@ protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); } - catch (JRedisGraphRunTimeException rt) { + catch (JRedisGraphException rt) { throw rt; } catch (JedisDataException j) { - throw new JRedisGraphCompileTimeException(j); + throw new JRedisGraphException(j); } } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index b5b2082..179db89 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -5,7 +5,7 @@ import com.redislabs.redisgraph.RedisGraph; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.Statistics; -import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException; +import com.redislabs.redisgraph.exceptions.JRedisGraphException; import com.redislabs.redisgraph.graph_entities.*; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; import redis.clients.jedis.util.SafeEncoder; @@ -37,7 +37,7 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache // If a run-time error occurred, the last member of the rawResponse will be a JedisDataException. if (rawResponse.get(rawResponse.size() - 1) instanceof JedisDataException) { - throw new JRedisGraphRunTimeException((Throwable) rawResponse.get(rawResponse.size() - 1)); + throw new JRedisGraphException((Throwable) rawResponse.get(rawResponse.size() - 1)); } if (rawResponse.size() != 3) { diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index 18b2c21..5840735 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -34,7 +34,7 @@ public void deleteGraph() { @Test public void testSyntaxErrorReporting() { - exceptionRule.expect(JRedisGraphCompileTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); // Issue a query that causes a compile-time error @@ -44,7 +44,7 @@ public void testSyntaxErrorReporting() { @Test public void testRuntimeErrorReporting() { - exceptionRule.expect(JRedisGraphRunTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); // Issue a query that causes a run-time error @@ -59,7 +59,7 @@ public void testExceptionFlow() { api.query("social", "RETURN toUpper(5)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphCompileTimeException.class, e.getClass()); + Assert.assertEquals(JRedisGraphException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -70,7 +70,7 @@ public void testExceptionFlow() { api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphRunTimeException.class, e.getClass()); + Assert.assertEquals(JRedisGraphException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -79,7 +79,7 @@ public void testExceptionFlow() { @Test public void testContextSyntaxErrorReporting() { - exceptionRule.expect(JRedisGraphCompileTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); RedisGraphContext c = api.getContext(); @@ -90,21 +90,21 @@ public void testContextSyntaxErrorReporting() { @Test public void testMissingParametersSyntaxErrorReporting(){ - exceptionRule.expect(JRedisGraphRunTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Missing parameters"); api.query("social","RETURN $param"); } @Test public void testMissingParametersSyntaxErrorReporting2(){ - exceptionRule.expect(JRedisGraphRunTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Missing parameters"); api.query("social","RETURN $param", new HashMap<>()); } @Test public void testContextRuntimeErrorReporting() { - exceptionRule.expect(JRedisGraphRunTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); RedisGraphContext c = api.getContext(); @@ -122,7 +122,7 @@ public void testContextExceptionFlow() { c.query("social", "RETURN toUpper(5)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphCompileTimeException.class, e.getClass()); + Assert.assertEquals(JRedisGraphException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -133,7 +133,7 @@ public void testContextExceptionFlow() { c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { - Assert.assertEquals(JRedisGraphRunTimeException.class, e.getClass()); + Assert.assertEquals(JRedisGraphException.class, e.getClass()); Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); } @@ -141,7 +141,7 @@ public void testContextExceptionFlow() { @Test public void timeoutExcpetion() { - exceptionRule.expect(JRedisGraphRunTimeException.class); + exceptionRule.expect(JRedisGraphException.class); exceptionRule.expectMessage("Query timed out"); api.query("social", "UNWIND range(0,100000) AS x WITH x AS x WHERE x = 10000 RETURN x", 1L); From 36f8dc9c8f5c43f73ce4b22046cb08f307b19816 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 8 Apr 2021 11:49:55 +0300 Subject: [PATCH 087/128] fix: upgrade redis.clients:jedis from 3.5.1 to 3.5.2 (#110) Snyk has created this PR to upgrade redis.clients:jedis from 3.5.1 to 3.5.2. See this package in Maven Repository: https://mvnrepository.com/artifact/redis.clients/jedis/ See this project in Snyk: https://app.snyk.io/org/dvirdukhan/project/cb2ca151-454d-4bfd-a328-6d77a935177b?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9868383..a373481 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.5.1 + 3.5.2 org.apache.commons From d84af9a434168d3bc113cb8474e08921f3aee0bf Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Mon, 19 Apr 2021 00:18:45 +0600 Subject: [PATCH 088/128] Remove Maven build warnings (#115) - Remove redundant dependency - Use specific version instead of `RELEASE`; Maven has deprecated the keyword --- pom.xml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index a373481..495cbc4 100644 --- a/pom.xml +++ b/pom.xml @@ -73,13 +73,7 @@ org.junit.jupiter junit-jupiter - RELEASE - test - - - org.junit.jupiter - junit-jupiter - RELEASE + 5.7.1 test From 12ed23f1972fc80e20940975a77dc6074a8ff1ed Mon Sep 17 00:00:00 2001 From: filipe oliveira Date: Wed, 21 Apr 2021 15:11:50 +0100 Subject: [PATCH 089/128] Add support for graph.RO_QUERY command (#105) * Add support for graph.RO_QUERY command * Apply suggestions from code review Co-authored-by: DvirDukhan * [fix] Fixes per PR review: removed deprecated read-only variants * [fix] Fixes per PR review: added RO to transactions. * [fix] Fixes per PR review: added RO to transactions. * [add] Added per PR review: included RO transaction test * [fix] Fixed wrong api being used on new test * Use JRedisGraphException Co-authored-by: DvirDukhan Co-authored-by: Guy Korland Co-authored-by: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> --- .../com/redislabs/redisgraph/RedisGraph.java | 38 +++++ .../redisgraph/RedisGraphTransaction.java | 36 +++++ .../impl/api/AbstractRedisGraph.java | 65 +++++++++ .../impl/api/ContextedRedisGraph.java | 44 ++++++ .../redisgraph/impl/api/RedisGraph.java | 31 ++++ .../impl/api/RedisGraphCommand.java | 1 + .../impl/api/RedisGraphTransaction.java | 79 +++++++++++ .../redisgraph/RedisGraphAPITest.java | 132 +++++++++++++++++- 8 files changed, 425 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index 3a2ae19..6cc57ce 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -14,6 +14,14 @@ public interface RedisGraph extends Closeable { */ ResultSet query(String graphId, String query); + /** + * Execute a Cypher read-only query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a result set + */ + ResultSet readOnlyQuery(String graphId, String query); + /** * Execute a Cypher query with timeout. * @param graphId a graph to perform the query on @@ -23,6 +31,16 @@ public interface RedisGraph extends Closeable { */ ResultSet query(String graphId, String query, long timeout); + /** + * Execute a Cypher read-only query with timeout. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a result set + */ + ResultSet readOnlyQuery(String graphId, String query, long timeout); + + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on @@ -34,6 +52,7 @@ public interface RedisGraph extends Closeable { @Deprecated ResultSet query(String graphId, String query, Object ...args); + /** * Executes a cypher query with parameters. * @param graphId a graph to perform the query on. @@ -43,6 +62,15 @@ public interface RedisGraph extends Closeable { */ ResultSet query(String graphId, String query, Map params); + /** + * Executes a cypher read-only query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a result set. + */ + ResultSet readOnlyQuery(String graphId, String query, Map params); + /** * Executes a cypher query with parameters and timeout. * @param graphId a graph to perform the query on. @@ -53,6 +81,16 @@ public interface RedisGraph extends Closeable { */ ResultSet query(String graphId, String query, Map params, long timeout); + /** + * Executes a cypher read-only query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a result set. + */ + ResultSet readOnlyQuery(String graphId, String query, Map params, long timeout); + /** * Invokes stored procedures without arguments * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java index 08259fe..cbcd127 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java @@ -31,6 +31,14 @@ public interface RedisGraphTransaction extends */ Response query(String graphId, String query); + /** + * Execute a Cypher read-only query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query); + /** * Execute a Cypher query with timeout. * @param graphId a graph to perform the query on @@ -40,6 +48,15 @@ public interface RedisGraphTransaction extends */ Response query(String graphId, String query, long timeout); + /** + * Execute a Cypher read-only query with timeout. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query, long timeout); + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on @@ -60,6 +77,15 @@ public interface RedisGraphTransaction extends */ Response query(String graphId, String query, Map params); + /** + * Executes a cypher read-only query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query, Map params); + /** * Executes a cypher query with parameters and timeout. * @param graphId a graph to perform the query on. @@ -70,6 +96,16 @@ public interface RedisGraphTransaction extends */ Response query(String graphId, String query, Map params, long timeout); + /** + * Executes a cypher read-only query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query, Map params, long timeout); + /** * Invokes stored procedures without arguments * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java index e1149e0..57fce53 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java @@ -27,6 +27,14 @@ public abstract class AbstractRedisGraph implements RedisGraph { */ protected abstract ResultSet sendQuery(String graphId, String preparedQuery); + /** + * Sends a read-only query to the redis graph. Implementation and context dependent + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @return Result set + */ + protected abstract ResultSet sendReadOnlyQuery(String graphId, String preparedQuery); + /** * Sends a query to the redis graph.Implementation and context dependent * @param graphId graph to be queried @@ -36,6 +44,15 @@ public abstract class AbstractRedisGraph implements RedisGraph { */ protected abstract ResultSet sendQuery(String graphId, String preparedQuery, long timeout); + /** + * Sends a read-query to the redis graph.Implementation and context dependent + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @param timeout + * @return Result set + */ + protected abstract ResultSet sendReadOnlyQuery(String graphId, String preparedQuery, long timeout); + /** * Execute a Cypher query. * @param graphId a graph to perform the query on @@ -46,6 +63,16 @@ public ResultSet query(String graphId, String query) { return sendQuery(graphId, query); } + /** + * Execute a Cypher read-only query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a result set + */ + public ResultSet readOnlyQuery(String graphId, String query) { + return sendReadOnlyQuery(graphId, query); + } + /** * Execute a Cypher query with timeout. * @param graphId a graph to perform the query on @@ -58,6 +85,18 @@ public ResultSet query(String graphId, String query, long timeout) { return sendQuery(graphId, query, timeout); } + /** + * Execute a Cypher read-only query with timeout. + * @param graphId a graph to perform the query on + * @param timeout + * @param query Cypher query + * @return a result set + */ + @Override + public ResultSet readOnlyQuery(String graphId, String query, long timeout) { + return sendReadOnlyQuery(graphId, query, timeout); + } + /** * Execute a Cypher query with arguments * @param graphId a graph to perform the query on @@ -84,6 +123,18 @@ public ResultSet query(String graphId, String query, Map params) return sendQuery(graphId, preparedQuery); } + /** + * Executes a cypher read-only query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a result set. + */ + public ResultSet readOnlyQuery(String graphId, String query, Map params) { + String preparedQuery = Utils.prepareQuery(query, params); + return sendReadOnlyQuery(graphId, preparedQuery); + } + /** * Executes a cypher query with parameters and timeout. * @param graphId a graph to perform the query on. @@ -98,6 +149,20 @@ public ResultSet query(String graphId, String query, Map params, return sendQuery(graphId, preparedQuery, timeout); } + /** + * Executes a cypher read-only query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param timeout + * @param query Cypher query. + * @param params parameters map. + * @return a result set. + */ + @Override + public ResultSet readOnlyQuery(String graphId, String query, Map params, long timeout) { + String preparedQuery = Utils.prepareQuery(query, params); + return sendReadOnlyQuery(graphId, preparedQuery, timeout); + } + public ResultSet callProcedure(String graphId, String procedure){ return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index 7918c37..92896d0 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -59,6 +59,27 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { } } + /** + * Sends the read-only query over the instance only connection + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @return Result set with the query answer + */ + @Override + protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery) { + Jedis conn = getConnection(); + try { + List rawResponse = (List) conn.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); + return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); + } + catch (JRedisGraphException ge) { + throw ge; + } + catch (JedisDataException de) { + throw new JRedisGraphException(de); + } + } + /** * Sends the query over the instance only connection * @param graphId graph to be queried @@ -82,6 +103,29 @@ protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout } } + /** + * Sends the read-only query over the instance only connection + * @param graphId graph to be queried + * @param timeout + * @param preparedQuery prepared query + * @return Result set with the query answer + */ + @Override + protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery, long timeout) { + Jedis conn = getConnection(); + try { + List rawResponse = (List) conn.sendBlockingCommand(RedisGraphCommand.RO_QUERY, + graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); + } + catch (JRedisGraphException ge) { + throw ge; + } + catch (JedisDataException de) { + throw new JRedisGraphException(de); + } + } + /** * @return Returns the instance Jedis connection. */ diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index c2f4cc2..1bb0f50 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -69,6 +69,21 @@ protected ResultSet sendQuery(String graphId, String preparedQuery){ } } + /** + * Overrides the abstract function. + * Sends the read-only query from any Jedis connection received from the Jedis pool and closes it once done + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @return Result set with the query answer + */ + @Override + protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery){ + try (ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection())) { + contextedRedisGraph.setRedisGraphCaches(caches); + return contextedRedisGraph.sendReadOnlyQuery(graphId, preparedQuery); + } + } + /** * Overrides the abstract function. * Sends the query from any Jedis connection received from the Jedis pool and closes it once done @@ -85,6 +100,22 @@ protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout } } + /** + * Overrides the abstract function. + * Sends the read-only query from any Jedis connection received from the Jedis pool and closes it once done + * @param graphId graph to be queried + * @param preparedQuery prepared query + * @param timeout + * @return Result set with the query answer + */ + @Override + protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery, long timeout){ + try (ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection())) { + contextedRedisGraph.setRedisGraphCaches(caches); + return contextedRedisGraph.sendReadOnlyQuery(graphId, preparedQuery, timeout); + } + } + /** * Closes the Jedis pool */ diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java index 3db45d0..0af0f61 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphCommand.java @@ -9,6 +9,7 @@ */ public enum RedisGraphCommand implements ProtocolCommand { QUERY("graph.QUERY"), + RO_QUERY("graph.RO_QUERY"), DELETE("graph.DELETE"); private final byte[] raw; diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index c96c749..2f2fd73 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -47,6 +47,23 @@ public ResultSet build(Object o) { }); } + /** + * Execute a Cypher read-oly query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query) { + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Execute a Cypher query with timeout. * @@ -67,6 +84,26 @@ public ResultSet build(Object o) { }); } + /** + * Execute a Cypher read-only query with timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query, long timeout) { + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Execute a Cypher query with arguments * @@ -108,6 +145,25 @@ public ResultSet build(Object o) { }); } + /** + * Executes a cypher read-only query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query, Map params) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Executes a cypher query with parameters and timeout. * @@ -131,6 +187,29 @@ public ResultSet build(Object o) { }); } + /** + * Executes a cypher read-only query with parameters and timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query, Map params, long timeout) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + /** * Invokes stored procedures without arguments, in multi/exec context * @param graphId a graph to perform the query on diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index e0c4f09..8a137bc 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -9,7 +9,6 @@ import com.redislabs.redisgraph.impl.resultset.RecordImpl; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import com.redislabs.redisgraph.test.utils.PathBuilder; -import redis.clients.jedis.exceptions.JedisDataException; import java.util.*; import java.util.stream.Collectors; @@ -479,6 +478,7 @@ public void testEscapedQuery() { Assert.assertNotNull(api.query("social", "CREATE (:escaped{s1:%s,s2:%s})", "S\"'", "S'\"")); Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1=%s and n.s2=%s RETURN n", "S\"'", "S'\"")); Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"' RETURN n")); + } @Test @@ -877,6 +877,28 @@ public void testParameters(){ } } + + @Test + public void testParametersReadOnly(){ + Object[] parameters = {1, 2.3, true, false, null, "str", 'a', "b" ,Arrays.asList(1,2,3), new Integer[]{1,2,3}}; + Object[] expected_anwsers = {1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), new Long[]{1L, 2L, 3L}}; + Map params = new HashMap<>(); + for (int i=0; i < parameters.length; i++) { + Object param = parameters[i]; + params.put("param", param); + ResultSet resultSetRo = api.readOnlyQuery("social", "RETURN $param", params); + Assert.assertEquals(1, resultSetRo.size()); + Record rRo = resultSetRo.next(); + Object oRo = rRo.getValue(0); + Object expected = expected_anwsers[i]; + if(i == parameters.length-1) { + expected = Arrays.asList((Object[])expected); + } + Assert.assertEquals(expected, oRo); + } + } + + @Test public void testNullGraphEntities() { // Create two nodes connected by a single outgoing edge. @@ -977,6 +999,30 @@ public void testMapDataType() { Assert.assertEquals(expected, actual); } + @Test + public void testCachedExecutionReadOnly() { + api.query("social", "CREATE (:N {val:1}), (:N {val:2})"); + + // First time should not be loaded from execution cache + Map params = new HashMap<>(); + params.put("val", 1L); + ResultSet resultSet = api.readOnlyQuery("social","MATCH (n:N {val:$val}) RETURN n.val", params); + Assert.assertEquals(1, resultSet.size()); + Record r = resultSet.next(); + Assert.assertEquals(params.get("val"), r.getValue(0)); + Assert.assertFalse(resultSet.getStatistics().cachedExecution()); + + // Run in loop many times to make sure the query will be loaded + // from cache at least once + for (int i = 0 ; i < 64; i++){ + resultSet = api.readOnlyQuery("social","MATCH (n:N {val:$val}) RETURN n.val", params); + } + Assert.assertEquals(1, resultSet.size()); + r = resultSet.next(); + Assert.assertEquals(params.get("val"), r.getValue(0)); + Assert.assertTrue(resultSet.getStatistics().cachedExecution()); + } + @Test public void timeoutArgument() { ResultSet rs = api.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L); @@ -984,4 +1030,88 @@ public void timeoutArgument() { Record r = rs.next(); Assert.assertEquals(Long.valueOf(100), r.getValue(0)); } + + @Test + public void testSimpleReadOnly() { + api.query("social","CREATE (:person{name:'filipe',age:30})"); + ResultSet rsRo = api.readOnlyQuery("social", "MATCH (a:person) WHERE (a.name = 'filipe') RETURN a.age"); + Assert.assertEquals(1, rsRo.size()); + Record r = rsRo.next(); + Assert.assertEquals(Long.valueOf(30), r.getValue(0)); + } + + @Test + public void testMultiExecWithReadOnlyQueries(){ + try (RedisGraphContext c = api.getContext()) { + RedisGraphTransaction transaction = api.getContext().multi(); + + transaction.set("x", "1"); + transaction.query("social", "CREATE (:Person {name:'a'})"); + transaction.query("g", "CREATE (:Person {name:'a'})"); + transaction.readOnlyQuery("social", "MATCH (n:Person) RETURN n"); + transaction.deleteGraph("g"); + transaction.callProcedure("social", "db.labels"); + List results = transaction.exec(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Graph read-only query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(3); + + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + List schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("n", schemaNames.get(0)); + + Property nameProperty = new Property<>("name", "a"); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("label", schemaNames.get(0)); + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + } + } } From ed8c81a2ab3fa8c0e3ebc7b0860efe9ae7036de7 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Thu, 6 May 2021 10:15:25 +0300 Subject: [PATCH 090/128] bump version to 2.4.0-snapshot (#106) --- README.md | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f14dace..f64e5d1 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.2.0 + 2.3.0 ``` @@ -43,7 +43,7 @@ and com.redislabs jredisgraph - 2.3.0-SNAPSHOT + 2.4.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 495cbc4..c81e7f1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.3.0-SNAPSHOT + 2.4.0-SNAPSHOT JRedisGraph Official client for Redis-Graph From 3d16fd6e9a3fc080b5932fe6868b077f95cab50a Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 13 May 2021 15:07:15 +0300 Subject: [PATCH 091/128] fix: upgrade redis.clients:jedis from 3.5.2 to 3.6.0 (#116) Snyk has created this PR to upgrade redis.clients:jedis from 3.5.2 to 3.6.0. See this package in Maven Repository: https://mvnrepository.com/artifact/redis.clients/jedis/ See this project in Snyk: https://app.snyk.io/org/gkorland/project/bf05955d-de0e-4973-a40c-38a21033b8fd?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c81e7f1..b64b11e 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.5.2 + 3.6.0 org.apache.commons From 9e65ddc4d39d837ea1963828c82f04d72e4b9f30 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 25 May 2021 15:45:01 +0300 Subject: [PATCH 092/128] bump version to 2.5.0-snapshot --- README.md | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f64e5d1..4ed663c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.3.0 + 2.4.0 ``` @@ -43,7 +43,7 @@ and com.redislabs jredisgraph - 2.4.0-SNAPSHOT + 2.5.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index b64b11e..790aea3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.4.0-SNAPSHOT + 2.5.0-SNAPSHOT JRedisGraph Official client for Redis-Graph From 353636fa3faa11948757d2ab05b5d1cf917d5792 Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Sun, 6 Jun 2021 09:47:09 +0300 Subject: [PATCH 093/128] context for circle --- .circleci/config.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d51fe5e..29838f2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,14 +44,14 @@ jobs: paths: - ~/.m2 key: v1-dependencies-{{ checksum "pom.xml" }} - + # run tests! # - run: mvn pmd:check - + - run: mvn integration-test - early_return_for_forked_pull_requests - + - run: bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN} - run: mvn -s .circleci.settings.xml -DskipTests deploy @@ -60,7 +60,9 @@ workflows: version: 2 commit: jobs: - - build + - build: + context: + - common nightly: triggers: - schedule: From 5ffd1597f9012470d0411ed0ede6f0f2b1d46960 Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Sun, 6 Jun 2021 11:17:34 +0300 Subject: [PATCH 094/128] USERNAME not USERNMAE --- .circleci.settings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci.settings.xml b/.circleci.settings.xml index 709cbf4..0ace6f5 100644 --- a/.circleci.settings.xml +++ b/.circleci.settings.xml @@ -2,7 +2,7 @@ ossrh - ${env.OSSRH_USERNMAE} + ${env.OSSRH_USERNAME} ${env.OSSRH_PASSWORD} @@ -10,4 +10,4 @@ ${env.GPG_PASSPHRASE} - \ No newline at end of file + From 4f3667f4eff2904bc4512d8ed8ba834e147e0a95 Mon Sep 17 00:00:00 2001 From: Chayim Date: Tue, 8 Jun 2021 09:41:59 +0300 Subject: [PATCH 095/128] adding context to nightly (#118) --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 29838f2..201618f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -72,5 +72,6 @@ workflows: only: - master jobs: - - build - + - build: + context: + - common From 181ef1799c11504cd28a1066872dc6141440691a Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 16 Jun 2021 14:18:20 +0300 Subject: [PATCH 096/128] Create .deepsource.toml --- .deepsource.toml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml new file mode 100644 index 0000000..424f975 --- /dev/null +++ b/.deepsource.toml @@ -0,0 +1,8 @@ +version = 1 + +[[analyzers]] +name = "java" +enabled = true + + [analyzers.meta] + runtime_version = "8" From 1f7a11f7769b4e94cebb8047d13cf1cb1e295222 Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Tue, 29 Jun 2021 16:00:09 +0300 Subject: [PATCH 097/128] moving codecov bash executor to the repository relying on the contents of the github repo directly --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 201618f..1ba4047 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,7 +52,7 @@ jobs: - early_return_for_forked_pull_requests - - run: bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN} + - run: bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-action/master/codecov) -t ${CODECOV_TOKEN} - run: mvn -s .circleci.settings.xml -DskipTests deploy From aa04c7ffcee9fb53e04217f4d7371e74e90128e0 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Tue, 6 Jul 2021 08:11:07 +0300 Subject: [PATCH 098/128] fix: upgrade redis.clients:jedis from 3.6.0 to 3.6.1 (#120) Snyk has created this PR to upgrade redis.clients:jedis from 3.6.0 to 3.6.1. See this package in Maven Repository: https://mvnrepository.com/artifact/redis.clients/jedis/ See this project in Snyk: https://app.snyk.io/org/redislabs/project/17e7afa9-5a10-4ccf-8133-b44090b60109?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 790aea3..5524787 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.6.0 + 3.6.1 org.apache.commons From 39e9fe283931821a8339e83e68d5983dbea0b1bd Mon Sep 17 00:00:00 2001 From: Chayim Date: Tue, 6 Jul 2021 13:09:58 +0300 Subject: [PATCH 099/128] fixing action syntax (#121) --- .github/workflows/version-and-release.yml | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/version-and-release.yml diff --git a/.github/workflows/version-and-release.yml b/.github/workflows/version-and-release.yml new file mode 100644 index 0000000..7b2c515 --- /dev/null +++ b/.github/workflows/version-and-release.yml @@ -0,0 +1,47 @@ +name: Release + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: get version from tag + id: get_version + run: | + realversion="${GITHUB_REF/refs\/tags\//}" + realversion="${realversion//v/}" + echo "::set-output name=VERSION::$realversion" + + - name: Set up publishing to maven central + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + - name: mvn versions + run: mvn versions:set -DnewVersion=${{ steps.get_version.outputs.VERSION }} + + - name: Install gpg key + run: | + cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import + gpg --list-secret-keys --keyid-format LONG + + - name: Publish + run: | + mvn --no-transfer-progress \ + --batch-mode \ + -Dgpg.passphrase="${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}" \ + -s -DskipTests deploy -P release + env: + MAVEN_USERNAME: ${{secrets.OSSH_USERNAME}} + MAVEN_PASSWORD: ${{secrets.OSSH_TOKEN}} From ffd56a58b482d503e9a21442317c4c425cd6e096 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 20 Jul 2021 19:05:56 +0600 Subject: [PATCH 100/128] Changing codecov script location (#125) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1ba4047..bc119f3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,7 +52,7 @@ jobs: - early_return_for_forked_pull_requests - - run: bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-action/master/codecov) -t ${CODECOV_TOKEN} + - run: bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -t ${CODECOV_TOKEN} - run: mvn -s .circleci.settings.xml -DskipTests deploy From 5b14170cd89063f6adc3fd45021e104bf57ef625 Mon Sep 17 00:00:00 2001 From: Chayim Date: Tue, 20 Jul 2021 16:06:22 +0300 Subject: [PATCH 101/128] upstream change in codecov location (#124) From 976976b584a061574c36e8d956f92242c168177f Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 20 Jul 2021 16:13:05 +0300 Subject: [PATCH 102/128] Add Pipeline support (#123) * Add Pipeline support * Broke the Transaction and Pipeline tests to seperate files. Co-authored-by: DvirDukhan Co-authored-by: DvirDukhan --- .../redisgraph/RedisGraphContext.java | 6 + .../redisgraph/RedisGraphPipeline.java | 158 +++++++++++ .../impl/api/ContextedRedisGraph.java | 14 + .../impl/api/RedisGraphPipeline.java | 265 ++++++++++++++++++ .../redislabs/redisgraph/PipelineTest.java | 194 +++++++++++++ .../redisgraph/RedisGraphAPITest.java | 200 ------------- .../redislabs/redisgraph/TransactionTest.java | 231 +++++++++++++++ 7 files changed, 868 insertions(+), 200 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java create mode 100644 src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java create mode 100644 src/test/java/com/redislabs/redisgraph/PipelineTest.java create mode 100644 src/test/java/com/redislabs/redisgraph/TransactionTest.java diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphContext.java b/src/main/java/com/redislabs/redisgraph/RedisGraphContext.java index db2a5e8..44d6319 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphContext.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphContext.java @@ -16,6 +16,12 @@ public interface RedisGraphContext extends RedisGraph { * @return Redis transactional object, over the connection context, with graph API capabilities */ RedisGraphTransaction multi(); + + /** + * Returns a Redis pipeline object, over the connection context, with graph API capabilities + * @return Redis pipeline object, over the connection context, with graph API capabilities + */ + RedisGraphPipeline pipelined(); /** * Perform watch over given Redis keys diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java b/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java new file mode 100644 index 0000000..c2806c8 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java @@ -0,0 +1,158 @@ +package com.redislabs.redisgraph; + +import redis.clients.jedis.Response; +import redis.clients.jedis.commands.BasicRedisPipeline; +import redis.clients.jedis.commands.BinaryRedisPipeline; +import redis.clients.jedis.commands.BinaryScriptingCommandsPipeline; +import redis.clients.jedis.commands.ClusterPipeline; +import redis.clients.jedis.commands.MultiKeyBinaryRedisPipeline; +import redis.clients.jedis.commands.MultiKeyCommandsPipeline; +import redis.clients.jedis.commands.RedisPipeline; +import redis.clients.jedis.commands.ScriptingCommandsPipeline; + +import java.io.Closeable; +import java.util.List; +import java.util.Map; + +/** + * An interface which aligned to Jedis Pipeline interface + */ +public interface RedisGraphPipeline extends + MultiKeyBinaryRedisPipeline, + MultiKeyCommandsPipeline, ClusterPipeline, + BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline, + BasicRedisPipeline, BinaryRedisPipeline, RedisPipeline, Closeable { + + /** + * Execute a Cypher query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query); + + /** + * Execute a Cypher read-only query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query); + + /** + * Execute a Cypher query with timeout. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query, long timeout); + + /** + * Execute a Cypher read-only query with timeout. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query, long timeout); + + /** + * Execute a Cypher query with arguments + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param args + * @return a response which builds the result set with the query answer. + * @deprecated use {@link #query(String, String, Map)} instead. + */ + @Deprecated + Response query(String graphId, String query, Object ...args); + + /** + * Executes a cypher query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query, Map params); + + /** + * Executes a cypher read-only query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query, Map params); + + /** + * Executes a cypher query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response query(String graphId, String query, Map params, long timeout); + + /** + * Executes a cypher read-only query with parameters and timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + Response readOnlyQuery(String graphId, String query, Map params, long timeout); + + /** + * Invokes stored procedures without arguments + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @return a response which builds result set with the procedure data + */ + Response callProcedure(String graphId, String procedure); + + /** + * Invokes stored procedure with arguments + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @param args procedure arguments + * @return a response which builds result set with the procedure data + */ + Response callProcedure(String graphId, String procedure, List args); + + /** + * Invoke a stored procedure + * @param graphId a graph to perform the query on + * @param procedure - procedure to execute + * @param args - procedure arguments + * @param kwargs - procedure output arguments + * @return a response which builds result set with the procedure data + */ + Response callProcedure(String graphId, String procedure, List args , Map> kwargs); + + /** + * Deletes the entire graph + * @param graphId graph to delete + * @return a response which builds the delete running time statistics + */ + Response deleteGraph(String graphId); + + + /** + * Synchronize pipeline by reading all responses. This operation close the pipeline. Whenever + * possible try to avoid using this version and use Pipeline.sync() as it won't go through all the + * responses and generate the right response type (usually it is a waste of time). + * @return A list of all the responses in the order you executed them. + */ + List syncAndReturnAll(); + + /** + * Synchronize pipeline by reading all responses. This operation close the pipeline. In order to + * get return values from pipelined commands, capture the different Response<?> of the + * commands you execute. + */ + public void sync(); +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index 92896d0..2de4e4d 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -8,6 +8,7 @@ import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; +import redis.clients.jedis.Pipeline; import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.exceptions.JedisDataException; import java.util.List; @@ -148,6 +149,19 @@ public RedisGraphTransaction multi() { transaction.setRedisGraphCaches(caches); return transaction; } + + /** + * Creates a new RedisGraphPipeline pipeline object + * @return new RedisGraphPipeline + */ + @Override + public RedisGraphPipeline pipelined() { + Jedis jedis = getConnection(); + Client client = jedis.getClient(); + RedisGraphPipeline pipeline = new RedisGraphPipeline(client, this); + pipeline.setRedisGraphCaches(caches); + return pipeline; + } /** * Perfrom watch over given Redis keys diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java new file mode 100644 index 0000000..ec7e5ae --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java @@ -0,0 +1,265 @@ +package com.redislabs.redisgraph.impl.api; + +import com.redislabs.redisgraph.RedisGraph; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.impl.Utils; +import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; +import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.Client; +import redis.clients.jedis.Pipeline; +import redis.clients.jedis.Response; + +import java.util.List; +import java.util.Map; + +/** + * This class is extending Jedis Pipeline + */ +public class RedisGraphPipeline extends Pipeline implements com.redislabs.redisgraph.RedisGraphPipeline, RedisGraphCacheHolder { + + private final RedisGraph redisGraph; + private RedisGraphCaches caches; + + + public RedisGraphPipeline(Client client, RedisGraph redisGraph){ + super.setClient(client); + this.redisGraph = redisGraph; + } + + /** + * Execute a Cypher query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query) { + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Execute a Cypher read-oly query. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query) { + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Execute a Cypher query with timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query, long timeout) { + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Execute a Cypher read-only query with timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query, long timeout) { + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Execute a Cypher query with arguments + * + * @param graphId a graph to perform the query on + * @param query Cypher query + * @param args + * @return response with a result set + * @deprecated use {@link #query(String, String, Map)} instead. + */ + @Deprecated + @Override + public Response query(String graphId, String query, Object ...args){ + String preparedQuery = Utils.prepareQuery(query, args); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Executes a cypher query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query, Map params) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Executes a cypher read-only query with parameters. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query, Map params) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT"); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Executes a cypher query with parameters and timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response query(String graphId, String query, Map params, long timeout) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Executes a cypher read-only query with parameters and timeout. + * + * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. + * timeout. + * @param graphId a graph to perform the query on. + * @param query Cypher query. + * @param params parameters map. + * @param timeout + * @return a response which builds the result set with the query answer. + */ + @Override + public Response readOnlyQuery(String graphId, String query, Map params, long timeout) { + String preparedQuery = Utils.prepareQuery(query, params); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + return getResponse(new Builder() { + @Override + public ResultSet build(Object o) { + return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + } + }); + } + + /** + * Invokes stored procedures without arguments + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @return response with result set with the procedure data + */ + public Response callProcedure(String graphId, String procedure){ + return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); + } + + /** + * Invokes stored procedure with arguments + * @param graphId a graph to perform the query on + * @param procedure procedure name to invoke + * @param args procedure arguments + * @return response with result set with the procedure data + */ + public Response callProcedure(String graphId, String procedure, List args ){ + return callProcedure(graphId, procedure, args, Utils.DUMMY_MAP); + } + + + /** + * Invoke a stored procedure + * @param graphId a graph to perform the query on + * @param procedure - procedure to execute + * @param args - procedure arguments + * @param kwargs - procedure output arguments + * @return response with result set with the procedure data + */ + public Response callProcedure(String graphId, String procedure, List args, + Map> kwargs) { + String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); + return query(graphId, preparedProcedure); + } + + + /** + * Deletes the entire graph + * @param graphId graph to delete + * @return response with the deletion running time statistics + */ + public Response deleteGraph(String graphId){ + + client.sendCommand(RedisGraphCommand.DELETE, graphId); + Response response = getResponse(BuilderFactory.STRING); + caches.removeGraphCache(graphId); + return response; + } + + @Override + public void setRedisGraphCaches(RedisGraphCaches caches) { + this.caches = caches; + } +} diff --git a/src/test/java/com/redislabs/redisgraph/PipelineTest.java b/src/test/java/com/redislabs/redisgraph/PipelineTest.java new file mode 100644 index 0000000..8b3e9fb --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/PipelineTest.java @@ -0,0 +1,194 @@ +package com.redislabs.redisgraph; + +import com.redislabs.redisgraph.Statistics.Label; +import com.redislabs.redisgraph.graph_entities.Edge; +import com.redislabs.redisgraph.graph_entities.Node; +import com.redislabs.redisgraph.graph_entities.Property; +import com.redislabs.redisgraph.impl.api.RedisGraph; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.*; + +public class PipelineTest { + + private RedisGraphContextGenerator api; + + public PipelineTest() { + } + + @Before + public void createApi(){ + api = new RedisGraph(); + } + + @After + public void deleteGraph() { + api.deleteGraph("social"); + api.close(); + } + + @Test + public void testPipelineExec(){ + try (RedisGraphContext c = api.getContext()) { + RedisGraphPipeline pipeline = api.getContext().pipelined(); + + pipeline.set("x", "1"); + pipeline.query("social", "CREATE (:Person {name:'a'})"); + pipeline.query("g", "CREATE (:Person {name:'a'})"); + pipeline.incr("x"); + pipeline.get("x"); + pipeline.query("social", "MATCH (n:Person) RETURN n"); + pipeline.deleteGraph("g"); + pipeline.callProcedure("social", "db.labels"); + List results = pipeline.syncAndReturnAll(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Redis incr command + Assert.assertEquals(Long.class, results.get(3).getClass()); + Assert.assertEquals(2L, results.get(3)); + + // Redis get command + Assert.assertEquals(String.class, results.get(4).getClass()); + Assert.assertEquals("2", results.get(4)); + + // Graph query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); + + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + + List schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("n", schemaNames.get(0)); + + Property nameProperty = new Property<>("name", "a"); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + + Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); + resultSet = (ResultSet) results.get(7); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + + schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("label", schemaNames.get(0)); + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + } + } + + @Test + public void testPipelineWithReadOnlyQueries(){ + try (RedisGraphContext c = api.getContext()) { + RedisGraphPipeline pipeline = api.getContext().pipelined(); + + pipeline.set("x", "1"); + pipeline.query("social", "CREATE (:Person {name:'a'})"); + pipeline.query("g", "CREATE (:Person {name:'a'})"); + pipeline.readOnlyQuery("social", "MATCH (n:Person) RETURN n"); + pipeline.deleteGraph("g"); + pipeline.callProcedure("social", "db.labels"); + List results = pipeline.syncAndReturnAll(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Graph read-only query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(3); + + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + List schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("n", schemaNames.get(0)); + + Property nameProperty = new Property<>("name", "a"); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("label", schemaNames.get(0)); + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + } + } +} diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 8a137bc..700c230 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -481,92 +481,6 @@ public void testEscapedQuery() { } - @Test - public void testMultiExec(){ - try (RedisGraphContext c = api.getContext()) { - RedisGraphTransaction transaction = api.getContext().multi(); - - transaction.set("x", "1"); - transaction.query("social", "CREATE (:Person {name:'a'})"); - transaction.query("g", "CREATE (:Person {name:'a'})"); - transaction.incr("x"); - transaction.get("x"); - transaction.query("social", "MATCH (n:Person) RETURN n"); - transaction.deleteGraph("g"); - transaction.callProcedure("social", "db.labels"); - List results = transaction.exec(); - - // Redis set command - Assert.assertEquals(String.class, results.get(0).getClass()); - Assert.assertEquals("OK", results.get(0)); - - // Redis graph command - Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); - ResultSet resultSet = (ResultSet) results.get(1); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - - - Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); - resultSet = (ResultSet) results.get(2); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - - // Redis incr command - Assert.assertEquals(Long.class, results.get(3).getClass()); - Assert.assertEquals(2L, results.get(3)); - - // Redis get command - Assert.assertEquals(String.class, results.get(4).getClass()); - Assert.assertEquals("2", results.get(4)); - - // Graph query result - Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); - resultSet = (ResultSet) results.get(5); - - Assert.assertNotNull(resultSet.getHeader()); - Header header = resultSet.getHeader(); - - - List schemaNames = header.getSchemaNames(); - Assert.assertNotNull(schemaNames); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals("n", schemaNames.get(0)); - - Property nameProperty = new Property<>("name", "a"); - - Node expectedNode = new Node(); - expectedNode.setId(0); - expectedNode.addLabel("Person"); - expectedNode.addProperty(nameProperty); - // see that the result were pulled from the right graph - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - Record record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(Arrays.asList("n"), record.keys()); - Assert.assertEquals(expectedNode, record.getValue("n")); - - Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); - resultSet = (ResultSet) results.get(7); - - Assert.assertNotNull(resultSet.getHeader()); - header = resultSet.getHeader(); - - - schemaNames = header.getSchemaNames(); - Assert.assertNotNull(schemaNames); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals("label", schemaNames.get(0)); - - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(Arrays.asList("label"), record.keys()); - Assert.assertEquals("Person", record.getValue("label")); - } - } @Test public void testContextedAPI() { @@ -673,45 +587,6 @@ public void testContextedAPI() { } } - @Test - public void testWriteTransactionWatch(){ - - RedisGraphContext c1 = api.getContext(); - RedisGraphContext c2 = api.getContext(); - - c1.watch("social"); - RedisGraphTransaction t1 = c1.multi(); - - - t1.query("social", "CREATE (:Person {name:'a'})"); - c2.query("social", "CREATE (:Person {name:'b'})"); - List returnValue = t1.exec(); - Assert.assertNull(returnValue); - c1.close(); - c2.close(); - } - - @Test - public void testReadTransactionWatch(){ - - RedisGraphContext c1 = api.getContext(); - RedisGraphContext c2 = api.getContext(); - Assert.assertNotEquals(c1.getConnectionContext(), c2.getConnectionContext()); - c1.query("social", "CREATE (:Person {name:'a'})"); - c1.watch("social"); - RedisGraphTransaction t1 = c1.multi(); - - Map params = new HashMap<>(); - params.put("name", 'b'); - t1.query("social", "CREATE (:Person {name:$name})", params); - c2.query("social", "MATCH (n) return n"); - List returnValue = t1.exec(); - - Assert.assertNotNull(returnValue); - c1.close(); - c2.close(); - } - @Test public void testArraySupport() { @@ -1039,79 +914,4 @@ public void testSimpleReadOnly() { Record r = rsRo.next(); Assert.assertEquals(Long.valueOf(30), r.getValue(0)); } - - @Test - public void testMultiExecWithReadOnlyQueries(){ - try (RedisGraphContext c = api.getContext()) { - RedisGraphTransaction transaction = api.getContext().multi(); - - transaction.set("x", "1"); - transaction.query("social", "CREATE (:Person {name:'a'})"); - transaction.query("g", "CREATE (:Person {name:'a'})"); - transaction.readOnlyQuery("social", "MATCH (n:Person) RETURN n"); - transaction.deleteGraph("g"); - transaction.callProcedure("social", "db.labels"); - List results = transaction.exec(); - - // Redis set command - Assert.assertEquals(String.class, results.get(0).getClass()); - Assert.assertEquals("OK", results.get(0)); - - // Redis graph command - Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); - ResultSet resultSet = (ResultSet) results.get(1); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - - - Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); - resultSet = (ResultSet) results.get(2); - Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); - Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - - // Graph read-only query result - Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); - resultSet = (ResultSet) results.get(3); - - Assert.assertNotNull(resultSet.getHeader()); - Header header = resultSet.getHeader(); - - List schemaNames = header.getSchemaNames(); - Assert.assertNotNull(schemaNames); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals("n", schemaNames.get(0)); - - Property nameProperty = new Property<>("name", "a"); - - Node expectedNode = new Node(); - expectedNode.setId(0); - expectedNode.addLabel("Person"); - expectedNode.addProperty(nameProperty); - // see that the result were pulled from the right graph - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - Record record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(Arrays.asList("n"), record.keys()); - Assert.assertEquals(expectedNode, record.getValue("n")); - - Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); - resultSet = (ResultSet) results.get(5); - - Assert.assertNotNull(resultSet.getHeader()); - header = resultSet.getHeader(); - - schemaNames = header.getSchemaNames(); - Assert.assertNotNull(schemaNames); - Assert.assertEquals(1, schemaNames.size()); - Assert.assertEquals("label", schemaNames.get(0)); - - Assert.assertEquals(1, resultSet.size()); - Assert.assertTrue(resultSet.hasNext()); - record = resultSet.next(); - Assert.assertFalse(resultSet.hasNext()); - Assert.assertEquals(Arrays.asList("label"), record.keys()); - Assert.assertEquals("Person", record.getValue("label")); - } - } } diff --git a/src/test/java/com/redislabs/redisgraph/TransactionTest.java b/src/test/java/com/redislabs/redisgraph/TransactionTest.java new file mode 100644 index 0000000..ec68b93 --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/TransactionTest.java @@ -0,0 +1,231 @@ +package com.redislabs.redisgraph; + +import com.redislabs.redisgraph.graph_entities.Node; +import com.redislabs.redisgraph.graph_entities.Property; +import com.redislabs.redisgraph.impl.api.RedisGraph; +import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.*; + +public class TransactionTest { + + private RedisGraphContextGenerator api; + + public TransactionTest() { + } + + @Before + public void createApi(){ + api = new RedisGraph(); + } + + @After + public void deleteGraph() { + api.deleteGraph("social"); + api.close(); + } + + @Test + public void testMultiExec(){ + try (RedisGraphContext c = api.getContext()) { + RedisGraphTransaction transaction = api.getContext().multi(); + + transaction.set("x", "1"); + transaction.query("social", "CREATE (:Person {name:'a'})"); + transaction.query("g", "CREATE (:Person {name:'a'})"); + transaction.incr("x"); + transaction.get("x"); + transaction.query("social", "MATCH (n:Person) RETURN n"); + transaction.deleteGraph("g"); + transaction.callProcedure("social", "db.labels"); + List results = transaction.exec(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Redis incr command + Assert.assertEquals(Long.class, results.get(3).getClass()); + Assert.assertEquals(2L, results.get(3)); + + // Redis get command + Assert.assertEquals(String.class, results.get(4).getClass()); + Assert.assertEquals("2", results.get(4)); + + // Graph query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); + + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + + List schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("n", schemaNames.get(0)); + + Property nameProperty = new Property<>("name", "a"); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + + Assert.assertEquals(ResultSetImpl.class, results.get(7).getClass()); + resultSet = (ResultSet) results.get(7); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + + schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("label", schemaNames.get(0)); + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + } + } + + @Test + public void testWriteTransactionWatch(){ + + RedisGraphContext c1 = api.getContext(); + RedisGraphContext c2 = api.getContext(); + + c1.watch("social"); + RedisGraphTransaction t1 = c1.multi(); + + + t1.query("social", "CREATE (:Person {name:'a'})"); + c2.query("social", "CREATE (:Person {name:'b'})"); + List returnValue = t1.exec(); + Assert.assertNull(returnValue); + c1.close(); + c2.close(); + } + + @Test + public void testReadTransactionWatch(){ + + RedisGraphContext c1 = api.getContext(); + RedisGraphContext c2 = api.getContext(); + Assert.assertNotEquals(c1.getConnectionContext(), c2.getConnectionContext()); + c1.query("social", "CREATE (:Person {name:'a'})"); + c1.watch("social"); + RedisGraphTransaction t1 = c1.multi(); + + Map params = new HashMap<>(); + params.put("name", 'b'); + t1.query("social", "CREATE (:Person {name:$name})", params); + c2.query("social", "MATCH (n) return n"); + List returnValue = t1.exec(); + + Assert.assertNotNull(returnValue); + c1.close(); + c2.close(); + } + + @Test + public void testMultiExecWithReadOnlyQueries(){ + try (RedisGraphContext c = api.getContext()) { + RedisGraphTransaction transaction = api.getContext().multi(); + + transaction.set("x", "1"); + transaction.query("social", "CREATE (:Person {name:'a'})"); + transaction.query("g", "CREATE (:Person {name:'a'})"); + transaction.readOnlyQuery("social", "MATCH (n:Person) RETURN n"); + transaction.deleteGraph("g"); + transaction.callProcedure("social", "db.labels"); + List results = transaction.exec(); + + // Redis set command + Assert.assertEquals(String.class, results.get(0).getClass()); + Assert.assertEquals("OK", results.get(0)); + + // Redis graph command + Assert.assertEquals(ResultSetImpl.class, results.get(1).getClass()); + ResultSet resultSet = (ResultSet) results.get(1); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + + Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); + resultSet = (ResultSet) results.get(2); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); + + // Graph read-only query result + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(3); + + Assert.assertNotNull(resultSet.getHeader()); + Header header = resultSet.getHeader(); + + List schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("n", schemaNames.get(0)); + + Property nameProperty = new Property<>("name", "a"); + + Node expectedNode = new Node(); + expectedNode.setId(0); + expectedNode.addLabel("Person"); + expectedNode.addProperty(nameProperty); + // see that the result were pulled from the right graph + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + Record record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("n"), record.keys()); + Assert.assertEquals(expectedNode, record.getValue("n")); + + Assert.assertEquals(ResultSetImpl.class, results.get(5).getClass()); + resultSet = (ResultSet) results.get(5); + + Assert.assertNotNull(resultSet.getHeader()); + header = resultSet.getHeader(); + + schemaNames = header.getSchemaNames(); + Assert.assertNotNull(schemaNames); + Assert.assertEquals(1, schemaNames.size()); + Assert.assertEquals("label", schemaNames.get(0)); + + Assert.assertEquals(1, resultSet.size()); + Assert.assertTrue(resultSet.hasNext()); + record = resultSet.next(); + Assert.assertFalse(resultSet.hasNext()); + Assert.assertEquals(Arrays.asList("label"), record.keys()); + Assert.assertEquals("Person", record.getValue("label")); + } + } +} From fb4ab4000cb900b9780fae75323b72e4931a8825 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 20 Jul 2021 19:35:50 +0300 Subject: [PATCH 103/128] Update to jedis 3.6.3 (#126) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5524787..22dd001 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.6.1 + 3.6.3 org.apache.commons From a066ee641448824c251767d3859878792373ef9a Mon Sep 17 00:00:00 2001 From: Chayim Date: Tue, 20 Jul 2021 19:47:51 +0300 Subject: [PATCH 104/128] changed action to single quote the string (#122) Co-authored-by: Guy Korland --- .github/workflows/version-and-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/version-and-release.yml b/.github/workflows/version-and-release.yml index 7b2c515..0808b6f 100644 --- a/.github/workflows/version-and-release.yml +++ b/.github/workflows/version-and-release.yml @@ -40,8 +40,8 @@ jobs: run: | mvn --no-transfer-progress \ --batch-mode \ - -Dgpg.passphrase="${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}" \ - -s -DskipTests deploy -P release + -Dgpg.passphrase='${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}' \ + -DskipTests deploy -P release env: MAVEN_USERNAME: ${{secrets.OSSH_USERNAME}} MAVEN_PASSWORD: ${{secrets.OSSH_TOKEN}} From 5792322753a2631de981c839474d644ceb20986e Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 20 Jul 2021 19:58:28 +0300 Subject: [PATCH 105/128] Pipeline (#127) * replace "compact" "timeout" with constant --- .../impl/api/RedisGraphPipeline.java | 18 +++++++++--------- .../impl/api/RedisGraphTransaction.java | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java index ec7e5ae..71deb1a 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java @@ -36,7 +36,7 @@ public RedisGraphPipeline(Client client, RedisGraph redisGraph){ */ @Override public Response query(String graphId, String query) { - client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -53,7 +53,7 @@ public ResultSet build(Object o) { */ @Override public Response readOnlyQuery(String graphId, String query) { - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT"); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -73,7 +73,7 @@ public ResultSet build(Object o) { */ @Override public Response query(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -93,7 +93,7 @@ public ResultSet build(Object o) { */ @Override public Response readOnlyQuery(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -115,7 +115,7 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Object ...args){ String preparedQuery = Utils.prepareQuery(query, args); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -134,7 +134,7 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Map params) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -153,7 +153,7 @@ public ResultSet build(Object o) { @Override public Response readOnlyQuery(String graphId, String query, Map params) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -176,7 +176,7 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -199,7 +199,7 @@ public ResultSet build(Object o) { @Override public Response readOnlyQuery(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 2f2fd73..4c8c16f 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -38,7 +38,7 @@ public RedisGraphTransaction(Client client, RedisGraph redisGraph){ */ @Override public Response query(String graphId, String query) { - client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -55,7 +55,7 @@ public ResultSet build(Object o) { */ @Override public Response readOnlyQuery(String graphId, String query) { - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT"); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -75,7 +75,7 @@ public ResultSet build(Object o) { */ @Override public Response query(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -95,7 +95,7 @@ public ResultSet build(Object o) { */ @Override public Response readOnlyQuery(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -117,7 +117,7 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Object ...args){ String preparedQuery = Utils.prepareQuery(query, args); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -136,7 +136,7 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Map params) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -155,7 +155,7 @@ public ResultSet build(Object o) { @Override public Response readOnlyQuery(String graphId, String query, Map params) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT"); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -178,7 +178,7 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { @@ -201,7 +201,7 @@ public ResultSet build(Object o) { @Override public Response readOnlyQuery(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { @Override public ResultSet build(Object o) { From 0237cd33492b18c925fc0f3782416e44c0d6ee05 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 21 Jul 2021 11:36:48 +0300 Subject: [PATCH 106/128] Add waitReplicas to Pipeline interface (#128) * Add waitReplicas to Pipeline interface * Add simple testWaitReplicas test --- pom.xml | 2 +- .../redisgraph/RedisGraphPipeline.java | 24 ++++++++++--------- .../impl/api/RedisGraphPipeline.java | 22 ----------------- .../redislabs/redisgraph/PipelineTest.java | 22 +++++++++++++---- .../redislabs/redisgraph/TransactionTest.java | 4 ++-- 5 files changed, 33 insertions(+), 41 deletions(-) diff --git a/pom.xml b/pom.xml index 22dd001..61e879b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.5.0-SNAPSHOT + 2.5.1-SNAPSHOT JRedisGraph Official client for Redis-Graph diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java b/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java index c2806c8..8416f66 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphPipeline.java @@ -57,17 +57,6 @@ public interface RedisGraphPipeline extends */ Response readOnlyQuery(String graphId, String query, long timeout); - /** - * Execute a Cypher query with arguments - * @param graphId a graph to perform the query on - * @param query Cypher query - * @param args - * @return a response which builds the result set with the query answer. - * @deprecated use {@link #query(String, String, Map)} instead. - */ - @Deprecated - Response query(String graphId, String query, Object ...args); - /** * Executes a cypher query with parameters. * @param graphId a graph to perform the query on. @@ -155,4 +144,17 @@ public interface RedisGraphPipeline extends * commands you execute. */ public void sync(); + + + /** + * Blocks until all the previous write commands are successfully transferred and acknowledged by + * at least the specified number of replicas. If the timeout, specified in milliseconds, is + * reached, the command returns even if the specified number of replicas were not yet reached. + * @param replicas successfully transferred and acknowledged by at least the specified number of + * replicas + * @param timeout the time to block in milliseconds, a timeout of 0 means to block forever + * @return the number of replicas reached by all the writes performed in the context of the + * current connection + */ + public Response waitReplicas(int replicas, long timeout); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java index 71deb1a..5ddbf09 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java @@ -102,28 +102,6 @@ public ResultSet build(Object o) { }); } - /** - * Execute a Cypher query with arguments - * - * @param graphId a graph to perform the query on - * @param query Cypher query - * @param args - * @return response with a result set - * @deprecated use {@link #query(String, String, Map)} instead. - */ - @Deprecated - @Override - public Response query(String graphId, String query, Object ...args){ - String preparedQuery = Utils.prepareQuery(query, args); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); - return getResponse(new Builder() { - @Override - public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); - } - }); - } - /** * Executes a cypher query with parameters. * @param graphId a graph to perform the query on. diff --git a/src/test/java/com/redislabs/redisgraph/PipelineTest.java b/src/test/java/com/redislabs/redisgraph/PipelineTest.java index 8b3e9fb..5dd58e2 100644 --- a/src/test/java/com/redislabs/redisgraph/PipelineTest.java +++ b/src/test/java/com/redislabs/redisgraph/PipelineTest.java @@ -31,10 +31,9 @@ public void deleteGraph() { } @Test - public void testPipelineExec(){ + public void testSync(){ try (RedisGraphContext c = api.getContext()) { - RedisGraphPipeline pipeline = api.getContext().pipelined(); - + RedisGraphPipeline pipeline = c.pipelined(); pipeline.set("x", "1"); pipeline.query("social", "CREATE (:Person {name:'a'})"); pipeline.query("g", "CREATE (:Person {name:'a'})"); @@ -118,9 +117,9 @@ record = resultSet.next(); } @Test - public void testPipelineWithReadOnlyQueries(){ + public void testReadOnlyQueries(){ try (RedisGraphContext c = api.getContext()) { - RedisGraphPipeline pipeline = api.getContext().pipelined(); + RedisGraphPipeline pipeline = c.pipelined(); pipeline.set("x", "1"); pipeline.query("social", "CREATE (:Person {name:'a'})"); @@ -191,4 +190,17 @@ record = resultSet.next(); Assert.assertEquals("Person", record.getValue("label")); } } + + @Test + public void testWaitReplicas(){ + try (RedisGraphContext c = api.getContext()) { + RedisGraphPipeline pipeline = c.pipelined(); + pipeline.set("x", "1"); + pipeline.query("social", "CREATE (:Person {name:'a'})"); + pipeline.query("g", "CREATE (:Person {name:'a'})"); + pipeline.waitReplicas(0, 100L); + List results = pipeline.syncAndReturnAll(); + Assert.assertEquals(0L, results.get(3)); + } + } } diff --git a/src/test/java/com/redislabs/redisgraph/TransactionTest.java b/src/test/java/com/redislabs/redisgraph/TransactionTest.java index ec68b93..28f31f0 100644 --- a/src/test/java/com/redislabs/redisgraph/TransactionTest.java +++ b/src/test/java/com/redislabs/redisgraph/TransactionTest.java @@ -31,7 +31,7 @@ public void deleteGraph() { @Test public void testMultiExec(){ try (RedisGraphContext c = api.getContext()) { - RedisGraphTransaction transaction = api.getContext().multi(); + RedisGraphTransaction transaction = c.multi(); transaction.set("x", "1"); transaction.query("social", "CREATE (:Person {name:'a'})"); @@ -157,7 +157,7 @@ public void testReadTransactionWatch(){ @Test public void testMultiExecWithReadOnlyQueries(){ try (RedisGraphContext c = api.getContext()) { - RedisGraphTransaction transaction = api.getContext().multi(); + RedisGraphTransaction transaction = c.multi(); transaction.set("x", "1"); transaction.query("social", "CREATE (:Person {name:'a'})"); From dec9037720c1d5eaac4ef7e4c32aaa7e97d37528 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 21 Jul 2021 14:09:12 +0300 Subject: [PATCH 107/128] Update version-and-release.yml --- .github/workflows/version-and-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/version-and-release.yml b/.github/workflows/version-and-release.yml index 0808b6f..a42782b 100644 --- a/.github/workflows/version-and-release.yml +++ b/.github/workflows/version-and-release.yml @@ -33,14 +33,14 @@ jobs: - name: Install gpg key run: | - cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import + cat <(echo -e "${{ secrets.OSSH_GPG_SECRET_KEY }}") | gpg --batch --import gpg --list-secret-keys --keyid-format LONG - name: Publish run: | mvn --no-transfer-progress \ --batch-mode \ - -Dgpg.passphrase='${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}' \ + -Dgpg.passphrase='${{ secrets.OSSH_GPG_SECRET_KEY_PASSWORD }}' \ -DskipTests deploy -P release env: MAVEN_USERNAME: ${{secrets.OSSH_USERNAME}} From 3db8c1332e4b1df8ac91abfbde2b90667fc17de1 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 21 Jul 2021 19:32:07 +0300 Subject: [PATCH 108/128] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4ed663c..c83d521 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ RedisGraph Java client com.redislabs jredisgraph - 2.4.0 + 2.5.1 ``` @@ -43,7 +43,7 @@ and com.redislabs jredisgraph - 2.5.0-SNAPSHOT + 2.6.0-SNAPSHOT ``` From b32561d6a418accb741b76ca4561d81e3f480d15 Mon Sep 17 00:00:00 2001 From: Chayim Date: Sat, 24 Jul 2021 09:45:57 +0300 Subject: [PATCH 109/128] release drafter and release actions (#129) Co-authored-by: Guy Korland --- .circleci.settings.xml | 4 ++-- .github/workflows/release-drafter.yml | 1 - .github/workflows/version-and-release.yml | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.circleci.settings.xml b/.circleci.settings.xml index 0ace6f5..b3e253a 100644 --- a/.circleci.settings.xml +++ b/.circleci.settings.xml @@ -2,8 +2,8 @@ ossrh - ${env.OSSRH_USERNAME} - ${env.OSSRH_PASSWORD} + ${env.OSSH_USERNAME} + ${env.OSSH_PASSWORD} gpg.passphrase diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index caac3ca..ec2d88b 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -17,4 +17,3 @@ jobs: config-name: release-drafter-config.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - diff --git a/.github/workflows/version-and-release.yml b/.github/workflows/version-and-release.yml index a42782b..8ea1964 100644 --- a/.github/workflows/version-and-release.yml +++ b/.github/workflows/version-and-release.yml @@ -1,9 +1,8 @@ name: Release on: - push: - tags: - - '*' + release: + types: [published] jobs: build: @@ -17,6 +16,7 @@ jobs: run: | realversion="${GITHUB_REF/refs\/tags\//}" realversion="${realversion//v/}" + realversion=`echo ${realversion}|cut -d '-' -f 2-2` echo "::set-output name=VERSION::$realversion" - name: Set up publishing to maven central From ac661722a749ac8c501999d2dee4fd970e292ded Mon Sep 17 00:00:00 2001 From: Chayim Date: Tue, 27 Jul 2021 13:22:11 +0300 Subject: [PATCH 110/128] accepting versions directly (#130) --- .github/workflows/version-and-release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/version-and-release.yml b/.github/workflows/version-and-release.yml index 8ea1964..255c634 100644 --- a/.github/workflows/version-and-release.yml +++ b/.github/workflows/version-and-release.yml @@ -16,7 +16,6 @@ jobs: run: | realversion="${GITHUB_REF/refs\/tags\//}" realversion="${realversion//v/}" - realversion=`echo ${realversion}|cut -d '-' -f 2-2` echo "::set-output name=VERSION::$realversion" - name: Set up publishing to maven central From 5e1de0558ad82fdf61fb76ca0949a4bc0cbb52f0 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 29 Jul 2021 20:57:51 +0600 Subject: [PATCH 111/128] Support (Geo) Point datatype (#112) * Support (Geo) Point datatype * address equals review * remove hashCode * address toString review * assert CREATE response * Revert "remove hashCode" This reverts commit 629500d7a43f610c48b64af40b9825ac667737d7. * reorder * Use IllegalArgumentException --- .../redisgraph/graph_entities/Point.java | 62 +++++++++++++++++++ .../impl/resultset/ResultSetImpl.java | 7 +++ .../impl/resultset/ResultSetScalarTypes.java | 3 +- .../redisgraph/RedisGraphAPITest.java | 49 ++++++++++++--- 4 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/redislabs/redisgraph/graph_entities/Point.java diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Point.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Point.java new file mode 100644 index 0000000..5aeb4d3 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Point.java @@ -0,0 +1,62 @@ +package com.redislabs.redisgraph.graph_entities; + +import java.util.List; +import java.util.Objects; + +/** + * This class represents a (geographical) point in the graph. + */ +public final class Point { + + private static final double EPSILON = 1e-5; + + private final double latitude; + private final double longitude; + + /** + * @param latitude + * @param longitude + */ + public Point(double latitude, double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + + /** + * @param values {@code [latitude, longitude]} + */ + public Point(List values) { + if (values == null || values.size() != 2) { + throw new IllegalArgumentException("Point requires two doubles."); + } + this.latitude = values.get(0); + this.longitude = values.get(1); + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + + @Override + public boolean equals(Object other) { + if (this == other) return true; + if (!(other instanceof Point)) return false; + Point o = (Point) other; + return Math.abs(latitude - o.latitude) < EPSILON && + Math.abs(longitude - o.longitude) < EPSILON; + } + + @Override + public int hashCode() { + return Objects.hash(latitude, longitude); + } + + @Override + public String toString() { + return "Point{latitude=" + latitude + ", longitude=" + longitude + "}"; + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 179db89..5dff097 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -8,6 +8,7 @@ import com.redislabs.redisgraph.exceptions.JRedisGraphException; import com.redislabs.redisgraph.graph_entities.*; import com.redislabs.redisgraph.impl.graph_cache.GraphCache; +import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.exceptions.JedisDataException; @@ -239,12 +240,18 @@ private Object deserializeScalar(List rawScalarData) { return deserializePath(obj); case VALUE_MAP: return deserializeMap(obj); + case VALUE_POINT: + return deserializePoint(obj); case VALUE_UNKNOWN: default: return obj; } } + private Object deserializePoint(Object rawScalarData) { + return new Point(BuilderFactory.DOUBLE_LIST.build(rawScalarData)); + } + private Map deserializeMap(Object rawScalarData) { List keyTypeValueEntries = (List) rawScalarData; Map map = new HashMap<>(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java index e0ad7fa..1a8dc43 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetScalarTypes.java @@ -13,7 +13,8 @@ enum ResultSetScalarTypes { VALUE_EDGE, VALUE_NODE, VALUE_PATH, - VALUE_MAP; + VALUE_MAP, + VALUE_POINT; private static final ResultSetScalarTypes[] values = values(); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 700c230..80a008f 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -4,9 +4,9 @@ import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Path; +import com.redislabs.redisgraph.graph_entities.Point; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; -import com.redislabs.redisgraph.impl.resultset.RecordImpl; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import com.redislabs.redisgraph.test.utils.PathBuilder; @@ -874,6 +874,45 @@ public void testMapDataType() { Assert.assertEquals(expected, actual); } + @Test + public void testGeoPointLatLon() { + ResultSet rs = api.query("social", "CREATE (:restaurant" + + " {location: point({latitude:30.27822306, longitude:-97.75134723})})"); + Assert.assertEquals(1, rs.getStatistics().nodesCreated()); + Assert.assertEquals(1, rs.getStatistics().propertiesSet()); + + assertTestGeoPoint(); + } + + @Test + public void testGeoPointLonLat() { + ResultSet rs = api.query("social", "CREATE (:restaurant" + + " {location: point({longitude:-97.75134723, latitude:30.27822306})})"); + Assert.assertEquals(1, rs.getStatistics().nodesCreated()); + Assert.assertEquals(1, rs.getStatistics().propertiesSet()); + + assertTestGeoPoint(); + } + + private void assertTestGeoPoint() { + ResultSet results = api.query("social", "MATCH (restaurant) RETURN restaurant"); + Assert.assertEquals(1, results.size()); + Record record = results.next(); + Assert.assertEquals(1, record.size()); + Assert.assertEquals(Collections.singletonList("restaurant"), record.keys()); + Node node = record.getValue(0); + Property property = node.getProperty("location"); + Assert.assertEquals(new Point(30.27822306, -97.75134723), property.getValue()); + } + + @Test + public void timeoutArgument() { + ResultSet rs = api.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L); + Assert.assertEquals(1, rs.size()); + Record r = rs.next(); + Assert.assertEquals(Long.valueOf(100), r.getValue(0)); + } + @Test public void testCachedExecutionReadOnly() { api.query("social", "CREATE (:N {val:1}), (:N {val:2})"); @@ -898,14 +937,6 @@ public void testCachedExecutionReadOnly() { Assert.assertTrue(resultSet.getStatistics().cachedExecution()); } - @Test - public void timeoutArgument() { - ResultSet rs = api.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L); - Assert.assertEquals(1, rs.size()); - Record r = rs.next(); - Assert.assertEquals(Long.valueOf(100), r.getValue(0)); - } - @Test public void testSimpleReadOnly() { api.query("social","CREATE (:person{name:'filipe',age:30})"); From 7f71cbc0768d850816bd7cdfac914791ac18bb85 Mon Sep 17 00:00:00 2001 From: Chayim Date: Tue, 31 Aug 2021 10:43:52 +0300 Subject: [PATCH 112/128] gpg maven upgrade (#132) --- pom.xml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 61e879b..67afe44 100644 --- a/pom.xml +++ b/pom.xml @@ -3,11 +3,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - + com.redislabs jredisgraph 2.5.1-SNAPSHOT - + JRedisGraph Official client for Redis-Graph https://redisgraph.io @@ -171,7 +171,13 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 3.0.1 + + + --pinentry-mode + loopback + + sign-artifacts @@ -182,6 +188,7 @@ + org.apache.maven.plugins maven-pmd-plugin From 5f53471fa449b0b21bd070df2e816bba9b8ab0ab Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 22 Sep 2021 13:22:52 +0200 Subject: [PATCH 113/128] fix: upgrade redis.clients:jedis from 3.6.3 to 3.7.0 (#133) Snyk has created this PR to upgrade redis.clients:jedis from 3.6.3 to 3.7.0. See this package in Maven Repository: https://mvnrepository.com/artifact/redis.clients/jedis/ See this project in Snyk: https://app.snyk.io/org/dvirdukhan/project/cb2ca151-454d-4bfd-a328-6d77a935177b?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 67afe44..2ffd64a 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.6.3 + 3.7.0 org.apache.commons From a611183a962a81f7fc1b34d84d924427da30305f Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 15 Dec 2021 11:29:36 +0200 Subject: [PATCH 114/128] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2ffd64a..8635c15 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.7.0 + 3.7.1 org.apache.commons From bce45550f510c3678d6d0a2ac281ef21f48ac90e Mon Sep 17 00:00:00 2001 From: Brian Sam-Bodden Date: Mon, 10 Jan 2022 01:37:20 -0700 Subject: [PATCH 115/128] Adds Jedis constructor, general cleanup (#135) * feat: allow client to be instantiated with a Jedis instance * refactor: close standalone Jedis instance if needed * build: upgrade JUnit to 4.13.2 * refactor: fix deprecations and compiler warnings * refactor: rename api to client * test: add tests for instantiation Co-authored-by: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> --- pom.xml | 2 +- .../com/redislabs/redisgraph/RedisGraph.java | 6 + .../exceptions/JRedisGraphException.java | 24 +- .../redisgraph/graph_entities/Property.java | 2 +- .../com/redislabs/redisgraph/impl/Utils.java | 10 +- .../impl/api/ContextedRedisGraph.java | 48 +-- .../redisgraph/impl/api/RedisGraph.java | 28 +- .../impl/api/RedisGraphPipeline.java | 37 +- .../impl/api/RedisGraphTransaction.java | 70 +-- .../impl/resultset/ResultSetImpl.java | 91 ++-- .../redisgraph/InstantiationTest.java | 45 ++ .../redislabs/redisgraph/IterableTest.java | 85 ++-- .../redislabs/redisgraph/PipelineTest.java | 31 +- .../redisgraph/RedisGraphAPITest.java | 401 +++++++++--------- .../redislabs/redisgraph/TransactionTest.java | 15 +- .../exceptions/JRedisGraphErrorTest.java | 105 ++--- .../redislabs/redisgraph/impl/UtilsTest.java | 131 +++--- .../redisgraph/test/utils/PathBuilder.java | 4 +- .../test/utils/PathBuilderTest.java | 33 +- 19 files changed, 616 insertions(+), 552 deletions(-) create mode 100644 src/test/java/com/redislabs/redisgraph/InstantiationTest.java diff --git a/pom.xml b/pom.xml index 8635c15..2d73bbd 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ junit junit - 4.13.1 + 4.13.2 test diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/RedisGraph.java index 6cc57ce..f5c9a62 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraph.java @@ -4,8 +4,14 @@ import java.util.List; import java.util.Map; +import redis.clients.jedis.Jedis; + public interface RedisGraph extends Closeable { + public static RedisGraph with(Jedis jedis) { + return new com.redislabs.redisgraph.impl.api.RedisGraph(jedis); + } + /** * Execute a Cypher query. * @param graphId a graph to perform the query on diff --git a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java index db31104..db33370 100644 --- a/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java +++ b/src/main/java/com/redislabs/redisgraph/exceptions/JRedisGraphException.java @@ -3,19 +3,21 @@ import redis.clients.jedis.exceptions.JedisDataException; /** - * RedisGraph query evaluation exception. An instance of JRedisGraphException is thrown when RedisGraph - * encounters an error during query evaluation. + * RedisGraph query evaluation exception. An instance of JRedisGraphException is + * thrown when RedisGraph encounters an error during query evaluation. */ public class JRedisGraphException extends JedisDataException { - public JRedisGraphException(String message) { - super(message); - } + private static final long serialVersionUID = -476099681322055468L; - public JRedisGraphException(Throwable cause) { - super(cause); - } + public JRedisGraphException(String message) { + super(message); + } - public JRedisGraphException(String message, Throwable cause) { - super(message, cause); - } + public JRedisGraphException(Throwable cause) { + super(cause); + } + + public JRedisGraphException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java index 4be4a7a..249bd64 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Property.java @@ -73,7 +73,7 @@ private boolean valueEquals(Object value1, Object value2) { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Property)) return false; - Property property = (Property) o; + Property property = (Property) o; return Objects.equals(name, property.name) && valueEquals(value, property.value); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/Utils.java b/src/main/java/com/redislabs/redisgraph/impl/Utils.java index cdcff78..d508f9d 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/Utils.java +++ b/src/main/java/com/redislabs/redisgraph/impl/Utils.java @@ -23,7 +23,7 @@ public class Utils { escapeJavaMap.put("\"", "\\\""); ESCAPE_CHYPER = new AggregateTranslator(new LookupTranslator(Collections.unmodifiableMap(escapeJavaMap))); } - + private Utils() {} /** @@ -87,9 +87,8 @@ private static String arrayToString(Object[] arr) { } private static String valueToString(Object value) { - if(value == null) - return "null"; - + if(value == null) return "null"; + if(value instanceof String){ return quoteString((String) value); } @@ -102,7 +101,8 @@ private static String valueToString(Object value) { } if(value instanceof List){ - List list = (List)value; + @SuppressWarnings("unchecked") + List list = (List) value; return arrayToString(list.toArray()); } return value.toString(); diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java index 2de4e4d..4d6fe34 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java @@ -1,17 +1,18 @@ package com.redislabs.redisgraph.impl.api; +import java.util.List; + import com.redislabs.redisgraph.RedisGraphContext; import com.redislabs.redisgraph.ResultSet; import com.redislabs.redisgraph.exceptions.JRedisGraphException; import com.redislabs.redisgraph.impl.Utils; import com.redislabs.redisgraph.impl.graph_cache.RedisGraphCaches; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; + import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; -import redis.clients.jedis.Pipeline; -import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.exceptions.JedisDataException; -import java.util.List; +import redis.clients.jedis.util.SafeEncoder; /** * An implementation of RedisGraphContext. Allows sending RedisGraph and some Redis commands, @@ -26,7 +27,7 @@ public class ContextedRedisGraph extends AbstractRedisGraph implements RedisGrap * Generates a new instance with a specific Jedis connection * @param connectionContext */ - public ContextedRedisGraph(Jedis connectionContext){ + public ContextedRedisGraph(Jedis connectionContext) { this.connectionContext = connectionContext; } @@ -49,13 +50,12 @@ protected Jedis getConnection() { protected ResultSet sendQuery(String graphId, String preparedQuery) { Jedis conn = getConnection(); try { + @SuppressWarnings("unchecked") List rawResponse = (List) conn.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); - } - catch (JRedisGraphException rt) { + } catch (JRedisGraphException rt) { throw rt; - } - catch (JedisDataException j) { + } catch (JedisDataException j) { throw new JRedisGraphException(j); } } @@ -70,13 +70,12 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) { protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery) { Jedis conn = getConnection(); try { + @SuppressWarnings("unchecked") List rawResponse = (List) conn.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); - } - catch (JRedisGraphException ge) { + } catch (JRedisGraphException ge) { throw ge; - } - catch (JedisDataException de) { + } catch (JedisDataException de) { throw new JRedisGraphException(de); } } @@ -92,14 +91,13 @@ protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery) { protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout) { Jedis conn = getConnection(); try { + @SuppressWarnings("unchecked") List rawResponse = (List) conn.sendBlockingCommand(RedisGraphCommand.QUERY, - graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); - } - catch (JRedisGraphException rt) { + } catch (JRedisGraphException rt) { throw rt; - } - catch (JedisDataException j) { + } catch (JedisDataException j) { throw new JRedisGraphException(j); } } @@ -115,14 +113,13 @@ protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery, long timeout) { Jedis conn = getConnection(); try { + @SuppressWarnings("unchecked") List rawResponse = (List) conn.sendBlockingCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId)); - } - catch (JRedisGraphException ge) { + } catch (JRedisGraphException ge) { throw ge; - } - catch (JedisDataException de) { + } catch (JedisDataException de) { throw new JRedisGraphException(de); } } @@ -145,11 +142,11 @@ public RedisGraphTransaction multi() { Client client = jedis.getClient(); client.multi(); client.getOne(); - RedisGraphTransaction transaction = new RedisGraphTransaction(client,this); + RedisGraphTransaction transaction = new RedisGraphTransaction(client, this); transaction.setRedisGraphCaches(caches); return transaction; } - + /** * Creates a new RedisGraphPipeline pipeline object * @return new RedisGraphPipeline @@ -158,7 +155,7 @@ public RedisGraphTransaction multi() { public RedisGraphPipeline pipelined() { Jedis jedis = getConnection(); Client client = jedis.getClient(); - RedisGraphPipeline pipeline = new RedisGraphPipeline(client, this); + RedisGraphPipeline pipeline = new RedisGraphPipeline(client, this); pipeline.setRedisGraphCaches(caches); return pipeline; } @@ -193,8 +190,7 @@ public String deleteGraph(String graphId) { Object response; try { response = conn.sendCommand(RedisGraphCommand.DELETE, graphId); - } - catch (Exception e) { + } catch (Exception e) { conn.close(); throw e; } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java index 1bb0f50..d187f70 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java @@ -14,7 +14,8 @@ */ public class RedisGraph extends AbstractRedisGraph implements RedisGraphContextGenerator { - private final Pool client; + private final Pool pool; + private final Jedis jedis; private final RedisGraphCaches caches = new RedisGraphCaches(); /** @@ -32,18 +33,23 @@ public RedisGraph() { * @param port Redis port */ public RedisGraph(String host, int port) { - this( new JedisPool(host, port)); + this(new JedisPool(host, port)); } /** * Creates a client using provided Jedis pool * - * @param jedis bring your own Jedis pool + * @param pool bring your own Jedis pool */ - public RedisGraph( Pool jedis) { - this.client = jedis; + public RedisGraph(Pool pool) { + this.pool = pool; + this.jedis = null; } + public RedisGraph(Jedis jedis) { + this.jedis = jedis; + this.pool = null; + } /** * Overrides the abstract function. Gets and returns a Jedis connection from the Jedis pool @@ -51,7 +57,7 @@ public RedisGraph( Pool jedis) { */ @Override protected Jedis getConnection() { - return client.getResource(); + return jedis != null ? jedis : pool.getResource(); } /** @@ -120,11 +126,15 @@ protected ResultSet sendReadOnlyQuery(String graphId, String preparedQuery, long * Closes the Jedis pool */ @Override - public void close(){ - this.client.close(); + public void close() { + if (pool != null) { + pool.close(); + } + if (jedis != null) { + jedis.close(); + } } - /** * Deletes the entire graph * @param graphId graph to delete diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java index 5ddbf09..8078afd 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphPipeline.java @@ -38,9 +38,10 @@ public RedisGraphPipeline(Client client, RedisGraph redisGraph){ public Response query(String graphId, String query) { client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -55,9 +56,10 @@ public ResultSet build(Object o) { public Response readOnlyQuery(String graphId, String query) { client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -73,11 +75,13 @@ public ResultSet build(Object o) { */ @Override public Response query(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -93,11 +97,13 @@ public ResultSet build(Object o) { */ @Override public Response readOnlyQuery(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -114,9 +120,10 @@ public Response query(String graphId, String query, Map() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -133,9 +140,10 @@ public Response readOnlyQuery(String graphId, String query, Map() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -154,11 +162,13 @@ public ResultSet build(Object o) { @Override public Response query(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -177,11 +187,14 @@ public ResultSet build(Object o) { @Override public Response readOnlyQuery(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, + Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } diff --git a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java index 4c8c16f..5294993 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java +++ b/src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java @@ -17,13 +17,13 @@ /** * This class is extending Jedis Transaction */ -public class RedisGraphTransaction extends Transaction implements com.redislabs.redisgraph.RedisGraphTransaction, RedisGraphCacheHolder { +public class RedisGraphTransaction extends Transaction + implements com.redislabs.redisgraph.RedisGraphTransaction, RedisGraphCacheHolder { private final RedisGraph redisGraph; private RedisGraphCaches caches; - - public RedisGraphTransaction(Client client, RedisGraph redisGraph){ + public RedisGraphTransaction(Client client, RedisGraph redisGraph) { // init as in Jedis super(client); @@ -40,9 +40,10 @@ public RedisGraphTransaction(Client client, RedisGraph redisGraph){ public Response query(String graphId, String query) { client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -57,9 +58,10 @@ public ResultSet build(Object o) { public Response readOnlyQuery(String graphId, String query) { client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -75,11 +77,13 @@ public ResultSet build(Object o) { */ @Override public Response query(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -95,11 +99,13 @@ public ResultSet build(Object o) { */ @Override public Response readOnlyQuery(String graphId, String query, long timeout) { - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, query, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -115,13 +121,14 @@ public ResultSet build(Object o) { */ @Deprecated @Override - public Response query(String graphId, String query, Object ...args){ + public Response query(String graphId, String query, Object... args) { String preparedQuery = Utils.prepareQuery(query, args); client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -131,16 +138,17 @@ public ResultSet build(Object o) { * @param graphId a graph to perform the query on. * @param query Cypher query. * @param params parameters map. - * @return a response which builds the result set with the query answer. + * @return a response which builds the result set with the query answer. */ @Override public Response query(String graphId, String query, Map params) { String preparedQuery = Utils.prepareQuery(query, params); client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -150,16 +158,17 @@ public ResultSet build(Object o) { * @param graphId a graph to perform the query on. * @param query Cypher query. * @param params parameters map. - * @return a response which builds the result set with the query answer. + * @return a response which builds the result set with the query answer. */ @Override public Response readOnlyQuery(String graphId, String query, Map params) { String preparedQuery = Utils.prepareQuery(query, params); client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -168,21 +177,22 @@ public ResultSet build(Object o) { * Executes a cypher query with parameters and timeout. * * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. - * timeout. * @param graphId a graph to perform the query on. * @param query Cypher query. * @param params parameters map. * @param timeout - * @return a response which builds the result set with the query answer. + * @return a response which builds the result set with the query answer. */ @Override public Response query(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, + Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -191,21 +201,22 @@ public ResultSet build(Object o) { * Executes a cypher read-only query with parameters and timeout. * * NOTE: timeout is simply sent to DB. Socket timeout will not be changed. - * timeout. * @param graphId a graph to perform the query on. * @param query Cypher query. * @param params parameters map. * @param timeout - * @return a response which builds the result set with the query answer. + * @return a response which builds the result set with the query answer. */ @Override public Response readOnlyQuery(String graphId, String query, Map params, long timeout) { String preparedQuery = Utils.prepareQuery(query, params); - client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout)); + client.sendCommand(RedisGraphCommand.RO_QUERY, graphId, preparedQuery, Utils.COMPACT_STRING, + Utils.TIMEOUT_STRING, Long.toString(timeout)); return getResponse(new Builder() { + @SuppressWarnings("unchecked") @Override public ResultSet build(Object o) { - return new ResultSetImpl((List)o, redisGraph, caches.getGraphCache(graphId)); + return new ResultSetImpl((List) o, redisGraph, caches.getGraphCache(graphId)); } }); } @@ -216,7 +227,7 @@ public ResultSet build(Object o) { * @param procedure procedure name to invoke * @return response with result set with the procedure data */ - public Response callProcedure(String graphId, String procedure){ + public Response callProcedure(String graphId, String procedure) { return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP); } @@ -227,11 +238,10 @@ public Response callProcedure(String graphId, String procedure){ * @param args procedure arguments * @return response with result set with the procedure data */ - public Response callProcedure(String graphId, String procedure, List args ){ + public Response callProcedure(String graphId, String procedure, List args) { return callProcedure(graphId, procedure, args, Utils.DUMMY_MAP); } - /** * Invoke a stored procedure, in multi/exec context * @param graphId a graph to perform the query on @@ -241,21 +251,19 @@ public Response callProcedure(String graphId, String procedure, List< * @return response with result set with the procedure data */ public Response callProcedure(String graphId, String procedure, List args, - Map> kwargs) { + Map> kwargs) { String preparedProcedure = Utils.prepareProcedure(procedure, args, kwargs); return query(graphId, preparedProcedure); } - /** * Deletes the entire graph, in multi/exec context * @param graphId graph to delete * @return response with the deletion running time statistics */ - public Response deleteGraph(String graphId){ - + public Response deleteGraph(String graphId) { client.sendCommand(RedisGraphCommand.DELETE, graphId); - Response response = getResponse(BuilderFactory.STRING); + Response response = getResponse(BuilderFactory.STRING); caches.removeGraphCache(graphId); return response; } diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 5dff097..952b015 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -16,7 +16,6 @@ public class ResultSetImpl implements ResultSet { - private final Header header; private final Statistics statistics; private final List results; @@ -26,16 +25,18 @@ public class ResultSetImpl implements ResultSet { private final GraphCache cache; /** - * @param rawResponse the raw representation of response is at most 3 lists of objects. - * The last list is the statistics list. + * @param rawResponse the raw representation of response is at most 3 lists of + * objects. The last list is the statistics list. * @param redisGraph the graph connection * @param cache the graph local cache */ + @SuppressWarnings("unchecked") public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache cache) { this.redisGraph = redisGraph; this.cache = cache; - // If a run-time error occurred, the last member of the rawResponse will be a JedisDataException. + // If a run-time error occurred, the last member of the rawResponse will be a + // JedisDataException. if (rawResponse.get(rawResponse.size() - 1) instanceof JedisDataException) { throw new JRedisGraphException((Throwable) rawResponse.get(rawResponse.size() - 1)); @@ -45,8 +46,8 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache header = parseHeader(new ArrayList<>()); results = new ArrayList<>(); - statistics = rawResponse.isEmpty() ? parseStatistics(new ArrayList()) : - parseStatistics(rawResponse.get(rawResponse.size() - 1)); + statistics = rawResponse.isEmpty() ? parseStatistics(new ArrayList()) + : parseStatistics(rawResponse.get(rawResponse.size() - 1)); } else { @@ -56,27 +57,27 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache } } - /** * @param rawResultSet - raw result set representation * @return parsed result set */ + @SuppressWarnings("unchecked") private List parseResult(List> rawResultSet) { List results = new ArrayList<>(); if (rawResultSet == null || rawResultSet.isEmpty()) { return results; } else { - //go over each raw result + // go over each raw result for (List row : rawResultSet) { List parsedRow = new ArrayList<>(row.size()); - //go over each object in the result + // go over each object in the result for (int i = 0; i < row.size(); i++) { - //get raw representation of the object + // get raw representation of the object List obj = (List) row.get(i); - //get object type + // get object type Header.ResultSetColumnTypes objType = header.getSchemaTypes().get(i); - //deserialize according to type and + // deserialize according to type and switch (objType) { case COLUMN_NODE: parsedRow.add(deserializeNode(obj)); @@ -93,7 +94,7 @@ private List parseResult(List> rawResultSet) { } } - //create new record from deserialized objects + // create new record from deserialized objects Record record = new RecordImpl(header.getSchemaNames(), parsedRow); results.add(record); } @@ -105,11 +106,11 @@ private List parseResult(List> rawResultSet) { * @param rawStatistics raw statistics representation * @return parsed statistics */ + @SuppressWarnings("unchecked") private StatisticsImpl parseStatistics(Object rawStatistics) { return new StatisticsImpl((List) rawStatistics); } - /** * @param rawHeader - raw header representation * @return parsed header @@ -128,14 +129,15 @@ public Header getHeader() { return header; } - /** * @param rawNodeData - raw node object in the form of list of object - * rawNodeData.get(0) - id (long) - * rawNodeData.get(1) - a list y which contains the labels of this node. Each entry is a label id from the type of long - * rawNodeData.get(2) - a list which contains the properties of the node. + * rawNodeData.get(0) - id (long) rawNodeData.get(1) - a list + * y which contains the labels of this node. Each entry is a + * label id from the type of long rawNodeData.get(2) - a list + * which contains the properties of the node. * @return Node object */ + @SuppressWarnings("unchecked") private Node deserializeNode(List rawNodeData) { Node node = new Node(); deserializeGraphEntityId(node, rawNodeData.get(0)); @@ -152,29 +154,27 @@ private Node deserializeNode(List rawNodeData) { /** * @param graphEntity graph entity - * @param rawEntityId raw representation of entity id to be set to the graph entity + * @param rawEntityId raw representation of entity id to be set to the graph + * entity */ private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityId) { long id = (Long) rawEntityId; graphEntity.setId(id); } - /** - * @param rawEdgeData - a list of objects - * rawEdgeData[0] - edge id - * rawEdgeData[1] - edge relationship type - * rawEdgeData[2] - edge source - * rawEdgeData[3] - edge destination + * @param rawEdgeData - a list of objects rawEdgeData[0] - edge id + * rawEdgeData[1] - edge relationship type rawEdgeData[2] - + * edge source rawEdgeData[3] - edge destination * rawEdgeData[4] - edge properties * @return Edge object */ + @SuppressWarnings("unchecked") private Edge deserializeEdge(List rawEdgeData) { Edge edge = new Edge(); deserializeGraphEntityId(edge, rawEdgeData.get(0)); - String relationshipType = cache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue(), - redisGraph); + String relationshipType = cache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue(), redisGraph); edge.setRelationshipType(relationshipType); edge.setSource((long) rawEdgeData.get(2)); @@ -187,21 +187,19 @@ private Edge deserializeEdge(List rawEdgeData) { /** * @param entity graph entity for adding the properties to - * @param rawProperties raw representation of a list of graph entity properties. Each entry is a list (rawProperty) - * is a raw representation of property, as follows: - * rawProperty.get(0) - property key - * rawProperty.get(1) - property type - * rawProperty.get(2) - property value + * @param rawProperties raw representation of a list of graph entity properties. + * Each entry is a list (rawProperty) is a raw + * representation of property, as follows: + * rawProperty.get(0) - property key rawProperty.get(1) - + * property type rawProperty.get(2) - property value */ private void deserializeGraphEntityProperties(GraphEntity entity, List> rawProperties) { - for (List rawProperty : rawProperties) { Property property = new Property<>(); - property.setName(cache.getPropertyName(((Long) rawProperty.get(0)).intValue(), - redisGraph)); + property.setName(cache.getPropertyName(((Long) rawProperty.get(0)).intValue(), redisGraph)); - //trimmed for getting to value using deserializeScalar + // trimmed for getting to value using deserializeScalar List propertyScalar = rawProperty.subList(1, rawProperty.size()); property.setValue(deserializeScalar(propertyScalar)); @@ -212,9 +210,11 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List rawScalarData) { ResultSetScalarTypes type = getValueTypeFromObject(rawScalarData.get(0)); @@ -252,6 +252,7 @@ private Object deserializePoint(Object rawScalarData) { return new Point(BuilderFactory.DOUBLE_LIST.build(rawScalarData)); } + @SuppressWarnings("unchecked") private Map deserializeMap(Object rawScalarData) { List keyTypeValueEntries = (List) rawScalarData; Map map = new HashMap<>(); @@ -263,6 +264,7 @@ private Map deserializeMap(Object rawScalarData) { return map; } + @SuppressWarnings("unchecked") private Path deserializePath(Object rawScalarData) { List> array = (List>) rawScalarData; List nodes = (List) deserializeScalar(array.get(0)); @@ -270,6 +272,7 @@ private Path deserializePath(Object rawScalarData) { return new Path(nodes, edges); } + @SuppressWarnings("unchecked") private List deserializeArray(Object rawScalarData) { List> array = (List>) rawScalarData; List res = new ArrayList<>(array.size()); @@ -303,7 +306,6 @@ public Record next() { return results.get(position++); } - @Override public int size() { return results.size(); @@ -311,12 +313,14 @@ public int size() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ResultSetImpl)) return false; + if (this == o) + return true; + if (!(o instanceof ResultSetImpl)) + return false; ResultSetImpl resultSet = (ResultSetImpl) o; - return Objects.equals(getHeader(), resultSet.getHeader()) && - Objects.equals(getStatistics(), resultSet.getStatistics()) && - Objects.equals(results, resultSet.results); + return Objects.equals(getHeader(), resultSet.getHeader()) + && Objects.equals(getStatistics(), resultSet.getStatistics()) + && Objects.equals(results, resultSet.results); } @Override @@ -334,7 +338,6 @@ public String toString() { return sb.toString(); } - @Override public Iterator iterator() { // TODO Auto-generated method stub diff --git a/src/test/java/com/redislabs/redisgraph/InstantiationTest.java b/src/test/java/com/redislabs/redisgraph/InstantiationTest.java new file mode 100644 index 0000000..5771279 --- /dev/null +++ b/src/test/java/com/redislabs/redisgraph/InstantiationTest.java @@ -0,0 +1,45 @@ +package com.redislabs.redisgraph; + +import org.junit.After; +import org.junit.Assert; + +import com.redislabs.redisgraph.impl.api.RedisGraph; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +public class InstantiationTest { + private RedisGraphContextGenerator client; + + public void createDefaultClient() { + client = new RedisGraph(); + ResultSet resultSet = client.query("g", "CREATE ({name:'bsb'})"); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + } + + public void createClientWithHostAndPort() { + client = new RedisGraph("localhost", 6379); + ResultSet resultSet = client.query("g", "CREATE ({name:'bsb'})"); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + } + + public void createClientWithJedisInstance() { + client = new RedisGraph(new Jedis()); + ResultSet resultSet = client.query("g", "CREATE ({name:'bsb'})"); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + } + + public void createClientWithJedisPool() { + client = new RedisGraph(new JedisPool()); + ResultSet resultSet = client.query("g", "CREATE ({name:'bsb'})"); + Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); + } + + @After + public void closeClient() { + if (client != null) { + client.deleteGraph("g"); + client.close(); + } + } +} diff --git a/src/test/java/com/redislabs/redisgraph/IterableTest.java b/src/test/java/com/redislabs/redisgraph/IterableTest.java index 8ca962f..4cec849 100644 --- a/src/test/java/com/redislabs/redisgraph/IterableTest.java +++ b/src/test/java/com/redislabs/redisgraph/IterableTest.java @@ -2,65 +2,66 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import com.redislabs.redisgraph.impl.api.RedisGraph; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.redislabs.redisgraph.impl.api.RedisGraph; + public class IterableTest { - private RedisGraphContextGenerator api; + private RedisGraphContextGenerator api; - @Before - public void createApi() { - // api = new RedisGraph(); - api = new RedisGraph(); - } + @Before + public void createApi() { + api = new RedisGraph(); + } - @After - public void deleteGraph() { + @After + public void deleteGraph() { - api.deleteGraph("social"); - api.close(); - } + api.deleteGraph("social"); + api.close(); + } - @Test - public void testRecordsIterator() { - api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); + @Test + public void testRecordsIterator() { + api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); - ResultSet rs = api.query("social", "MATCH(n) RETURN n"); - int count = 0; - while (rs.hasNext()) { - rs.next(); - count++; + ResultSet rs = api.query("social", "MATCH(n) RETURN n"); + int count = 0; + while (rs.hasNext()) { + rs.next(); + count++; + } + assertEquals(rs.size(), count); } - assertEquals(rs.size(), count); - } - @Test - public void testRecordsIterable() { - api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); + @Test + public void testRecordsIterable() { + api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); - ResultSet rs = api.query("social", "MATCH(n) RETURN n"); - int count = 0; - for(Record row: rs) { - count++; + ResultSet rs = api.query("social", "MATCH(n) RETURN n"); + int count = 0; + for (@SuppressWarnings("unused") + Record row : rs) { + count++; + } + assertEquals(rs.size(), count); } - assertEquals(rs.size(), count); - } - @Test - public void testRecordsIteratorAndIterable() { - api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); + @Test + public void testRecordsIteratorAndIterable() { + api.query("social", "UNWIND(range(0,50)) as i CREATE(:N{i:i})"); - ResultSet rs = api.query("social", "MATCH(n) RETURN n"); - rs.next(); - int count = 0; - for(Record row: rs) { - count++; + ResultSet rs = api.query("social", "MATCH(n) RETURN n"); + rs.next(); + int count = 0; + for (@SuppressWarnings("unused") + Record row : rs) { + count++; + } + assertEquals(rs.size(), count); } - assertEquals(rs.size(), count); - } } diff --git a/src/test/java/com/redislabs/redisgraph/PipelineTest.java b/src/test/java/com/redislabs/redisgraph/PipelineTest.java index 5dd58e2..1ec8beb 100644 --- a/src/test/java/com/redislabs/redisgraph/PipelineTest.java +++ b/src/test/java/com/redislabs/redisgraph/PipelineTest.java @@ -1,17 +1,18 @@ package com.redislabs.redisgraph; -import com.redislabs.redisgraph.Statistics.Label; -import com.redislabs.redisgraph.graph_entities.Edge; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.*; - public class PipelineTest { private RedisGraphContextGenerator api; @@ -20,7 +21,7 @@ public PipelineTest() { } @Before - public void createApi(){ + public void createApi() { api = new RedisGraph(); } @@ -31,7 +32,7 @@ public void deleteGraph() { } @Test - public void testSync(){ + public void testSync() { try (RedisGraphContext c = api.getContext()) { RedisGraphPipeline pipeline = c.pipelined(); pipeline.set("x", "1"); @@ -54,7 +55,6 @@ public void testSync(){ Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); resultSet = (ResultSet) results.get(2); Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); @@ -75,7 +75,6 @@ public void testSync(){ Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); - List schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); Assert.assertEquals(1, schemaNames.size()); @@ -101,7 +100,6 @@ public void testSync(){ Assert.assertNotNull(resultSet.getHeader()); header = resultSet.getHeader(); - schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); Assert.assertEquals(1, schemaNames.size()); @@ -117,10 +115,10 @@ record = resultSet.next(); } @Test - public void testReadOnlyQueries(){ + public void testReadOnlyQueries() { try (RedisGraphContext c = api.getContext()) { RedisGraphPipeline pipeline = c.pipelined(); - + pipeline.set("x", "1"); pipeline.query("social", "CREATE (:Person {name:'a'})"); pipeline.query("g", "CREATE (:Person {name:'a'})"); @@ -139,7 +137,6 @@ public void testReadOnlyQueries(){ Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); Assert.assertEquals(1, resultSet.getStatistics().propertiesSet()); - Assert.assertEquals(ResultSetImpl.class, results.get(2).getClass()); resultSet = (ResultSet) results.get(2); Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); @@ -190,9 +187,9 @@ record = resultSet.next(); Assert.assertEquals("Person", record.getValue("label")); } } - + @Test - public void testWaitReplicas(){ + public void testWaitReplicas() { try (RedisGraphContext c = api.getContext()) { RedisGraphPipeline pipeline = c.pipelined(); pipeline.set("x", "1"); diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 80a008f..5fdf54f 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -1,5 +1,14 @@ package com.redislabs.redisgraph; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import com.redislabs.redisgraph.Statistics.Label; import com.redislabs.redisgraph.graph_entities.Edge; import com.redislabs.redisgraph.graph_entities.Node; @@ -7,36 +16,27 @@ import com.redislabs.redisgraph.graph_entities.Point; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; -import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; import com.redislabs.redisgraph.test.utils.PathBuilder; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.*; - public class RedisGraphAPITest { - private RedisGraphContextGenerator api; - - public RedisGraphAPITest() { - } + private RedisGraphContextGenerator client; @Before - public void createApi(){ - api = new RedisGraph(); + public void createApi() { + client = new RedisGraph(); } @After public void deleteGraph() { - api.deleteGraph("social"); - api.close(); + client.deleteGraph("social"); + client.close(); } @Test public void testCreateNode() { - // Create a node - ResultSet resultSet = api.query("social", "CREATE ({name:'roi',age:32})"); + // Create a node + ResultSet resultSet = client.query("social", "CREATE ({name:'roi',age:32})"); Assert.assertEquals(1, resultSet.getStatistics().nodesCreated()); Assert.assertNull(resultSet.getStatistics().getStringValue(Label.NODES_DELETED)); @@ -45,7 +45,6 @@ public void testCreateNode() { Assert.assertEquals(2, resultSet.getStatistics().propertiesSet()); Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); - Assert.assertFalse(resultSet.hasNext()); try { @@ -58,7 +57,7 @@ public void testCreateNode() { @Test public void testCreateLabeledNode() { // Create a node with a label - ResultSet resultSet = api.query("social", "CREATE (:human{name:'danny',age:12})"); + ResultSet resultSet = client.query("social", "CREATE (:human{name:'danny',age:12})"); Assert.assertFalse(resultSet.hasNext()); Assert.assertEquals("1", resultSet.getStatistics().getStringValue(Label.NODES_CREATED)); Assert.assertEquals("2", resultSet.getStatistics().getStringValue(Label.PROPERTIES_SET)); @@ -68,11 +67,12 @@ public void testCreateLabeledNode() { @Test public void testConnectNodes() { // Create both source and destination nodes - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'amit',age:30})")); // Connect source and destination nodes. - ResultSet resultSet = api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); + ResultSet resultSet = client.query("social", + "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)"); Assert.assertFalse(resultSet.hasNext()); Assert.assertNull(resultSet.getStatistics().getStringValue(Label.NODES_CREATED)); @@ -83,10 +83,10 @@ public void testConnectNodes() { } @Test - public void testDeleteNodes(){ - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); - ResultSet deleteResult = api.query("social", "MATCH (a:person) WHERE (a.name = 'roi') DELETE a"); + public void testDeleteNodes() { + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'amit',age:30})")); + ResultSet deleteResult = client.query("social", "MATCH (a:person) WHERE (a.name = 'roi') DELETE a"); Assert.assertFalse(deleteResult.hasNext()); Assert.assertNull(deleteResult.getStatistics().getStringValue(Label.NODES_CREATED)); @@ -97,9 +97,10 @@ public void testDeleteNodes(){ Assert.assertEquals(1, deleteResult.getStatistics().nodesDeleted()); Assert.assertNotNull(deleteResult.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); - Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)")); - deleteResult = api.query("social", "MATCH (a:person) WHERE (a.name = 'roi') DELETE a"); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", + "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)")); + deleteResult = client.query("social", "MATCH (a:person) WHERE (a.name = 'roi') DELETE a"); Assert.assertFalse(deleteResult.hasNext()); Assert.assertNull(deleteResult.getStatistics().getStringValue(Label.NODES_CREATED)); @@ -114,12 +115,13 @@ public void testDeleteNodes(){ } @Test - public void testDeleteRelationship(){ + public void testDeleteRelationship() { - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); - Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)")); - ResultSet deleteResult = api.query("social", "MATCH (a:person)-[e]->() WHERE (a.name = 'roi') DELETE e"); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull(client.query("social", + "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)")); + ResultSet deleteResult = client.query("social", "MATCH (a:person)-[e]->() WHERE (a.name = 'roi') DELETE e"); Assert.assertFalse(deleteResult.hasNext()); Assert.assertNull(deleteResult.getStatistics().getStringValue(Label.NODES_CREATED)); @@ -133,28 +135,27 @@ public void testDeleteRelationship(){ } - @Test public void testIndex() { // Create both source and destination nodes - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); - ResultSet createIndexResult = api.query("social", "CREATE INDEX ON :person(age)"); + ResultSet createIndexResult = client.query("social", "CREATE INDEX ON :person(age)"); Assert.assertFalse(createIndexResult.hasNext()); Assert.assertEquals(1, createIndexResult.getStatistics().indicesAdded()); // since RediSearch as index, those action are allowed - ResultSet createNonExistingIndexResult = api.query("social", "CREATE INDEX ON :person(age1)"); + ResultSet createNonExistingIndexResult = client.query("social", "CREATE INDEX ON :person(age1)"); Assert.assertFalse(createNonExistingIndexResult.hasNext()); Assert.assertNotNull(createNonExistingIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); Assert.assertEquals(1, createNonExistingIndexResult.getStatistics().indicesAdded()); - ResultSet createExistingIndexResult = api.query("social", "CREATE INDEX ON :person(age)"); + ResultSet createExistingIndexResult = client.query("social", "CREATE INDEX ON :person(age)"); Assert.assertFalse(createExistingIndexResult.hasNext()); Assert.assertNotNull(createExistingIndexResult.getStatistics().getStringValue(Label.INDICES_ADDED)); Assert.assertEquals(0, createExistingIndexResult.getStatistics().indicesAdded()); - ResultSet deleteExistingIndexResult = api.query("social", "DROP INDEX ON :person(age)"); + ResultSet deleteExistingIndexResult = client.query("social", "DROP INDEX ON :person(age)"); Assert.assertFalse(deleteExistingIndexResult.hasNext()); Assert.assertNotNull(deleteExistingIndexResult.getStatistics().getStringValue(Label.INDICES_DELETED)); Assert.assertEquals(1, deleteExistingIndexResult.getStatistics().indicesDeleted()); @@ -162,21 +163,22 @@ public void testIndex() { } @Test - public void testHeader(){ + public void testHeader() { - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); - Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull(client.query("social", + "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)")); - ResultSet queryResult = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age"); + ResultSet queryResult = client.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age"); Header header = queryResult.getHeader(); Assert.assertNotNull(header); Assert.assertEquals("HeaderImpl{" - + "schemaTypes=[COLUMN_SCALAR, COLUMN_SCALAR, COLUMN_SCALAR], " - + "schemaNames=[a, r, a.age]}", header.toString()); -// Assert.assertEquals(-1901778507, header.hashCode()); - + + "schemaTypes=[COLUMN_SCALAR, COLUMN_SCALAR, COLUMN_SCALAR], " + + "schemaNames=[a, r, a.age]}", header.toString()); + // Assert.assertEquals(-1901778507, header.hashCode()); + List schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); @@ -188,11 +190,11 @@ public void testHeader(){ } @Test - public void testRecord(){ + public void testRecord() { String name = "roi"; int age = 32; double doubleValue = 3.14; - boolean boolValue = true; + boolean boolValue = true; String place = "TLV"; int since = 2000; @@ -214,11 +216,12 @@ public void testRecord(){ expectedNode.addProperty(doubleProperty); expectedNode.addProperty(trueBooleanProperty); Assert.assertEquals( - "Node{labels=[person], id=0, " - + "propertyMap={name=Property{name='name', value=roi}, " - + "boolValue=Property{name='boolValue', value=true}, " - + "doubleValue=Property{name='doubleValue', value=3.14}, " - + "age=Property{name='age', value=32}}}", expectedNode.toString()); + "Node{labels=[person], id=0, " + + "propertyMap={name=Property{name='name', value=roi}, " + + "boolValue=Property{name='boolValue', value=true}, " + + "doubleValue=Property{name='doubleValue', value=3.14}, " + + "age=Property{name='age', value=32}}}", + expectedNode.toString()); Edge expectedEdge = new Edge(); expectedEdge.setId(0); @@ -230,10 +233,10 @@ public void testRecord(){ expectedEdge.addProperty(doubleProperty); expectedEdge.addProperty(falseBooleanProperty); Assert.assertEquals("Edge{relationshipType='knows', source=0, destination=1, id=0, " - + "propertyMap={boolValue=Property{name='boolValue', value=false}, " - + "place=Property{name='place', value=TLV}, " - + "doubleValue=Property{name='doubleValue', value=3.14}, " - + "since=Property{name='since', value=2000}}}", expectedEdge.toString()); + + "propertyMap={boolValue=Property{name='boolValue', value=false}, " + + "place=Property{name='place', value=TLV}, " + + "doubleValue=Property{name='doubleValue', value=3.14}, " + + "since=Property{name='since', value=2000}}}", expectedEdge.toString()); Map params = new HashMap<>(); params.put("name", name); @@ -241,17 +244,18 @@ public void testRecord(){ params.put("boolValue", boolValue); params.put("doubleValue", doubleValue); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:$name,age:$age, doubleValue:$doubleValue, boolValue:$boolValue})", params)); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); - Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + - "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false}]->(b)")); + Assert.assertNotNull(client.query("social", + "CREATE (:person{name:$name,age:$age, doubleValue:$doubleValue, boolValue:$boolValue})", params)); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull( + client.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false}]->(b)")); - ResultSet resultSet = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + + ResultSet resultSet = client.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + "a.name, a.age, a.doubleValue, a.boolValue, " + "r.place, r.since, r.doubleValue, r.boolValue"); Assert.assertNotNull(resultSet); - Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); Assert.assertEquals(0, resultSet.getStatistics().nodesDeleted()); Assert.assertEquals(0, resultSet.getStatistics().labelsAdded()); @@ -260,7 +264,6 @@ public void testRecord(){ Assert.assertEquals(0, resultSet.getStatistics().relationshipsDeleted()); Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); - Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); Record record = resultSet.next(); @@ -285,45 +288,33 @@ public void testRecord(){ "r.place", "r.since", "r.doubleValue", "r.boolValue"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, (long)age, doubleValue, true, - place, (long)since, doubleValue, false), + name, (long) age, doubleValue, true, + place, (long) since, doubleValue, false), record.values()); Node a = record.getValue("a"); - for (String propertyName : expectedNode.getEntityPropertyNames()){ - Assert.assertEquals(expectedNode.getProperty(propertyName) ,a.getProperty(propertyName)); + for (String propertyName : expectedNode.getEntityPropertyNames()) { + Assert.assertEquals(expectedNode.getProperty(propertyName), a.getProperty(propertyName)); } - Assert.assertEquals( "roi", record.getString(2)); - Assert.assertEquals( "32", record.getString(3)); - Assert.assertEquals( 32L, ((Long)record.getValue(3)).longValue()); - Assert.assertEquals( 32L, ((Long)record.getValue("a.age")).longValue()); - Assert.assertEquals( "roi", record.getString("a.name")); - Assert.assertEquals( "32", record.getString("a.age")); - - } + Assert.assertEquals("roi", record.getString(2)); + Assert.assertEquals("32", record.getString(3)); + Assert.assertEquals(32L, ((Long) record.getValue(3)).longValue()); + Assert.assertEquals(32L, ((Long) record.getValue("a.age")).longValue()); + Assert.assertEquals("roi", record.getString("a.name")); + Assert.assertEquals("32", record.getString("a.age")); - @Ignore - @Test - public void tinyTestMultiThread(){ - ResultSet resultSet = api.query("social", "CREATE ({name:'roi',age:32})"); - api.query("social", "MATCH (a:person) RETURN a"); - for (int i =0; i < 10000; i++){ - List resultSets = IntStream.range(0,16).parallel(). - mapToObj( - j-> api.query("social", "MATCH (a:person) RETURN a")). - collect(Collectors.toList()); - } } @Test - public void testMultiThread(){ + public void testMultiThread() { - Assert.assertNotNull(api.query("social", "CREATE (:person {name:'roi', age:32})-[:knows]->(:person {name:'amit',age:30}) ")); + Assert.assertNotNull(client.query("social", + "CREATE (:person {name:'roi', age:32})-[:knows]->(:person {name:'amit',age:30}) ")); - List resultSets = IntStream.range(0,16).parallel(). - mapToObj(i-> api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")). - collect(Collectors.toList()); + List resultSets = IntStream.range(0, 16).parallel() + .mapToObj(i -> client.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.age")) + .collect(Collectors.toList()); Property nameProperty = new Property<>("name", "roi"); Property ageProperty = new Property<>("age", 32); @@ -335,15 +326,13 @@ public void testMultiThread(){ expectedNode.addProperty(nameProperty); expectedNode.addProperty(ageProperty); - Edge expectedEdge = new Edge(); expectedEdge.setId(0); expectedEdge.setSource(0); expectedEdge.setDestination(1); expectedEdge.setRelationshipType("knows"); - - for (ResultSet resultSet : resultSets){ + for (ResultSet resultSet : resultSets) { Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); List schemaNames = header.getSchemaNames(); @@ -360,7 +349,7 @@ public void testMultiThread(){ Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, 32L), record.values()); } - //test for update in local cache + // test for update in local cache expectedNode.removeProperty("name"); expectedNode.removeProperty("age"); expectedNode.addProperty(lastNameProperty); @@ -368,21 +357,21 @@ public void testMultiThread(){ expectedNode.addLabel("worker"); expectedNode.setId(2); - expectedEdge.setRelationshipType("worksWith"); expectedEdge.setSource(2); expectedEdge.setDestination(3); expectedEdge.setId(1); - Assert.assertNotNull(api.query("social", "CREATE (:worker{lastName:'a'})")); - Assert.assertNotNull(api.query("social", "CREATE (:worker{lastName:'b'})")); - Assert.assertNotNull(api.query("social", "MATCH (a:worker), (b:worker) WHERE (a.lastName = 'a' AND b.lastName='b') CREATE (a)-[:worksWith]->(b)")); + Assert.assertNotNull(client.query("social", "CREATE (:worker{lastName:'a'})")); + Assert.assertNotNull(client.query("social", "CREATE (:worker{lastName:'b'})")); + Assert.assertNotNull(client.query("social", + "MATCH (a:worker), (b:worker) WHERE (a.lastName = 'a' AND b.lastName='b') CREATE (a)-[:worksWith]->(b)")); - resultSets = IntStream.range(0,16).parallel(). - mapToObj(i-> api.query("social", "MATCH (a:worker)-[r:worksWith]->(b:worker) RETURN a,r")). - collect(Collectors.toList()); + resultSets = IntStream.range(0, 16).parallel() + .mapToObj(i -> client.query("social", "MATCH (a:worker)-[r:worksWith]->(b:worker) RETURN a,r")) + .collect(Collectors.toList()); - for (ResultSet resultSet : resultSets){ + for (ResultSet resultSet : resultSets) { Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); List schemaNames = header.getSchemaNames(); @@ -399,18 +388,18 @@ public void testMultiThread(){ } } - @Test - public void testAdditionToProcedures(){ + public void testAdditionToProcedures() { - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'roi',age:32})")); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'amit',age:30})")); - Assert.assertNotNull(api.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'roi',age:32})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'amit',age:30})")); + Assert.assertNotNull(client.query("social", + "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")); - //expected objects init + // expected objects init Property nameProperty = new Property<>("name", "roi"); Property ageProperty = new Property<>("age", 32); - Property lastNameProperty =new Property<>("lastName", "a"); + Property lastNameProperty = new Property<>("lastName", "a"); Node expectedNode = new Node(); expectedNode.setId(0); @@ -418,15 +407,13 @@ public void testAdditionToProcedures(){ expectedNode.addProperty(nameProperty); expectedNode.addProperty(ageProperty); - Edge expectedEdge = new Edge(); expectedEdge.setId(0); expectedEdge.setSource(0); expectedEdge.setDestination(1); expectedEdge.setRelationshipType("knows"); - - ResultSet resultSet = api.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r"); + ResultSet resultSet = client.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r"); Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); List schemaNames = header.getSchemaNames(); @@ -441,7 +428,7 @@ public void testAdditionToProcedures(){ Assert.assertEquals(Arrays.asList("a", "r"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge), record.values()); - //test for local cache updates + // test for local cache updates expectedNode.removeProperty("name"); expectedNode.removeProperty("age"); @@ -453,10 +440,11 @@ public void testAdditionToProcedures(){ expectedEdge.setSource(2); expectedEdge.setDestination(3); expectedEdge.setId(1); - Assert.assertNotNull(api.query("social", "CREATE (:worker{lastName:'a'})")); - Assert.assertNotNull(api.query("social", "CREATE (:worker{lastName:'b'})")); - Assert.assertNotNull(api.query("social", "MATCH (a:worker), (b:worker) WHERE (a.lastName = 'a' AND b.lastName='b') CREATE (a)-[:worksWith]->(b)")); - resultSet = api.query("social", "MATCH (a:worker)-[r:worksWith]->(b:worker) RETURN a,r"); + Assert.assertNotNull(client.query("social", "CREATE (:worker{lastName:'a'})")); + Assert.assertNotNull(client.query("social", "CREATE (:worker{lastName:'b'})")); + Assert.assertNotNull(client.query("social", + "MATCH (a:worker), (b:worker) WHERE (a.lastName = 'a' AND b.lastName='b') CREATE (a)-[:worksWith]->(b)")); + resultSet = client.query("social", "MATCH (a:worker)-[r:worksWith]->(b:worker) RETURN a,r"); Assert.assertNotNull(resultSet.getHeader()); header = resultSet.getHeader(); schemaNames = header.getSchemaNames(); @@ -475,12 +463,19 @@ record = resultSet.next(); @Test public void testEscapedQuery() { - Assert.assertNotNull(api.query("social", "CREATE (:escaped{s1:%s,s2:%s})", "S\"'", "S'\"")); - Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1=%s and n.s2=%s RETURN n", "S\"'", "S'\"")); - Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"' RETURN n")); + Map params1 = new HashMap(); + params1.put("s1", "S\"'"); + params1.put("s2", "S'\""); + Assert.assertNotNull(client.query("social", "CREATE (:escaped{s1:$s1,s2:$s2})", params1)); - } + Map params2 = new HashMap(); + params2.put("s1", "S\"'"); + params2.put("s2", "S'\""); + Assert.assertNotNull(client.query("social", "MATCH (n) where n.s1=$s1 and n.s2=$s2 RETURN n", params2)); + + Assert.assertNotNull(client.query("social", "MATCH (n) where n.s1='S\"' RETURN n")); + } @Test public void testContextedAPI() { @@ -493,7 +488,6 @@ public void testContextedAPI() { String place = "TLV"; int since = 2000; - Property nameProperty = new Property<>("name", name); Property ageProperty = new Property<>("age", age); Property doubleProperty = new Property<>("doubleValue", doubleValue); @@ -526,11 +520,13 @@ public void testContextedAPI() { params.put("age", age); params.put("boolValue", boolValue); params.put("doubleValue", doubleValue); - try (RedisGraphContext c = api.getContext()) { - Assert.assertNotNull(c.query("social", "CREATE (:person{name:$name, age:$age, doubleValue:$doubleValue, boolValue:$boolValue})", params)); + try (RedisGraphContext c = client.getContext()) { + Assert.assertNotNull(c.query("social", + "CREATE (:person{name:$name, age:$age, doubleValue:$doubleValue, boolValue:$boolValue})", params)); Assert.assertNotNull(c.query("social", "CREATE (:person{name:'amit',age:30})")); - Assert.assertNotNull(c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + - "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false}]->(b)")); + Assert.assertNotNull( + c.query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') " + + "CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false}]->(b)")); ResultSet resultSet = c.query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, " + "a.name, a.age, a.doubleValue, a.boolValue, " + @@ -569,8 +565,8 @@ public void testContextedAPI() { "r.place", "r.since", "r.doubleValue", "r.boolValue"), record.keys()); Assert.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, (long)age, doubleValue, true, - place, (long)since, doubleValue, false), + name, (long) age, doubleValue, true, + place, (long) since, doubleValue, false), record.values()); Node a = record.getValue("a"); @@ -600,7 +596,6 @@ public void testArraySupport() { expectedANode.addProperty(aAgeProperty); expectedANode.addProperty(aListProperty); - Node expectedBNode = new Node(); expectedBNode.setId(1); expectedBNode.addLabel("person"); @@ -611,21 +606,17 @@ public void testArraySupport() { expectedBNode.addProperty(bAgeProperty); expectedBNode.addProperty(bListProperty); - - - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'a',age:32,array:[0,1,2]})")); - Assert.assertNotNull(api.query("social", "CREATE (:person{name:'b',age:30,array:[3,4,5]})")); - + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'a',age:32,array:[0,1,2]})")); + Assert.assertNotNull(client.query("social", "CREATE (:person{name:'b',age:30,array:[3,4,5]})")); // test array - ResultSet resultSet = api.query("social", "WITH [0,1,2] as x return x"); + ResultSet resultSet = client.query("social", "WITH [0,1,2] as x return x"); // check header Assert.assertNotNull(resultSet.getHeader()); Header header = resultSet.getHeader(); - List schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); Assert.assertEquals(1, schemaNames.size()); @@ -638,17 +629,15 @@ public void testArraySupport() { Assert.assertFalse(resultSet.hasNext()); Assert.assertEquals(Arrays.asList("x"), record.keys()); - List x = record.getValue("x"); Assert.assertEquals(Arrays.asList(0L, 1L, 2L), x); // test collect - resultSet = api.query("social", "MATCH(n) return collect(n) as x"); + resultSet = client.query("social", "MATCH(n) return collect(n) as x"); Assert.assertNotNull(resultSet.getHeader()); header = resultSet.getHeader(); - schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); Assert.assertEquals(1, schemaNames.size()); @@ -663,14 +652,12 @@ record = resultSet.next(); x = record.getValue("x"); Assert.assertEquals(Arrays.asList(expectedANode, expectedBNode), x); - // test unwind - resultSet = api.query("social", "unwind([0,1,2]) as x return x"); + resultSet = client.query("social", "unwind([0,1,2]) as x return x"); Assert.assertNotNull(resultSet.getHeader()); header = resultSet.getHeader(); - schemaNames = header.getSchemaNames(); Assert.assertNotNull(schemaNames); Assert.assertEquals(1, schemaNames.size()); @@ -683,16 +670,16 @@ record = resultSet.next(); Assert.assertTrue(resultSet.hasNext()); record = resultSet.next(); Assert.assertEquals(Arrays.asList("x"), record.keys()); - Assert.assertEquals(i, (long)record.getValue("x")); + Assert.assertEquals(i, (long) record.getValue("x")); } } @Test - public void testPath(){ - List nodes = new ArrayList<>(3); - for(int i =0; i < 3; i++){ + public void testPath() { + List nodes = new ArrayList<>(3); + for (int i = 0; i < 3; i++) { Node node = new Node(); node.setId(i); node.addLabel("L1"); @@ -700,7 +687,7 @@ public void testPath(){ } List edges = new ArrayList<>(2); - for(int i =0; i <2; i++){ + for (int i = 0; i < 2; i++) { Edge edge = new Edge(); edge.setId(i); edge.setRelationshipType("R1"); @@ -713,18 +700,19 @@ public void testPath(){ Path path01 = new PathBuilder(2).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)).build(); Path path12 = new PathBuilder(2).append(nodes.get(1)).append(edges.get(1)).append(nodes.get(2)).build(); - Path path02 = new PathBuilder(3).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)).append(edges.get(1)).append(nodes.get(2)).build(); + Path path02 = new PathBuilder(3).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)) + .append(edges.get(1)).append(nodes.get(2)).build(); expectedPaths.add(path01); expectedPaths.add(path12); expectedPaths.add(path02); - api.query("social", "CREATE (:L1)-[:R1]->(:L1)-[:R1]->(:L1)"); + client.query("social", "CREATE (:L1)-[:R1]->(:L1)-[:R1]->(:L1)"); - ResultSet resultSet = api.query("social", "MATCH p = (:L1)-[:R1*]->(:L1) RETURN p"); + ResultSet resultSet = client.query("social", "MATCH p = (:L1)-[:R1*]->(:L1) RETURN p"); Assert.assertEquals(expectedPaths.size(), resultSet.size()); - for(int i =0; i < resultSet.size(); i++){ + for (int i = 0; i < resultSet.size(); i++) { Path p = resultSet.next().getValue("p"); Assert.assertTrue(expectedPaths.contains(p)); expectedPaths.remove(p); @@ -733,53 +721,55 @@ public void testPath(){ } @Test - public void testParameters(){ - Object[] parameters = {1, 2.3, true, false, null, "str", 'a', "b" ,Arrays.asList(1,2,3), new Integer[]{1,2,3}}; - Object[] expected_anwsers = {1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), new Long[]{1L, 2L, 3L}}; + public void testParameters() { + Object[] parameters = { 1, 2.3, true, false, null, "str", 'a', "b", Arrays.asList(1, 2, 3), + new Integer[] { 1, 2, 3 } }; + Object[] expected_anwsers = { 1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), + new Long[] { 1L, 2L, 3L } }; Map params = new HashMap<>(); - for (int i=0; i < parameters.length; i++) { + for (int i = 0; i < parameters.length; i++) { Object param = parameters[i]; params.put("param", param); - ResultSet resultSet = api.query("social", "RETURN $param", params); + ResultSet resultSet = client.query("social", "RETURN $param", params); Assert.assertEquals(1, resultSet.size()); Record r = resultSet.next(); Object o = r.getValue(0); Object expected = expected_anwsers[i]; - if(i == parameters.length-1) { - expected = Arrays.asList((Object[])expected); + if (i == parameters.length - 1) { + expected = Arrays.asList((Object[]) expected); } Assert.assertEquals(expected, o); } } - @Test - public void testParametersReadOnly(){ - Object[] parameters = {1, 2.3, true, false, null, "str", 'a', "b" ,Arrays.asList(1,2,3), new Integer[]{1,2,3}}; - Object[] expected_anwsers = {1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), new Long[]{1L, 2L, 3L}}; + public void testParametersReadOnly() { + Object[] parameters = { 1, 2.3, true, false, null, "str", 'a', "b", Arrays.asList(1, 2, 3), + new Integer[] { 1, 2, 3 } }; + Object[] expected_anwsers = { 1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), + new Long[] { 1L, 2L, 3L } }; Map params = new HashMap<>(); - for (int i=0; i < parameters.length; i++) { + for (int i = 0; i < parameters.length; i++) { Object param = parameters[i]; params.put("param", param); - ResultSet resultSetRo = api.readOnlyQuery("social", "RETURN $param", params); + ResultSet resultSetRo = client.readOnlyQuery("social", "RETURN $param", params); Assert.assertEquals(1, resultSetRo.size()); Record rRo = resultSetRo.next(); Object oRo = rRo.getValue(0); Object expected = expected_anwsers[i]; - if(i == parameters.length-1) { - expected = Arrays.asList((Object[])expected); + if (i == parameters.length - 1) { + expected = Arrays.asList((Object[]) expected); } Assert.assertEquals(expected, oRo); } } - @Test public void testNullGraphEntities() { // Create two nodes connected by a single outgoing edge. - Assert.assertNotNull(api.query("social", "CREATE (:L)-[:E]->(:L2)")); + Assert.assertNotNull(client.query("social", "CREATE (:L)-[:E]->(:L2)")); // Test a query that produces 1 record with 3 null values. - ResultSet resultSet = api.query("social", "OPTIONAL MATCH (a:NONEXISTENT)-[e]->(b) RETURN a, e, b"); + ResultSet resultSet = client.query("social", "OPTIONAL MATCH (a:NONEXISTENT)-[e]->(b) RETURN a, e, b"); Assert.assertEquals(1, resultSet.size()); Assert.assertTrue(resultSet.hasNext()); Record record = resultSet.next(); @@ -787,7 +777,7 @@ public void testNullGraphEntities() { Assert.assertEquals(Arrays.asList(null, null, null), record.values()); // Test a query that produces 2 records, with 2 null values in the second. - resultSet = api.query("social", "MATCH (a) OPTIONAL MATCH (a)-[e]->(b) RETURN a, e, b ORDER BY ID(a)"); + resultSet = client.query("social", "MATCH (a) OPTIONAL MATCH (a)-[e]->(b) RETURN a, e, b ORDER BY ID(a)"); Assert.assertEquals(2, resultSet.size()); record = resultSet.next(); Assert.assertEquals(3, record.size()); @@ -803,10 +793,11 @@ record = resultSet.next(); Assert.assertNull(record.getValue(1)); Assert.assertNull(record.getValue(2)); - // Test a query that produces 2 records, the first containing a path and the second containing a null value. - resultSet = api.query("social", "MATCH (a) OPTIONAL MATCH p = (a)-[e]->(b) RETURN p"); + // Test a query that produces 2 records, the first containing a path and the + // second containing a null value. + resultSet = client.query("social", "MATCH (a) OPTIONAL MATCH p = (a)-[e]->(b) RETURN p"); Assert.assertEquals(2, resultSet.size()); - + record = resultSet.next(); Assert.assertEquals(1, record.size()); Assert.assertNotNull(record.getValue(0)); @@ -817,11 +808,11 @@ record = resultSet.next(); } @Test - public void test64bitnumber(){ + public void test64bitnumber() { long value = 1 << 40; Map params = new HashMap<>(); params.put("val", value); - ResultSet resultSet = api.query("social","CREATE (n {val:$val}) RETURN n.val", params); + ResultSet resultSet = client.query("social", "CREATE (n {val:$val}) RETURN n.val", params); Assert.assertEquals(1, resultSet.size()); Record r = resultSet.next(); Assert.assertEquals(Long.valueOf(value), r.getValue(0)); @@ -829,21 +820,21 @@ public void test64bitnumber(){ @Test public void testCachedExecution() { - api.query("social", "CREATE (:N {val:1}), (:N {val:2})"); - - // First time should not be loaded from execution cache + client.query("social", "CREATE (:N {val:1}), (:N {val:2})"); + + // First time should not be loaded from execution cache Map params = new HashMap<>(); params.put("val", 1L); - ResultSet resultSet = api.query("social","MATCH (n:N {val:$val}) RETURN n.val", params); + ResultSet resultSet = client.query("social", "MATCH (n:N {val:$val}) RETURN n.val", params); Assert.assertEquals(1, resultSet.size()); Record r = resultSet.next(); Assert.assertEquals(params.get("val"), r.getValue(0)); Assert.assertFalse(resultSet.getStatistics().cachedExecution()); - + // Run in loop many times to make sure the query will be loaded // from cache at least once - for (int i = 0 ; i < 64; i++){ - resultSet = api.query("social","MATCH (n:N {val:$val}) RETURN n.val", params); + for (int i = 0; i < 64; i++) { + resultSet = client.query("social", "MATCH (n:N {val:$val}) RETURN n.val", params); } Assert.assertEquals(1, resultSet.size()); r = resultSet.next(); @@ -854,20 +845,20 @@ public void testCachedExecution() { @Test public void testMapDataType() { Map expected = new HashMap<>(); - expected.put("a", (long)1); + expected.put("a", (long) 1); expected.put("b", "str"); expected.put("c", null); List d = new ArrayList<>(); - d.add((long)1); - d.add((long)2); - d.add((long)3); + d.add((long) 1); + d.add((long) 2); + d.add((long) 3); expected.put("d", d); expected.put("e", true); - Mapf = new HashMap<>(); - f.put("x", (long)1); - f.put("y", (long)2); + Map f = new HashMap<>(); + f.put("x", (long) 1); + f.put("y", (long) 2); expected.put("f", f); - ResultSet res = api.query("social", "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"); + ResultSet res = client.query("social", "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"); Assert.assertEquals(1, res.size()); Record r = res.next(); Map actual = r.getValue(0); @@ -876,7 +867,7 @@ public void testMapDataType() { @Test public void testGeoPointLatLon() { - ResultSet rs = api.query("social", "CREATE (:restaurant" + ResultSet rs = client.query("social", "CREATE (:restaurant" + " {location: point({latitude:30.27822306, longitude:-97.75134723})})"); Assert.assertEquals(1, rs.getStatistics().nodesCreated()); Assert.assertEquals(1, rs.getStatistics().propertiesSet()); @@ -886,7 +877,7 @@ public void testGeoPointLatLon() { @Test public void testGeoPointLonLat() { - ResultSet rs = api.query("social", "CREATE (:restaurant" + ResultSet rs = client.query("social", "CREATE (:restaurant" + " {location: point({longitude:-97.75134723, latitude:30.27822306})})"); Assert.assertEquals(1, rs.getStatistics().nodesCreated()); Assert.assertEquals(1, rs.getStatistics().propertiesSet()); @@ -895,19 +886,19 @@ public void testGeoPointLonLat() { } private void assertTestGeoPoint() { - ResultSet results = api.query("social", "MATCH (restaurant) RETURN restaurant"); + ResultSet results = client.query("social", "MATCH (restaurant) RETURN restaurant"); Assert.assertEquals(1, results.size()); Record record = results.next(); Assert.assertEquals(1, record.size()); Assert.assertEquals(Collections.singletonList("restaurant"), record.keys()); Node node = record.getValue(0); - Property property = node.getProperty("location"); + Property property = node.getProperty("location"); Assert.assertEquals(new Point(30.27822306, -97.75134723), property.getValue()); } @Test public void timeoutArgument() { - ResultSet rs = api.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L); + ResultSet rs = client.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L); Assert.assertEquals(1, rs.size()); Record r = rs.next(); Assert.assertEquals(Long.valueOf(100), r.getValue(0)); @@ -915,12 +906,12 @@ public void timeoutArgument() { @Test public void testCachedExecutionReadOnly() { - api.query("social", "CREATE (:N {val:1}), (:N {val:2})"); + client.query("social", "CREATE (:N {val:1}), (:N {val:2})"); // First time should not be loaded from execution cache Map params = new HashMap<>(); params.put("val", 1L); - ResultSet resultSet = api.readOnlyQuery("social","MATCH (n:N {val:$val}) RETURN n.val", params); + ResultSet resultSet = client.readOnlyQuery("social", "MATCH (n:N {val:$val}) RETURN n.val", params); Assert.assertEquals(1, resultSet.size()); Record r = resultSet.next(); Assert.assertEquals(params.get("val"), r.getValue(0)); @@ -928,8 +919,8 @@ public void testCachedExecutionReadOnly() { // Run in loop many times to make sure the query will be loaded // from cache at least once - for (int i = 0 ; i < 64; i++){ - resultSet = api.readOnlyQuery("social","MATCH (n:N {val:$val}) RETURN n.val", params); + for (int i = 0; i < 64; i++) { + resultSet = client.readOnlyQuery("social", "MATCH (n:N {val:$val}) RETURN n.val", params); } Assert.assertEquals(1, resultSet.size()); r = resultSet.next(); @@ -939,8 +930,8 @@ public void testCachedExecutionReadOnly() { @Test public void testSimpleReadOnly() { - api.query("social","CREATE (:person{name:'filipe',age:30})"); - ResultSet rsRo = api.readOnlyQuery("social", "MATCH (a:person) WHERE (a.name = 'filipe') RETURN a.age"); + client.query("social", "CREATE (:person{name:'filipe',age:30})"); + ResultSet rsRo = client.readOnlyQuery("social", "MATCH (a:person) WHERE (a.name = 'filipe') RETURN a.age"); Assert.assertEquals(1, rsRo.size()); Record r = rsRo.next(); Assert.assertEquals(Long.valueOf(30), r.getValue(0)); diff --git a/src/test/java/com/redislabs/redisgraph/TransactionTest.java b/src/test/java/com/redislabs/redisgraph/TransactionTest.java index 28f31f0..0df475b 100644 --- a/src/test/java/com/redislabs/redisgraph/TransactionTest.java +++ b/src/test/java/com/redislabs/redisgraph/TransactionTest.java @@ -1,15 +1,20 @@ package com.redislabs.redisgraph; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import com.redislabs.redisgraph.graph_entities.Node; import com.redislabs.redisgraph.graph_entities.Property; import com.redislabs.redisgraph.impl.api.RedisGraph; import com.redislabs.redisgraph.impl.resultset.ResultSetImpl; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.*; - public class TransactionTest { private RedisGraphContextGenerator api; diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index 5840735..a504d4d 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -1,27 +1,29 @@ package com.redislabs.redisgraph.exceptions; -import com.redislabs.redisgraph.RedisGraphContext; -import com.redislabs.redisgraph.RedisGraphContextGenerator; -import com.redislabs.redisgraph.impl.api.RedisGraph; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.HashMap; +import com.redislabs.redisgraph.RedisGraphContext; +import com.redislabs.redisgraph.RedisGraphContextGenerator; +import com.redislabs.redisgraph.impl.api.RedisGraph; public class JRedisGraphErrorTest { private RedisGraphContextGenerator api; @Before - public void createApi(){ + public void createApi() { api = new RedisGraph(); Assert.assertNotNull(api.query("social", "CREATE (:person{mixed_prop: 'strval'}), (:person{mixed_prop: 50})")); } + @After public void deleteGraph() { @@ -29,26 +31,18 @@ public void deleteGraph() { api.close(); } - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); - @Test public void testSyntaxErrorReporting() { - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); - - // Issue a query that causes a compile-time error - api.query("social", "RETURN toUpper(5)"); - + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> api.query("social", "RETURN toUpper(5)")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); } @Test public void testRuntimeErrorReporting() { - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); - - // Issue a query that causes a run-time error - api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); } @Test @@ -57,10 +51,9 @@ public void testExceptionFlow() { try { // Issue a query that causes a compile-time error api.query("social", "RETURN toUpper(5)"); - } - catch (Exception e) { + } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); } // On general api usage, user should get a new connection @@ -68,50 +61,43 @@ public void testExceptionFlow() { try { // Issue a query that causes a compile-time error api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); - } - catch (Exception e) { + } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); } - } - @Test public void testContextSyntaxErrorReporting() { - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); RedisGraphContext c = api.getContext(); - // Issue a query that causes a compile-time error - c.query("social", "RETURN toUpper(5)"); - + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> c.query("social", "RETURN toUpper(5)")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); } @Test - public void testMissingParametersSyntaxErrorReporting(){ - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Missing parameters"); - api.query("social","RETURN $param"); + public void testMissingParametersSyntaxErrorReporting() { + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> api.query("social", "RETURN $param")); + assertTrue(exception.getMessage().contains("Missing parameters")); } @Test - public void testMissingParametersSyntaxErrorReporting2(){ - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Missing parameters"); - api.query("social","RETURN $param", new HashMap<>()); + public void testMissingParametersSyntaxErrorReporting2() { + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> api.query("social", "RETURN $param", new HashMap<>())); + assertTrue(exception.getMessage().contains("Missing parameters")); } @Test public void testContextRuntimeErrorReporting() { - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Type mismatch: expected String but was Integer"); - RedisGraphContext c = api.getContext(); - // Issue a query that causes a run-time error - c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); - } + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); + } @Test public void testContextExceptionFlow() { @@ -120,30 +106,25 @@ public void testContextExceptionFlow() { try { // Issue a query that causes a compile-time error c.query("social", "RETURN toUpper(5)"); - } - catch (Exception e) { + } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); } // On contexted api usage, connection should stay open - try { // Issue a query that causes a compile-time error c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); - } - catch (Exception e) { + } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue( e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); } - } @Test - public void timeoutExcpetion() { - exceptionRule.expect(JRedisGraphException.class); - exceptionRule.expectMessage("Query timed out"); - - api.query("social", "UNWIND range(0,100000) AS x WITH x AS x WHERE x = 10000 RETURN x", 1L); + public void timeoutException() { + JRedisGraphException exception = assertThrows(JRedisGraphException.class, + () -> api.query("social", "UNWIND range(0,100000) AS x WITH x AS x WHERE x = 10000 RETURN x", 1L)); + assertTrue(exception.getMessage().contains("Query timed out")); } } diff --git a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java index 2129f61..b745754 100644 --- a/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java +++ b/src/test/java/com/redislabs/redisgraph/impl/UtilsTest.java @@ -1,77 +1,82 @@ package com.redislabs.redisgraph.impl; -import java.util.*; +import static org.junit.Assert.assertThrows; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.IllegalFormatConversionException; +import java.util.List; +import java.util.Map; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; public class UtilsTest { - - @Test - public void testPrepareProcedure() { - - Assert.assertEquals("CALL prc()", Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), new HashMap<>())); - - Assert.assertEquals("CALL prc(\"a\",\"b\")", Utils.prepareProcedure("prc", Arrays.asList(new String[]{"a", "b"}), new HashMap<>())); - - Map> kwargs = new HashMap<>(); - kwargs.put("y", Arrays.asList(new String[]{"ka", "kb"})); - Assert.assertEquals("CALL prc(\"a\",\"b\")ka,kb", Utils.prepareProcedure("prc", Arrays.asList(new String[]{"a", "b"}), kwargs)); - - Assert.assertEquals("CALL prc()ka,kb", Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), kwargs)); - } - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); + @Test + public void testPrepareProcedure() { + Assert.assertEquals("CALL prc()", + Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), new HashMap<>())); + + Assert.assertEquals("CALL prc(\"a\",\"b\")", + Utils.prepareProcedure("prc", Arrays.asList(new String[]{"a", "b"}), new HashMap<>())); + + Map> kwargs = new HashMap<>(); + kwargs.put("y", Arrays.asList(new String[]{"ka", "kb"})); + Assert.assertEquals("CALL prc(\"a\",\"b\")ka,kb", + Utils.prepareProcedure("prc", Arrays.asList(new String[]{"a", "b"}), kwargs)); + + Assert.assertEquals("CALL prc()ka,kb", Utils.prepareProcedure("prc", Arrays.asList(new String[]{}), kwargs)); + } + @SuppressWarnings("deprecation") + @Test + public void prepareQuery() { + Assert.assertEquals("query %s %d end of query", Utils.prepareQuery("query %s %d end of query")); - @Test - public void prepareQuery() { - Assert.assertEquals("query %s %d end of query", Utils.prepareQuery("query %s %d end of query")); - - Assert.assertEquals("query 'a' 33 end of query", Utils.prepareQuery("query %s %d end of query", "a", 33)); + Assert.assertEquals("query 'a' 33 end of query", Utils.prepareQuery("query %s %d end of query", "a", 33)); - exceptionRule.expect(IllegalFormatConversionException.class); - Assert.assertEquals("CAL prc(\"a\",\"b\")ka,kb", Utils.prepareQuery("query %s %d end of query", "a", "b")); - } + assertThrows(IllegalFormatConversionException.class, + () -> Utils.prepareQuery("query %s %d end of query", "a", "b")); + } - @Test - public void testParamsPrep(){ - Map params = new HashMap<>(); - params.put("param", ""); - Assert.assertEquals("CYPHER param=\"\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", "\""); - Assert.assertEquals("CYPHER param=\"\\\"\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", "\"st"); - Assert.assertEquals("CYPHER param=\"\\\"st\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", 1); - Assert.assertEquals("CYPHER param=1 RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", 2.3); - Assert.assertEquals("CYPHER param=2.3 RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", true); - Assert.assertEquals("CYPHER param=true RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", false); - Assert.assertEquals("CYPHER param=false RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", null); - Assert.assertEquals("CYPHER param=null RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", "str"); - Assert.assertEquals("CYPHER param=\"str\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); - params.put("param", "s\"tr"); - Assert.assertEquals("CYPHER param=\"s\\\"tr\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); - Integer arr[] = {1,2,3}; - params.put("param", arr); - Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); - List list = Arrays.asList(1,2,3); - params.put("param", list); - Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); - String strArr[] = {"1", "2", "3"}; - params.put("param", strArr); - Assert.assertEquals("CYPHER param=[\"1\", \"2\", \"3\"] RETURN $param", Utils.prepareQuery("RETURN $param", params)); - List stringList = Arrays.asList("1", "2", "3"); - params.put("param", stringList); - Assert.assertEquals("CYPHER param=[\"1\", \"2\", \"3\"] RETURN $param", Utils.prepareQuery("RETURN $param", params)); - } + @Test + public void testParamsPrep() { + Map params = new HashMap<>(); + params.put("param", ""); + Assert.assertEquals("CYPHER param=\"\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "\""); + Assert.assertEquals("CYPHER param=\"\\\"\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "\"st"); + Assert.assertEquals("CYPHER param=\"\\\"st\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", 1); + Assert.assertEquals("CYPHER param=1 RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", 2.3); + Assert.assertEquals("CYPHER param=2.3 RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", true); + Assert.assertEquals("CYPHER param=true RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", false); + Assert.assertEquals("CYPHER param=false RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", null); + Assert.assertEquals("CYPHER param=null RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "str"); + Assert.assertEquals("CYPHER param=\"str\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + params.put("param", "s\"tr"); + Assert.assertEquals("CYPHER param=\"s\\\"tr\" RETURN $param", Utils.prepareQuery("RETURN $param", params)); + Integer arr[] = {1, 2, 3}; + params.put("param", arr); + Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); + List list = Arrays.asList(1, 2, 3); + params.put("param", list); + Assert.assertEquals("CYPHER param=[1, 2, 3] RETURN $param", Utils.prepareQuery("RETURN $param", params)); + String strArr[] = {"1", "2", "3"}; + params.put("param", strArr); + Assert.assertEquals("CYPHER param=[\"1\", \"2\", \"3\"] RETURN $param", + Utils.prepareQuery("RETURN $param", params)); + List stringList = Arrays.asList("1", "2", "3"); + params.put("param", stringList); + Assert.assertEquals("CYPHER param=[\"1\", \"2\", \"3\"] RETURN $param", + Utils.prepareQuery("RETURN $param", params)); + } } diff --git a/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java index 64de9c7..cf6db87 100644 --- a/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java +++ b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilder.java @@ -10,7 +10,7 @@ public final class PathBuilder{ private final List nodes; private final List edges; - private Class currentAppendClass; + private Class currentAppendClass; public PathBuilder() { this.nodes = new ArrayList<>(0); @@ -25,7 +25,7 @@ public PathBuilder(int nodesCount){ } public PathBuilder append(Object object){ - Class c = object.getClass(); + Class c = object.getClass(); if(!currentAppendClass.equals(c)) throw new IllegalArgumentException("Path Builder expected " + currentAppendClass.getSimpleName() + " but was " + c.getSimpleName()); if(c.equals(Node.class)) return appendNode((Node)object); else return appendEdge((Edge)object); diff --git a/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java index 01751eb..d6a0c03 100644 --- a/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java +++ b/src/test/java/com/redislabs/redisgraph/test/utils/PathBuilderTest.java @@ -1,28 +1,29 @@ package com.redislabs.redisgraph.test.utils; -import com.redislabs.redisgraph.graph_entities.Edge; -import org.junit.Rule; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + import org.junit.Test; -import org.junit.rules.ExpectedException; -public class PathBuilderTest { +import com.redislabs.redisgraph.graph_entities.Edge; - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); +public class PathBuilderTest { @Test - public void testPathBuilderSizeException(){ - exceptionRule.expect(IllegalArgumentException.class); - exceptionRule.expectMessage("Path builder nodes count should be edge count + 1"); - PathBuilder builder = new PathBuilder(0); - builder.build(); + public void testPathBuilderSizeException() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + PathBuilder builder = new PathBuilder(0); + builder.build(); + }); + assertTrue(exception.getMessage().equalsIgnoreCase("Path builder nodes count should be edge count + 1")); } @Test - public void testPathBuilderArgumentsException(){ - exceptionRule.expect(IllegalArgumentException.class); - exceptionRule.expectMessage("Path Builder expected Node but was Edge"); - PathBuilder builder = new PathBuilder(0); - builder.append(new Edge()); + public void testPathBuilderArgumentsException() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + PathBuilder builder = new PathBuilder(0); + builder.append(new Edge()); + }); + assertTrue(exception.getMessage().equalsIgnoreCase("Path Builder expected Node but was Edge")); } } From 47e8b10043c212c74455351cf59726603d21a2e4 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 27 Feb 2022 01:57:09 +0600 Subject: [PATCH 116/128] bump snapshot version to 2.6.0 (#138) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2d73bbd..3125d73 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.redislabs jredisgraph - 2.5.1-SNAPSHOT + 2.6.0-SNAPSHOT JRedisGraph Official client for Redis-Graph From eba77cd4ba6227a08ed6f7bc451cfe3b3da4b048 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:32:41 +0600 Subject: [PATCH 117/128] Deprecate library (#140) --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c83d521..37c53d9 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ RedisGraph Java client +## Deprecation notice + +As of [Jedis](https://github.com/redis/jedis) version 4.2.0, this library is deprecated. Its features have been merged into Jedis. Please either install it from [maven](https://mvnrepository.com/artifact/redis.clients/jedis) or [the repo](https://github.com/redis/jedis). ### Official Releases From af2d2ef06f7f57f3b57c1bb09cf5bce8c2e68e94 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Wed, 27 Jul 2022 21:22:03 +0600 Subject: [PATCH 118/128] Bump Jedis to 3.9.0 (#142) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3125d73..254e98b 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ redis.clients jedis - 3.7.1 + 3.9.0 org.apache.commons From b24aa55aab199a9ee4fcd60bb2fc2210465576c4 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 7 Aug 2022 20:10:46 +0600 Subject: [PATCH 119/128] Cannot test params on empty graph anymore (#143) --- .../redisgraph/RedisGraphAPITest.java | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 5fdf54f..6fc132a 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -720,50 +720,6 @@ public void testPath() { } - @Test - public void testParameters() { - Object[] parameters = { 1, 2.3, true, false, null, "str", 'a', "b", Arrays.asList(1, 2, 3), - new Integer[] { 1, 2, 3 } }; - Object[] expected_anwsers = { 1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), - new Long[] { 1L, 2L, 3L } }; - Map params = new HashMap<>(); - for (int i = 0; i < parameters.length; i++) { - Object param = parameters[i]; - params.put("param", param); - ResultSet resultSet = client.query("social", "RETURN $param", params); - Assert.assertEquals(1, resultSet.size()); - Record r = resultSet.next(); - Object o = r.getValue(0); - Object expected = expected_anwsers[i]; - if (i == parameters.length - 1) { - expected = Arrays.asList((Object[]) expected); - } - Assert.assertEquals(expected, o); - } - } - - @Test - public void testParametersReadOnly() { - Object[] parameters = { 1, 2.3, true, false, null, "str", 'a', "b", Arrays.asList(1, 2, 3), - new Integer[] { 1, 2, 3 } }; - Object[] expected_anwsers = { 1L, 2.3, true, false, null, "str", "a", "b", Arrays.asList(1L, 2L, 3L), - new Long[] { 1L, 2L, 3L } }; - Map params = new HashMap<>(); - for (int i = 0; i < parameters.length; i++) { - Object param = parameters[i]; - params.put("param", param); - ResultSet resultSetRo = client.readOnlyQuery("social", "RETURN $param", params); - Assert.assertEquals(1, resultSetRo.size()); - Record rRo = resultSetRo.next(); - Object oRo = rRo.getValue(0); - Object expected = expected_anwsers[i]; - if (i == parameters.length - 1) { - expected = Arrays.asList((Object[]) expected); - } - Assert.assertEquals(expected, oRo); - } - } - @Test public void testNullGraphEntities() { // Create two nodes connected by a single outgoing edge. From 81302a1f28b1e2e75da42af4235fb781f6b7f083 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 11 Aug 2022 23:20:50 +0600 Subject: [PATCH 120/128] Pre-allocate the results size in Graph ResultSetBuilder (#144) --- .../impl/resultset/ResultSetImpl.java | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index 952b015..df77cdd 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -63,42 +63,43 @@ public ResultSetImpl(List rawResponse, RedisGraph redisGraph, GraphCache */ @SuppressWarnings("unchecked") private List parseResult(List> rawResultSet) { - List results = new ArrayList<>(); if (rawResultSet == null || rawResultSet.isEmpty()) { - return results; - } else { - // go over each raw result - for (List row : rawResultSet) { - - List parsedRow = new ArrayList<>(row.size()); - // go over each object in the result - for (int i = 0; i < row.size(); i++) { - // get raw representation of the object - List obj = (List) row.get(i); - // get object type - Header.ResultSetColumnTypes objType = header.getSchemaTypes().get(i); - // deserialize according to type and - switch (objType) { - case COLUMN_NODE: - parsedRow.add(deserializeNode(obj)); - break; - case COLUMN_RELATION: - parsedRow.add(deserializeEdge(obj)); - break; - case COLUMN_SCALAR: - parsedRow.add(deserializeScalar(obj)); - break; - default: - parsedRow.add(null); - break; - } + return new ArrayList<>(0); + } + List results = new ArrayList<>(rawResultSet.size()); + // go over each raw result + for (List row : rawResultSet) { + + List parsedRow = new ArrayList<>(row.size()); + // go over each object in the result + for (int i = 0; i < row.size(); i++) { + // get raw representation of the object + List obj = (List) row.get(i); + // get object type + Header.ResultSetColumnTypes objType = header.getSchemaTypes().get(i); + // deserialize according to type and + switch (objType) { + case COLUMN_NODE: + parsedRow.add(deserializeNode(obj)); + break; + case COLUMN_RELATION: + parsedRow.add(deserializeEdge(obj)); + break; + case COLUMN_SCALAR: + parsedRow.add(deserializeScalar(obj)); + break; + default: + parsedRow.add(null); + break; } - // create new record from deserialized objects - Record record = new RecordImpl(header.getSchemaNames(), parsedRow); - results.add(record); } + + // create new record from deserialized objects + Record record = new RecordImpl(header.getSchemaNames(), parsedRow); + results.add(record); } + return results; } From c1297f79d8f42790442a367b6076518ec4f71131 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 14 Aug 2022 13:47:46 +0600 Subject: [PATCH 121/128] Optimize Entities capacity to avoid reallocation (#145) * Optimize Entities capacity to avoid reallocation --- .../redisgraph/graph_entities/Edge.java | 13 ++++++- .../graph_entities/GraphEntity.java | 14 +++++++- .../redisgraph/graph_entities/Node.java | 19 ++++++++++- .../impl/resultset/ResultSetImpl.java | 34 ++++++++++++------- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java index 6eebdf8..b36db16 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Edge.java @@ -9,11 +9,22 @@ public class Edge extends GraphEntity { //members - private String relationshipType; + private String relationshipType; private long source; private long destination; + public Edge() { + super(); + } + /** + * Use this constructor to reduce memory allocations + * when properties are added to the edge + * @param propertiesCapacity preallocate the capacity for the properties + */ + public Edge(int propertiesCapacity) { + super(propertiesCapacity); + } //getters & setters /** diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java index e86e302..2919747 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/GraphEntity.java @@ -10,8 +10,20 @@ public abstract class GraphEntity { //members protected long id; - protected final Map> propertyMap = new HashMap<>(); + protected final Map> propertyMap; + public GraphEntity() { + propertyMap = new HashMap<>(); + } + + /** + * Use this constructor to reduce memory allocations + * when properties are added to the edge + * @param propertiesCapacity preallocate the capacity for the properties + */ + public GraphEntity(int propertiesCapacity) { + propertyMap = new HashMap<>(propertiesCapacity); + } //setters & getters diff --git a/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java b/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java index 91b9a4f..3185b43 100644 --- a/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java +++ b/src/main/java/com/redislabs/redisgraph/graph_entities/Node.java @@ -10,7 +10,24 @@ public class Node extends GraphEntity { //members - private final List labels = new ArrayList<>(); + private final List labels; + + public Node() { + super(); + labels = new ArrayList<>(); + } + + /** + * Use this constructor to reduce memory allocations + * when labels or properties are added to the node + * @param labelsCapacity preallocate the capacity for the node labels + * @param propertiesCapacity preallocate the capacity for the properties + */ + public Node(int labelsCapacity, int propertiesCapacity) { + super(propertiesCapacity); + this.labels = new ArrayList<>(labelsCapacity); + } + /** * @param label - a label to be add diff --git a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java index df77cdd..62a9e2f 100644 --- a/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java +++ b/src/main/java/com/redislabs/redisgraph/impl/resultset/ResultSetImpl.java @@ -140,26 +140,28 @@ public Header getHeader() { */ @SuppressWarnings("unchecked") private Node deserializeNode(List rawNodeData) { - Node node = new Node(); - deserializeGraphEntityId(node, rawNodeData.get(0)); + List labelsIndices = (List) rawNodeData.get(1); + List> rawProperties = (List>) rawNodeData.get(2); + + Node node = new Node(labelsIndices.size(), rawProperties.size()); + deserializeGraphEntityId(node, (Long) rawNodeData.get(0)); + for (Long labelIndex : labelsIndices) { String label = cache.getLabel(labelIndex.intValue(), redisGraph); node.addLabel(label); } - deserializeGraphEntityProperties(node, (List>) rawNodeData.get(2)); - return node; + deserializeGraphEntityProperties(node, rawProperties); + return node; } /** * @param graphEntity graph entity - * @param rawEntityId raw representation of entity id to be set to the graph - * entity + * @param id entity id to be set to the graph entity */ - private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityId) { - long id = (Long) rawEntityId; + private void deserializeGraphEntityId(GraphEntity graphEntity, long id) { graphEntity.setId(id); } @@ -172,8 +174,11 @@ private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityI */ @SuppressWarnings("unchecked") private Edge deserializeEdge(List rawEdgeData) { - Edge edge = new Edge(); - deserializeGraphEntityId(edge, rawEdgeData.get(0)); + + List> rawProperties = (List>) rawEdgeData.get(4); + + Edge edge = new Edge(rawProperties.size()); + deserializeGraphEntityId(edge, (Long) rawEdgeData.get(0)); String relationshipType = cache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue(), redisGraph); edge.setRelationshipType(relationshipType); @@ -181,7 +186,7 @@ private Edge deserializeEdge(List rawEdgeData) { edge.setSource((long) rawEdgeData.get(2)); edge.setDestination((long) rawEdgeData.get(3)); - deserializeGraphEntityProperties(edge, (List>) rawEdgeData.get(4)); + deserializeGraphEntityProperties(edge, rawProperties); return edge; } @@ -256,8 +261,11 @@ private Object deserializePoint(Object rawScalarData) { @SuppressWarnings("unchecked") private Map deserializeMap(Object rawScalarData) { List keyTypeValueEntries = (List) rawScalarData; - Map map = new HashMap<>(); - for (int i = 0; i < keyTypeValueEntries.size(); i += 2) { + + int size = keyTypeValueEntries.size(); + Map map = new HashMap<>(size >> 1); // set the capacity to half of the list + + for (int i = 0; i < size; i += 2) { String key = SafeEncoder.encode((byte[]) keyTypeValueEntries.get(i)); Object value = deserializeScalar((List) keyTypeValueEntries.get(i + 1)); map.put(key, value); From d1ee2fe7c7cf2841dfac44edd8ce99672e85707c Mon Sep 17 00:00:00 2001 From: Avi Avni Date: Thu, 24 Nov 2022 11:56:50 +0200 Subject: [PATCH 122/128] fix error message --- .../exceptions/JRedisGraphErrorTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index a504d4d..bd61ded 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -35,14 +35,14 @@ public void deleteGraph() { public void testSyntaxErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> api.query("social", "RETURN toUpper(5)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } @Test public void testRuntimeErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } @Test @@ -53,7 +53,7 @@ public void testExceptionFlow() { api.query("social", "RETURN toUpper(5)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } // On general api usage, user should get a new connection @@ -63,7 +63,7 @@ public void testExceptionFlow() { api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } } @@ -73,7 +73,7 @@ public void testContextSyntaxErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> c.query("social", "RETURN toUpper(5)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } @Test @@ -96,7 +96,7 @@ public void testContextRuntimeErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected String but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } @Test @@ -108,7 +108,7 @@ public void testContextExceptionFlow() { c.query("social", "RETURN toUpper(5)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } // On contexted api usage, connection should stay open @@ -117,7 +117,7 @@ public void testContextExceptionFlow() { c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); } } From b497f097710bd9afd4a1348b70cb5ab50088c614 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Wed, 30 Nov 2022 11:39:50 +0600 Subject: [PATCH 123/128] Test: Address error message changes (#156) --- .../exceptions/JRedisGraphErrorTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java index bd61ded..f29bdaa 100644 --- a/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java +++ b/src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java @@ -42,7 +42,7 @@ public void testSyntaxErrorReporting() { public void testRuntimeErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } @Test @@ -53,7 +53,7 @@ public void testExceptionFlow() { api.query("social", "RETURN toUpper(5)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } // On general api usage, user should get a new connection @@ -63,7 +63,7 @@ public void testExceptionFlow() { api.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } } @@ -73,7 +73,7 @@ public void testContextSyntaxErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> c.query("social", "RETURN toUpper(5)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } @Test @@ -96,7 +96,7 @@ public void testContextRuntimeErrorReporting() { JRedisGraphException exception = assertThrows(JRedisGraphException.class, () -> c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)")); - assertTrue(exception.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + assertTrue(exception.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } @Test @@ -108,7 +108,7 @@ public void testContextExceptionFlow() { c.query("social", "RETURN toUpper(5)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } // On contexted api usage, connection should stay open @@ -117,7 +117,7 @@ public void testContextExceptionFlow() { c.query("social", "MATCH (p:person) RETURN toUpper(p.mixed_prop)"); } catch (Exception e) { Assert.assertEquals(JRedisGraphException.class, e.getClass()); - Assert.assertTrue(e.getMessage().contains("Type mismatch: expected Stringor Null but was Integer")); + Assert.assertTrue(e.getMessage().contains("Type mismatch: expected String or Null but was Integer")); } } From fb910c16c17122469f7fe20cb745c7ae876b8e8a Mon Sep 17 00:00:00 2001 From: Chayim Date: Wed, 30 Nov 2022 08:01:34 +0200 Subject: [PATCH 124/128] fix: pom.xml to reduce vulnerabilities (#150) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHECOMMONS-3043138 Co-authored-by: snyk-bot Co-authored-by: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 254e98b..fd096c0 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ org.apache.commons commons-text - 1.9 + 1.10.0 junit From 3d1cf43f3d3662106b8bd50dec2686311a770ad3 Mon Sep 17 00:00:00 2001 From: "lgtm-com[bot]" <43144390+lgtm-com[bot]@users.noreply.github.com> Date: Wed, 7 Dec 2022 14:37:21 +0600 Subject: [PATCH 125/128] Add CodeQL workflow for GitHub code scanning (#152) Co-authored-by: LGTM Migrator Co-authored-by: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> --- .github/workflows/codeql.yml | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..bf5c325 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,41 @@ +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: "56 20 * * 3" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ java ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" From 7834b9b94767dff1c0d1c08503b611f186232cd1 Mon Sep 17 00:00:00 2001 From: Chayim Date: Wed, 7 Dec 2022 10:38:52 +0200 Subject: [PATCH 126/128] Removing LGTM as the service is going offline shortly (#155) Co-authored-by: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 37c53d9..6969575 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph) [![Javadocs](https://www.javadoc.io/badge/com.redislabs/jredisgraph.svg)](https://www.javadoc.io/doc/com.redislabs/jredisgraph) [![Codecov](https://codecov.io/gh/RedisGraph/JRedisGraph/branch/master/graph/badge.svg)](https://codecov.io/gh/RedisGraph/JRedisGraph) -[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/RedisGraph/JRedisGraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/RedisGraph/JRedisGraph/context:java) [![Known Vulnerabilities](https://snyk.io/test/github/RedisGraph/JRedisGraph/badge.svg?targetFile=pom.xml)](https://snyk.io/test/github/RedisGraph/JRedisGraph?targetFile=pom.xml) # JRedisGraph @@ -70,7 +69,7 @@ public class RedisGraphExample { Map params = new HashMap<>(); params.put("age", 30); params.put("name", "amit"); - + // send queries to a specific graph called "social" graph.query("social","CREATE (:person{name:'roi',age:32})"); graph.query("social","CREATE (:person{name:$name,age:$age})", params); From 777898c7def7e18b7cec82aa6011d2d18e1603b3 Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Thu, 8 Dec 2022 10:35:30 +0200 Subject: [PATCH 127/128] removing circle and ensuring we redirect to active libraries --- .circleci/config.yml | 77 -------------------------------------------- README.md | 1 - 2 files changed, 78 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index bc119f3..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,77 +0,0 @@ -# Java Maven CircleCI 2.0 configuration file -# -# Check https://circleci.com/docs/2.0/language-java/ for more details -# -version: 2.1 -commands: - early_return_for_forked_pull_requests: - description: >- - If this build is from a fork, stop executing the current job and return success. - This is useful to avoid steps that will fail due to missing credentials. - steps: - - run: - name: Early return if this build is from a forked PR - command: | - if [ -n "$CIRCLE_PR_NUMBER" ]; then - echo "Nothing to do for forked PRs, so marking this step successful" - circleci step halt - fi -jobs: - build: - docker: - - image: circleci/openjdk:8u171-jdk - - image: redislabs/redisgraph:edge - working_directory: ~/repo - - environment: - # Customize the JVM maximum heap limit - MAVEN_OPTS: -Xmx3200m - - steps: - - - checkout - - # Download and cache dependencies - - restore_cache: - keys: - - v1-dependencies-{{ checksum "pom.xml" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - - run: mvn dependency:go-offline - - - save_cache: - paths: - - ~/.m2 - key: v1-dependencies-{{ checksum "pom.xml" }} - - # run tests! - # - run: mvn pmd:check - - - run: mvn integration-test - - - early_return_for_forked_pull_requests - - - run: bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -t ${CODECOV_TOKEN} - - - run: mvn -s .circleci.settings.xml -DskipTests deploy - -workflows: - version: 2 - commit: - jobs: - - build: - context: - - common - nightly: - triggers: - - schedule: - cron: "0 0 * * *" - filters: - branches: - only: - - master - jobs: - - build: - context: - - common diff --git a/README.md b/README.md index 6969575..5b492ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ [![license](https://img.shields.io/github/license/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph/blob/master/LICENSE) [![GitHub issues](https://img.shields.io/github/release/RedisGraph/JRedisGraph.svg)](https://github.com/RedisGraph/JRedisGraph/releases/latest) -[![CircleCI](https://circleci.com/gh/RedisGraph/JRedisGraph/tree/master.svg?style=svg)](https://circleci.com/gh/RedisGraph/JRedisGraph/tree/master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.redislabs/jredisgraph) [![Javadocs](https://www.javadoc.io/badge/com.redislabs/jredisgraph.svg)](https://www.javadoc.io/doc/com.redislabs/jredisgraph) [![Codecov](https://codecov.io/gh/RedisGraph/JRedisGraph/branch/master/graph/badge.svg)](https://codecov.io/gh/RedisGraph/JRedisGraph) From 92ce65875233bb486ded8ddf73d53dbed329ef35 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Mon, 27 Nov 2023 13:57:56 +0200 Subject: [PATCH 128/128] Create dependabot.yml --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ac6621f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly"