From f3a3c35e7453157bbbc430b2835fda7b0ac28544 Mon Sep 17 00:00:00 2001 From: Jermy Li Date: Mon, 3 Jun 2019 21:41:28 -0500 Subject: [PATCH] support negative number for index (#513) Change-Id: I7067cfb0a663e89ae4305425edf00e6a2a03587c implement: #311 --- .../backend/serializer/BinarySerializer.java | 6 +- .../store/memory/InMemoryDBTables.java | 80 +-- .../baidu/hugegraph/type/define/DataType.java | 10 +- .../backend/store/hbase/HbaseTables.java | 62 -- .../backend/store/mysql/MysqlTable.java | 32 +- .../backend/store/mysql/MysqlTables.java | 4 +- .../store/postgresql/PostgresqlTables.java | 18 +- .../baidu/hugegraph/core/EdgeCoreTest.java | 166 ++++- .../baidu/hugegraph/core/VertexCoreTest.java | 669 +++++++++++++++--- 9 files changed, 768 insertions(+), 279 deletions(-) diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/serializer/BinarySerializer.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/serializer/BinarySerializer.java index 37b6ac8fae..559cb984a1 100644 --- a/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/serializer/BinarySerializer.java +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/serializer/BinarySerializer.java @@ -66,8 +66,8 @@ import com.baidu.hugegraph.util.E; import com.baidu.hugegraph.util.JsonUtil; import com.baidu.hugegraph.util.KryoUtil; +import com.baidu.hugegraph.util.NumericUtil; import com.baidu.hugegraph.util.StringEncoding; -import com.baidu.hugegraph.util.StringUtil; public class BinarySerializer extends AbstractSerializer { @@ -710,8 +710,8 @@ private Query writeRangeIndexQuery(ConditionQuery query) { if (keyMin == null) { E.checkArgument(keyMax != null, "Please specify at least one condition"); - // Set keyMin to 0 - keyMin = StringUtil.valueOf(keyMax.getClass(), "0"); + // Set keyMin to min value + keyMin = NumericUtil.minValueOf(keyMax.getClass()); keyMinEq = true; } diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/store/memory/InMemoryDBTables.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/store/memory/InMemoryDBTables.java index aa314a2375..efbfa7c6ae 100644 --- a/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/store/memory/InMemoryDBTables.java +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/store/memory/InMemoryDBTables.java @@ -50,6 +50,7 @@ import com.baidu.hugegraph.type.define.HugeKeys; import com.baidu.hugegraph.util.E; import com.baidu.hugegraph.util.InsertionOrderUtil; +import com.baidu.hugegraph.util.NumericUtil; import com.google.common.collect.ImmutableList; public class InMemoryDBTables { @@ -484,70 +485,10 @@ public Iterator query(BackendSession session, q.offset(query.offset()); q.limit(query.limit()); return super.query(session, q); - } else { - if (keyMin == null) { - // Field value < keyMax - assert keyMax != null; - return this.ltQuery(indexLabelId, keyMax, keyMaxEq); - } else { - if (keyMax == null) { - // Field value > keyMin - return this.gtQuery(indexLabelId, keyMin, keyMinEq); - } else { - // keyMin <(=) field value <(=) keyMax - return this.betweenQuery(indexLabelId, - keyMax, keyMaxEq, - keyMin, keyMinEq); - } - } - } - } - - private Iterator ltQuery(Id indexLabelId, - Object keyMax, - boolean keyMaxEq) { - NavigableMap rs = this.store(); - Map results = new HashMap<>(); - - Id min = HugeIndex.formatIndexId(HugeType.RANGE_INDEX, - indexLabelId, 0L); - Id max = HugeIndex.formatIndexId(HugeType.RANGE_INDEX, - indexLabelId, keyMax); - Map.Entry entry = keyMaxEq ? - rs.floorEntry(max) : - rs.lowerEntry(max); - while (entry != null) { - if (entry.getKey().compareTo(min) < 0) { - break; - } - results.put(entry.getKey(), entry.getValue()); - entry = rs.lowerEntry(entry.getKey()); } - return results.values().iterator(); - } - - private Iterator gtQuery(Id indexLabelId, - Object keyMin, - boolean keyMinEq) { - NavigableMap rs = this.store(); - Map results = new HashMap<>(); - - Id min = HugeIndex.formatIndexId(HugeType.RANGE_INDEX, - indexLabelId, keyMin); - indexLabelId = IdGenerator.of(indexLabelId.asLong() + 1L); - Id max = HugeIndex.formatIndexId(HugeType.RANGE_INDEX, - indexLabelId, 0L); - Map.Entry entry = keyMinEq ? - rs.ceilingEntry(min) : - rs.higherEntry(min); - while (entry != null) { - if (entry.getKey().compareTo(max) >= 0) { - break; - } - results.put(entry.getKey(), entry.getValue()); - entry = rs.higherEntry(entry.getKey()); - } - return results.values().iterator(); + // keyMin <(=) field value <(=) keyMax + return this.betweenQuery(indexLabelId, keyMax, keyMaxEq, + keyMin, keyMinEq); } private Iterator betweenQuery(Id indexLabelId, @@ -557,8 +498,21 @@ private Iterator betweenQuery(Id indexLabelId, boolean keyMinEq) { NavigableMap rs = this.store(); + E.checkArgument(keyMin != null || keyMax != null, + "Please specify at least one condition"); + if (keyMin == null) { + // Field value < keyMax + keyMin = NumericUtil.minValueOf(keyMax.getClass()); + } Id min = HugeIndex.formatIndexId(HugeType.RANGE_INDEX, indexLabelId, keyMin); + + if (keyMax == null) { + // Field value > keyMin + keyMaxEq = false; + indexLabelId = IdGenerator.of(indexLabelId.asLong() + 1L); + keyMax = NumericUtil.minValueOf(keyMin.getClass()); + } Id max = HugeIndex.formatIndexId(HugeType.RANGE_INDEX, indexLabelId, keyMax); diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java index c69e7c042a..dc1b51092b 100644 --- a/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java @@ -106,10 +106,16 @@ public Number valueToNumber(V value) { number = Long.valueOf(value.toString()); break; case FLOAT: - number = Float.valueOf(value.toString()); + Float fvalue = Float.valueOf(value.toString()); + if (!fvalue.isInfinite() && !fvalue.isNaN()) { + number = fvalue; + } break; case DOUBLE: - number = Double.valueOf(value.toString()); + Double dvalue = Double.valueOf(value.toString()); + if (!dvalue.isInfinite() && !dvalue.isNaN()) { + number = dvalue; + } break; default: throw new AssertionError(String.format( diff --git a/hugegraph-hbase/src/main/java/com/baidu/hugegraph/backend/store/hbase/HbaseTables.java b/hugegraph-hbase/src/main/java/com/baidu/hugegraph/backend/store/hbase/HbaseTables.java index 4bfe758276..52a11df2ce 100644 --- a/hugegraph-hbase/src/main/java/com/baidu/hugegraph/backend/store/hbase/HbaseTables.java +++ b/hugegraph-hbase/src/main/java/com/baidu/hugegraph/backend/store/hbase/HbaseTables.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.Arrays; -import java.util.List; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellScanner; @@ -29,10 +28,6 @@ import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.util.Bytes; -import com.baidu.hugegraph.backend.id.Id; -import com.baidu.hugegraph.backend.query.Condition; -import com.baidu.hugegraph.backend.query.Condition.Relation; -import com.baidu.hugegraph.backend.query.ConditionQuery; import com.baidu.hugegraph.backend.query.Query; import com.baidu.hugegraph.backend.serializer.BinaryBackendEntry; import com.baidu.hugegraph.backend.serializer.BinaryEntryIterator; @@ -43,7 +38,6 @@ import com.baidu.hugegraph.backend.store.hbase.HbaseSessions.RowIterator; import com.baidu.hugegraph.backend.store.hbase.HbaseSessions.Session; import com.baidu.hugegraph.type.HugeType; -import com.baidu.hugegraph.type.define.HugeKeys; import com.baidu.hugegraph.util.E; import com.baidu.hugegraph.util.NumericUtil; @@ -258,61 +252,5 @@ public static class RangeIndex extends IndexTable { public RangeIndex(String store) { super(joinTableName(store, TABLE)); } - - @Override - protected RowIterator queryByCond(Session session, - ConditionQuery query) { - assert !query.conditions().isEmpty(); - - List conds = query.syspropConditions(HugeKeys.ID); - E.checkArgument(!conds.isEmpty(), - "Please specify the index conditions"); - - Id prefix = null; - Id min = null; - boolean minEq = false; - Id max = null; - boolean maxEq = false; - - for (Condition c : conds) { - Relation r = (Relation) c; - switch (r.relation()) { - case PREFIX: - prefix = (Id) r.value(); - break; - case GTE: - minEq = true; - case GT: - min = (Id) r.value(); - break; - case LTE: - maxEq = true; - case LT: - max = (Id) r.value(); - break; - default: - E.checkArgument(false, "Unsupported relation '%s'", - r.relation()); - } - } - - E.checkArgumentNotNull(min, "Range index begin key is missing"); - byte[] begin = min.asBytes(); - if (max == null) { - E.checkArgumentNotNull(prefix, "Range index prefix is missing"); - byte[] prefixFilter = prefix.asBytes(); - return session.scan(this.table(), begin, minEq, prefixFilter); - } else { - byte[] end = max.asBytes(); - if (maxEq) { - // The parameter stoprow-inclusive doesn't work before v2.0 - // https://issues.apache.org/jira/browse/HBASE-20675 - maxEq = false; - // Add a trailing 0 byte to stopRow - end = Arrays.copyOfRange(end, 0, end.length + 1); - } - return session.scan(this.table(), begin, minEq, end, maxEq); - } - } } } diff --git a/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTable.java b/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTable.java index 2686308812..d603ce250f 100644 --- a/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTable.java +++ b/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTable.java @@ -19,6 +19,7 @@ package com.baidu.hugegraph.backend.store.mysql; +import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -52,6 +53,8 @@ public abstract class MysqlTable private static final Logger LOG = Log.logger(MysqlStore.class); + private static final String DECIMAL = "DECIMAL"; + // The template for insert and delete statements private String insertTemplate; private String deleteTemplate; @@ -206,6 +209,10 @@ protected String buildTruncateTemplate() { return String.format("TRUNCATE TABLE %s;", this.table()); } + protected void appendPartition(StringBuilder sb) { + // pass + } + /** * Insert an entire row */ @@ -228,6 +235,19 @@ public void insert(Session session, MysqlBackendEntry.Row entry) { session.add(insertStmt); } + protected List buildInsertObjects(MysqlBackendEntry.Row entry) { + List objects = new ArrayList<>(); + for (Map.Entry e : entry.columns().entrySet()) { + Object value = e.getValue(); + String type = this.tableDefine().columns().get(e.getKey()); + if (type.startsWith(DECIMAL)) { + value = new BigDecimal(value.toString()); + } + objects.add(value); + } + return objects; + } + @Override public void delete(Session session, MysqlBackendEntry.Row entry) { List idNames = this.idColumnName(); @@ -546,18 +566,6 @@ protected BackendEntry mergeEntries(BackendEntry e1, BackendEntry e2) { return e2; } - protected void appendPartition(StringBuilder delete) { - // pass - } - - protected List buildInsertObjects(MysqlBackendEntry.Row entry) { - List objects = new ArrayList<>(); - for (Object key : entry.columns().keySet()) { - objects.add(entry.columns().get(key)); - } - return objects; - } - public static String formatKey(HugeKeys key) { return key.name(); } diff --git a/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTables.java b/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTables.java index faf083a0c4..2591977001 100644 --- a/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTables.java +++ b/hugegraph-mysql/src/main/java/com/baidu/hugegraph/backend/store/mysql/MysqlTables.java @@ -48,7 +48,7 @@ public class MysqlTables { public static final String BOOLEAN = "BOOLEAN"; public static final String TINYINT = "TINYINT"; public static final String INT = "INT"; - public static final String DOUBLE = "DOUBLE"; + public static final String NUMERIC = "DOUBLE"; public static final String SMALL_TEXT = "SMALL_TEXT"; public static final String MID_TEXT = "MID_TEXT"; public static final String LARGE_TEXT = "LARGE_TEXT"; @@ -452,7 +452,7 @@ public RangeIndex(String store, Map typesMapping) { this.define = new TableDefine(typesMapping); this.define.column(HugeKeys.INDEX_LABEL_ID, DATATYPE_IL); - this.define.column(HugeKeys.FIELD_VALUES, DOUBLE); + this.define.column(HugeKeys.FIELD_VALUES, NUMERIC); this.define.column(HugeKeys.ELEMENT_IDS, SMALL_TEXT); this.define.keys(HugeKeys.INDEX_LABEL_ID, HugeKeys.FIELD_VALUES, diff --git a/hugegraph-postgresql/src/main/java/com/baidu/hugegraph/backend/store/postgresql/PostgresqlTables.java b/hugegraph-postgresql/src/main/java/com/baidu/hugegraph/backend/store/postgresql/PostgresqlTables.java index b8514c330e..ed4d3415da 100644 --- a/hugegraph-postgresql/src/main/java/com/baidu/hugegraph/backend/store/postgresql/PostgresqlTables.java +++ b/hugegraph-postgresql/src/main/java/com/baidu/hugegraph/backend/store/postgresql/PostgresqlTables.java @@ -19,6 +19,14 @@ package com.baidu.hugegraph.backend.store.postgresql; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.BOOLEAN; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.INT; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.LARGE_TEXT; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.MID_TEXT; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.NUMERIC; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.SMALL_TEXT; +import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.TINYINT; + import java.sql.SQLException; import java.util.List; import java.util.Map; @@ -37,14 +45,6 @@ import jersey.repackaged.com.google.common.collect.ImmutableMap; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.BOOLEAN; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.DOUBLE; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.INT; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.LARGE_TEXT; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.MID_TEXT; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.SMALL_TEXT; -import static com.baidu.hugegraph.backend.store.mysql.MysqlTables.TINYINT; - public class PostgresqlTables { private static final Map TYPES_MAPPING = @@ -52,7 +52,7 @@ public class PostgresqlTables { .put(BOOLEAN, "BOOL") .put(TINYINT, "INT") .put(INT, "INT") - .put(DOUBLE, "FLOAT") + .put(NUMERIC, "DECIMAL") .put(SMALL_TEXT, "VARCHAR(255)") .put(MID_TEXT, "VARCHAR(1024)") .put(LARGE_TEXT, "VARCHAR(65533)") diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java index 66db5ba9fb..8e761cc1e5 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java @@ -44,6 +44,7 @@ import com.baidu.hugegraph.HugeGraph; import com.baidu.hugegraph.backend.BackendException; import com.baidu.hugegraph.backend.id.Id; +import com.baidu.hugegraph.backend.id.IdGenerator; import com.baidu.hugegraph.backend.page.PageInfo; import com.baidu.hugegraph.backend.query.ConditionQuery; import com.baidu.hugegraph.backend.query.Query; @@ -171,15 +172,6 @@ public void initSchema() { .ifNotExist().create(); } - protected void initTransferIndex() { - SchemaManager schema = graph().schema(); - - LOG.debug("=============== transfer index ================"); - - schema.indexLabel("transferByTimestamp").onE("transfer").range() - .by("timestamp").create(); - } - protected void initStrikeIndex() { SchemaManager schema = graph().schema(); @@ -1262,19 +1254,19 @@ public void testQueryInEdgesOfVertexByLabelAndFilter() { Vertex java3 = vertex("book", "name", "java-3"); List edges = graph.traversal().V(java3.id()) - .inE().has("score", 3).toList(); + .inE().has("score", 3).toList(); Assert.assertEquals(3, edges.size()); edges = graph.traversal().V(java3.id()) - .inE("look").has("score", 3).toList(); + .inE("look").has("score", 3).toList(); Assert.assertEquals(2, edges.size()); edges = graph.traversal().V(java3.id()) - .inE("look").has("score", 4).toList(); + .inE("look").has("score", 4).toList(); Assert.assertEquals(1, edges.size()); edges = graph.traversal().V(java3.id()) - .inE("look").has("score", 0).toList(); + .inE("look").has("score", 0).toList(); Assert.assertEquals(1, edges.size()); } @@ -1286,11 +1278,11 @@ public void testQueryInEdgesOfVertexBySortkey() { Vertex java3 = vertex("book", "name", "java-3"); List edges = graph.traversal().V(java3.id()) - .inE("look").toList(); + .inE("look").toList(); Assert.assertEquals(4, edges.size()); edges = graph.traversal().V(java3.id()) - .inE("look").has("time", "2017-5-27").toList(); + .inE("look").has("time", "2017-5-27").toList(); Assert.assertEquals(3, edges.size()); } @@ -1302,7 +1294,7 @@ public void testQueryInVerticesOfVertex() { Vertex java3 = vertex("book", "name", "java-3"); List vertices = graph.traversal().V(java3.id()) - .in("look").toList(); + .in("look").toList(); Assert.assertEquals(4, vertices.size()); } @@ -1315,15 +1307,15 @@ public void testQueryInVerticesOfVertexAndFilter() { // NOTE: the has() just filter by vertex props List vertices = graph.traversal().V(java3.id()) - .in("look").has("age", P.gt(22)) - .toList(); + .in("look").has("age", P.gt(22)) + .toList(); Assert.assertEquals(2, vertices.size()); } @Test public void testQueryByLongPropOfOverrideEdge() { HugeGraph graph = graph(); - initTransferIndex(); + initStrikeIndex(); Vertex louise = graph.addVertex(T.label, "person", "name", "Louise", "city", "Beijing", "age", 21); @@ -1345,26 +1337,112 @@ public void testQueryByLongPropOfOverrideEdge() { } @Test - public void testQueryByStringPropOfOverrideEdge() { + public void testQueryByNegativeLongProperty() { HugeGraph graph = graph(); - initStrikeIndex(); + SchemaManager schema = graph.schema(); + + schema.indexLabel("transferByTimestamp").onE("transfer").range() + .by("timestamp").create(); Vertex louise = graph.addVertex(T.label, "person", "name", "Louise", "city", "Beijing", "age", 21); Vertex sean = graph.addVertex(T.label, "person", "name", "Sean", "city", "Beijing", "age", 23); - long current = System.currentTimeMillis(); - louise.addEdge("strike", sean, "id", 1, "timestamp", current, - "place", "park", "tool", "shovel", "reason", "jeer", - "arrested", false); - louise.addEdge("strike", sean, "id", 1, "timestamp", current, - "place", "street", "tool", "shovel", "reason", "jeer", - "arrested", false); - List edges = graph.traversal().E().has("place", "park") - .toList(); + louise.addEdge("transfer", sean, "id", 1, + "amount", 500.00F, "timestamp", 1L, + "message", "Happy birthday!"); + louise.addEdge("transfer", sean, "id", 2, + "amount", -1234.56F, "timestamp", -100L, + "message", "Happy birthday!"); + + graph.tx().commit(); + + List edges = graph.traversal().E() + .has("timestamp", -100L).toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(2), edges.get(0).value("id")); + + edges = graph.traversal().E() + .has("timestamp", P.between(-101L, 0L)) + .toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(2), edges.get(0).value("id")); + + edges = graph.traversal().E().has("timestamp", P.gt(-101L)).toList(); + Assert.assertEquals(2, edges.size()); + + edges = graph.traversal().E().has("timestamp", P.gte(-100L)).toList(); + Assert.assertEquals(2, edges.size()); + + edges = graph.traversal().E().has("timestamp", P.gt(-100L)).toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(1), edges.get(0).value("id")); + + edges = graph.traversal().E().has("timestamp", P.gt(-99L)).toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(1), edges.get(0).value("id")); + + edges = graph.traversal().E().has("timestamp", P.lt(-100L)).toList(); Assert.assertEquals(0, edges.size()); - edges = graph.traversal().E().has("place", "street").toList(); + edges = graph.traversal().E().has("timestamp", P.lte(-100L)).toList(); + Assert.assertEquals(1, edges.size()); + edges = graph.traversal().E().has("timestamp", P.lt(0L)).toList(); + Assert.assertEquals(1, edges.size()); + } + + @Test + public void testQueryByNegativeFloatProperty() { + HugeGraph graph = graph(); + SchemaManager schema = graph.schema(); + + schema.indexLabel("transferByAmount").onE("transfer").range() + .by("amount").create(); + + Vertex louise = graph.addVertex(T.label, "person", "name", "Louise", + "city", "Beijing", "age", 21); + Vertex sean = graph.addVertex(T.label, "person", "name", "Sean", + "city", "Beijing", "age", 23); + + louise.addEdge("transfer", sean, "id", 1, + "amount", 500.00F, "timestamp", 1L, + "message", "Happy birthday!"); + louise.addEdge("transfer", sean, "id", 2, + "amount", -1234.56F, "timestamp", -100L, + "message", "Happy birthday!"); + + graph.tx().commit(); + + List edges = graph.traversal().E() + .has("amount", -1234.56F).toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(2), edges.get(0).value("id")); + + edges = graph.traversal().E() + .has("amount", P.between(-1235F, 0L)) + .toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(2), edges.get(0).value("id")); + + edges = graph.traversal().E().has("amount", P.gt(-1235F)).toList(); + Assert.assertEquals(2, edges.size()); + + edges = graph.traversal().E().has("amount", P.gte(-1234.56F)).toList(); + Assert.assertEquals(2, edges.size()); + + edges = graph.traversal().E().has("amount", P.gt(-1234.56F)).toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(1), edges.get(0).value("id")); + + edges = graph.traversal().E().has("amount", P.gt(-1234.56F)).toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(IdGenerator.of(1), edges.get(0).value("id")); + + edges = graph.traversal().E().has("amount", P.lt(-1234.56F)).toList(); + Assert.assertEquals(0, edges.size()); + edges = graph.traversal().E().has("amount", P.lte(-1234.56F)).toList(); + Assert.assertEquals(1, edges.size()); + edges = graph.traversal().E().has("amount", P.lt(0F)).toList(); Assert.assertEquals(1, edges.size()); } @@ -2398,6 +2476,30 @@ public void testQueryEdgeByPropertyWithEmptyString() { Assert.assertEquals(1, (int) edge.value("id")); } + @Test + public void testQueryEdgeByStringPropOfOverrideEdge() { + HugeGraph graph = graph(); + initStrikeIndex(); + + Vertex louise = graph.addVertex(T.label, "person", "name", "Louise", + "city", "Beijing", "age", 21); + Vertex sean = graph.addVertex(T.label, "person", "name", "Sean", + "city", "Beijing", "age", 23); + + long current = System.currentTimeMillis(); + louise.addEdge("strike", sean, "id", 1, "timestamp", current, + "place", "park", "tool", "shovel", "reason", "jeer", + "arrested", false); + louise.addEdge("strike", sean, "id", 1, "timestamp", current, + "place", "street", "tool", "shovel", "reason", "jeer", + "arrested", false); + List edges = graph.traversal().E().has("place", "park") + .toList(); + Assert.assertEquals(0, edges.size()); + edges = graph.traversal().E().has("place", "street").toList(); + Assert.assertEquals(1, edges.size()); + } + @Test public void testQueryEdgeBeforeAfterUpdateMultiPropertyWithIndex() { HugeGraph graph = graph(); @@ -2520,7 +2622,7 @@ public void testQueryEdgeWithNullablePropertyInCompositeIndex() { Assert.assertEquals(1, el.size()); Assert.assertEquals(1, (int) el.get(0).value("id")); el = graph.traversal().E().has("place", "park") - .has("tool", "shovel").toList(); + .has("tool", "shovel").toList(); Assert.assertEquals(1, el.size()); Assert.assertEquals(1, (int) el.get(0).value("id")); } diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java index 5f330cda75..45827cb21d 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java @@ -19,6 +19,7 @@ package com.baidu.hugegraph.core; +import java.math.BigDecimal; import java.util.Date; import java.util.HashSet; import java.util.Iterator; @@ -192,6 +193,122 @@ public void testAddVertexWithInvalidPropertyType() { graph.addVertex(T.label, "person", "name", "Baby", "city", "Hongkong", "age", "should-be-int"); }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + graph.addVertex(T.label, "person", "name", "Baby", + "city", "Hongkong", "age", 18.0); + }); + } + + @Test + public void testAddVertexWithInvalidPropertValueOfInt() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("int").asInt().create(); + schema.vertexLabel("number").properties("int").create(); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + long value = Integer.MAX_VALUE + 1L; + graph.addVertex(T.label, "number", "int", value); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + long value = Integer.MIN_VALUE - 1L; + graph.addVertex(T.label, "number", "int", value); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + graph.addVertex(T.label, "number", "int", Long.MAX_VALUE); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + graph.addVertex(T.label, "number", "int", Long.MIN_VALUE); + }); + } + + @Test + public void testAddVertexWithInvalidPropertValueOfLong() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("long").asLong().create(); + schema.vertexLabel("number").properties("long").create(); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + BigDecimal one = new BigDecimal(1); + BigDecimal value = new BigDecimal(Long.MAX_VALUE).add(one); + graph.addVertex(T.label, "number", "long", value); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + BigDecimal one = new BigDecimal(-1); + BigDecimal value = new BigDecimal(Long.MIN_VALUE).add(one); + graph.addVertex(T.label, "number", "long", value); + }); + } + + @Test + public void testAddVertexWithInvalidPropertValueOfFloat() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("float").asFloat().create(); + schema.vertexLabel("number").properties("float").create(); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + double value = Float.MAX_VALUE * 2.0d; + graph.addVertex(T.label, "number", "float", value); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + double value = -(Float.MAX_VALUE * 2.0d); + graph.addVertex(T.label, "number", "float", value); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + graph.addVertex(T.label, "number", "float", Double.MAX_VALUE); + }); + + double value = Float.MIN_VALUE / 2.0d; + float fvalue = graph.addVertex(T.label, "number", "float", value) + .value("float"); + Assert.assertEquals(0.0f, fvalue, 0.0d); + + fvalue = graph.addVertex(T.label, "number", "float", -value) + .value("float"); + Assert.assertEquals(0.0f, fvalue, 0.0d); + + fvalue = graph.addVertex(T.label, "number", "float", Double.MIN_VALUE) + .value("float"); + Assert.assertEquals(0.0f, fvalue, 0.0d); + } + + @Test + public void testAddVertexWithInvalidPropertValueOfDouble() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("double").asDouble().create(); + schema.vertexLabel("number").properties("double").create(); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + BigDecimal two = new BigDecimal(2); + BigDecimal value = new BigDecimal(Double.MAX_VALUE).multiply(two); + graph.addVertex(T.label, "number", "double", value); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + BigDecimal two = new BigDecimal(2); + BigDecimal value = new BigDecimal(-Double.MAX_VALUE).multiply(two); + graph.addVertex(T.label, "number", "double", value); + }); + + BigDecimal two = new BigDecimal(2); + BigDecimal value = new BigDecimal(Double.MIN_VALUE).divide(two); + double dvalue = graph.addVertex(T.label, "number", "double", value) + .value("double"); + Assert.assertEquals(0.0d, dvalue, 0.0d); + + value = new BigDecimal(-Double.MIN_VALUE).divide(two); + dvalue = graph.addVertex(T.label, "number", "double", value) + .value("double"); + Assert.assertEquals(0.0d, dvalue, 0.0d); } @Test @@ -1011,8 +1128,8 @@ public void testQueryByHasValue() { init10Vertices(); List vertices = graph.traversal().V() - .hasLabel("language").hasValue(true) - .toList(); + .hasLabel("language").hasValue(true) + .toList(); Assert.assertEquals(1, vertices.size()); assertContains(vertices, T.label, "language", "name", "python", @@ -1044,9 +1161,9 @@ public void testQueryByStringPropWithOneResult() { initPersonIndex(true); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("city", "Taipei") - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("city", "Taipei") + .toList(); Assert.assertEquals(1, vertices.size()); assertContains(vertices, @@ -1063,9 +1180,8 @@ public void testQueryByStringPropWithMultiResults() { initPersonIndex(true); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("city", "Beijing") - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("city", "Beijing").toList(); Assert.assertEquals(3, vertices.size()); @@ -1087,8 +1203,8 @@ public void testQueryByIntPropWithOneResult() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", 19).toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", 19).toList(); Assert.assertEquals(1, vertices.size()); assertContains(vertices, @@ -1103,8 +1219,8 @@ public void testQueryByIntPropWithMultiResults() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", 20).toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", 20).toList(); Assert.assertEquals(2, vertices.size()); @@ -1123,8 +1239,8 @@ public void testQueryByIntPropWithNonResult() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", 18).toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", 18).toList(); Assert.assertEquals(0, vertices.size()); } @@ -1136,9 +1252,8 @@ public void testQueryByIntPropWithDifferentDataType() { HugeGraph graph = graph(); initPersonIndex(false); init5Persons(); - List vertices; - vertices = graph.traversal().V().has("age", 21).toList(); + List vertices = graph.traversal().V().has("age", 21).toList(); Assert.assertEquals(1, vertices.size()); Assert.assertThrows(IllegalArgumentException.class, () -> { @@ -1150,6 +1265,57 @@ public void testQueryByIntPropWithDifferentDataType() { }); } + @Test + public void testQueryByIntPropWithNegativeNumber() { + HugeGraph graph = graph(); + initPersonIndex(false); + + graph.addVertex(T.label, "person", "name", "Louise", + "city", "Hongkong", "age", 17, + "birth", Utils.date("2012-01-01")); + graph.addVertex(T.label, "person", "name", "Sean", + "city", "Beijing", "age", -10, + "birth", Utils.date("2029-01-01")); + + List vertices = graph.traversal().V().has("age", -10).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, + T.label, "person", "name", "Sean", + "city", "Beijing", "age", -10, + "birth", Utils.date("2029-01-01")); + + vertices = graph.traversal().V() + .has("age", P.between(-11, 0)) + .toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals("Sean", vertices.get(0).value("name")); + + vertices = graph.traversal().V().has("age", P.gt(-11)).toList(); + Assert.assertEquals(2, vertices.size()); + + vertices = graph.traversal().V().has("age", P.gte(-10)).toList(); + Assert.assertEquals(2, vertices.size()); + + vertices = graph.traversal().V().has("age", P.gt(-10)).toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals("Louise", vertices.get(0).value("name")); + + vertices = graph.traversal().V().has("age", P.gt(-9)).toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals("Louise", vertices.get(0).value("name")); + + vertices = graph.traversal().V().has("age", P.lt(-10)).toList(); + Assert.assertEquals(0, vertices.size()); + + vertices = graph.traversal().V().has("age", P.lte(-10)).toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals("Sean", vertices.get(0).value("name")); + + vertices = graph.traversal().V().has("age", P.lt(0)).toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals("Sean", vertices.get(0).value("name")); + } + @Test public void testQueryByIntPropUsingLtWithOneResult() { // age < 19 @@ -1157,9 +1323,8 @@ public void testQueryByIntPropUsingLtWithOneResult() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.lt(19)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.lt(19)).toList(); Assert.assertEquals(1, vertices.size()); assertContains(vertices, @@ -1174,9 +1339,8 @@ public void testQueryByIntPropUsingLtWithMultiResults() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.lt(21)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.lt(21)).toList(); Assert.assertEquals(4, vertices.size()); } @@ -1188,9 +1352,8 @@ public void testQueryByIntPropUsingLteWithMultiResults() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.lte(20)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.lte(20)).toList(); Assert.assertEquals(4, vertices.size()); } @@ -1202,9 +1365,8 @@ public void testQueryByIntPropUsingGtWithOneResult() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.gt(20)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.gt(20)).toList(); Assert.assertEquals(1, vertices.size()); } @@ -1216,9 +1378,8 @@ public void testQueryByIntPropUsingGtWithMultiResults() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.gt(1)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.gt(1)).toList(); Assert.assertEquals(5, vertices.size()); } @@ -1230,9 +1391,8 @@ public void testQueryByIntPropUsingGtWithNonResult() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.gt(30)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.gt(30)).toList(); Assert.assertEquals(0, vertices.size()); } @@ -1244,9 +1404,8 @@ public void testQueryByIntPropUsingGteWithMultiResults() { initPersonIndex(false); init5Persons(); - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.gte(20)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.gte(20)).toList(); Assert.assertEquals(3, vertices.size()); } @@ -1260,9 +1419,8 @@ public void testQueryByIntPropUsingInsideWithOneResult() { init5Persons(); // 3 < age && age < 20 (that's age == 19) - List vertices = graph.traversal().V() - .hasLabel("person").has("age", P.inside(3, 20)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(3, 20)).toList(); Assert.assertEquals(1, vertices.size()); Assert.assertEquals(19, vertices.get(0).property("age").value()); @@ -1277,25 +1435,20 @@ public void testQueryByIntPropUsingInsideWithMultiResults() { init5Persons(); // 19 < age && age < 21 (that's age == 20) - List vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.inside(19, 21)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(19, 21)).toList(); Assert.assertEquals(2, vertices.size()); // 3 < age && age < 21 (that's age == 19 or age == 20) - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.inside(3, 21)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(3, 21)).toList(); Assert.assertEquals(3, vertices.size()); // 0 < age && age < 22 (that's all) - vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.inside(0, 22)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(0, 22)).toList(); Assert.assertEquals(5, vertices.size()); } @@ -1309,39 +1462,32 @@ public void testQueryByIntPropUsingInsideWithNonResult() { init5Persons(); // 3 < age && age < 19 - List vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.inside(3, 19)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(3, 19)).toList(); Assert.assertEquals(0, vertices.size()); // 0 < age && age < 3 - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.inside(0, 3)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(0, 3)).toList(); Assert.assertEquals(0, vertices.size()); // 20 < age && age < 21 - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.inside(20, 21)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(20, 21)).toList(); Assert.assertEquals(0, vertices.size()); // 21 < age && age < 25 - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.inside(21, 25)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(21, 25)).toList(); Assert.assertEquals(0, vertices.size()); // 21 < age && age < 20 - vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.inside(21, 20)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.inside(21, 20)).toList(); Assert.assertEquals(0, vertices.size()); } @@ -1355,10 +1501,8 @@ public void testQueryByIntPropUsingBetweenWithOneResult() { init5Persons(); // 3 <= age && age < 19 (that's age == 3) - List vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.between(3, 19)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.between(3, 19)).toList(); Assert.assertEquals(1, vertices.size()); } @@ -1372,17 +1516,14 @@ public void testQueryByIntPropUsingBetweenWithMultiResults() { init5Persons(); // 19 <= age && age < 21 - List vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.between(19, 21)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.between(19, 21)).toList(); Assert.assertEquals(3, vertices.size()); // 3 <= age && age < 21 - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.between(3, 21)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.between(3, 21)).toList(); Assert.assertEquals(4, vertices.size()); } @@ -1396,28 +1537,370 @@ public void testQueryByIntPropUsingBetweenWithNonResult() { init5Persons(); // 4 <= age && age < 19 - List vertices = graph.traversal().V() - .hasLabel("person") - .has("age", P.between(4, 19)) - .toList(); + List vertices = graph.traversal().V().hasLabel("person") + .has("age", P.between(4, 19)).toList(); Assert.assertEquals(0, vertices.size()); // 3 <= age && age < 3 - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.between(3, 3)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.between(3, 3)).toList(); Assert.assertEquals(0, vertices.size()); // 21 <= age && age < 20 - vertices = graph.traversal().V() - .hasLabel("person").has("age", P.between(21, 20)) - .toList(); + vertices = graph.traversal().V().hasLabel("person") + .has("age", P.between(21, 20)).toList(); Assert.assertEquals(0, vertices.size()); } + @Test + public void testQueryByIntProperty() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("int").asInt().create(); + schema.vertexLabel("number").primaryKeys("id") + .properties("id", "int").create(); + schema.indexLabel("numberByInt").range() + .onV("number").by("int").create(); + + graph().addVertex(T.label, "number", "id", 1, "int", 0); + graph().addVertex(T.label, "number", "id", 2, "int", 12345678); + graph().addVertex(T.label, "number", "id", 3, "int", 1000000001L); + graph().addVertex(T.label, "number", "id", 4, "int", -1); + graph().addVertex(T.label, "number", "id", 5, "int", Integer.MAX_VALUE); + graph().addVertex(T.label, "number", "id", 6, "int", Integer.MIN_VALUE); + + graph().tx().commit(); + + List vertices = graph.traversal().V().hasLabel("number") + .has("int", 0).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 1, "int", 0); + + vertices = graph.traversal().V().hasLabel("number") + .has("int", 12345678).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 2, "int", 12345678); + + vertices = graph.traversal().V().hasLabel("number") + .has("int", 1000000001L).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 3, "int", 1000000001); + + vertices = graph.traversal().V().hasLabel("number") + .has("int", -1).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 4, "int", -1); + + vertices = graph.traversal().V().hasLabel("number") + .has("int", Integer.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 5, + "int", Integer.MAX_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("int", Integer.MIN_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 6, + "int", Integer.MIN_VALUE); + } + + @Test + public void testQueryByLongProperty() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("long").asLong().create(); + schema.vertexLabel("number").primaryKeys("id") + .properties("id", "long").create(); + schema.indexLabel("numberByLong").range() + .onV("number").by("long").create(); + + final long largeLong = 9123456789087654321L; + + graph().addVertex(T.label, "number", "id", 1, "long", 0L); + graph().addVertex(T.label, "number", "id", 2, "long", 7L); + graph().addVertex(T.label, "number", "id", 3, "long", 1000000001); + graph().addVertex(T.label, "number", "id", 4, "long", -1L); + graph().addVertex(T.label, "number", "id", 5, "long", largeLong); + graph().addVertex(T.label, "number", "id", 6, "long", -largeLong); + graph().addVertex(T.label, "number", "id", 7, "long", Long.MAX_VALUE); + graph().addVertex(T.label, "number", "id", 8, "long", Long.MIN_VALUE); + + graph().tx().commit(); + + List vertices = graph.traversal().V().hasLabel("number") + .has("long", 0).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 1, "long", 0L); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", 7).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 2, "long", 7L); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", 1000000001).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 3, + "long", 1000000001L); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", -1).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 4, "long", -1L); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", largeLong).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 5, + "long", largeLong); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", -largeLong).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 6, + "long", -largeLong); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", Long.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 7, + "long", Long.MAX_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("long", Long.MIN_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 8, + "long", Long.MIN_VALUE); + } + + @Test + public void testQueryByFloatProperty() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("float").asFloat().create(); + schema.vertexLabel("number").primaryKeys("id") + .properties("id", "float").create(); + schema.indexLabel("numberByFloat").range() + .onV("number").by("float").create(); + + graph().addVertex(T.label, "number", "id", 1, "float", 7); + graph().addVertex(T.label, "number", "id", 2, "float", 3.14f); + graph().addVertex(T.label, "number", "id", 3, "float", 3.141592f); + graph().addVertex(T.label, "number", "id", 4, "float", 1234.567d); + graph().addVertex(T.label, "number", "id", 5, + "float", Float.MAX_VALUE); + graph().addVertex(T.label, "number", "id", 6, + "float", -Float.MAX_VALUE); + graph().addVertex(T.label, "number", "id", 7, + "float", Float.MIN_VALUE); + graph().addVertex(T.label, "number", "id", 8, + "float", -Float.MIN_VALUE); + + graph().tx().commit(); + + List vertices = graph.traversal().V().hasLabel("number") + .has("float", 7).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 1, "float", 7f); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", 3.14f).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 2, "float", 3.14f); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", 3.141592f).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 3, + "float", 3.141592f); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", 1234.567d).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 4, + "float", 1234.567f); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", Float.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 5, + "float", Float.MAX_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", -Float.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 6, + "float", -Float.MAX_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", Float.MIN_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 7, + "float", Float.MIN_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("float", -Float.MIN_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 8, + "float", -Float.MIN_VALUE); + } + + @Test + public void testQueryByDoubleProperty() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("double").asDouble().create(); + schema.vertexLabel("number").primaryKeys("id") + .properties("id", "double").create(); + schema.indexLabel("numberByDouble").range() + .onV("number").by("double").create(); + + final double max7 = Double.valueOf(String.valueOf(Float.MAX_VALUE)); + + /* + * The double precision type typically has a range of around 1E-307 to + * 1E+308 with a precision of at least 15 digits. (postgresql) + * https://www.postgresql.org/docs/9.5/datatype-numeric.html#DATATYPE-NUMERIC-TABLE + */ + final double max15 = new BigDecimal(Double.MAX_VALUE) + .movePointLeft(308) + .setScale(15, BigDecimal.ROUND_DOWN) + .movePointRight(308) + .doubleValue(); // 1.797693134862315E308 + final double min15 = new BigDecimal(1.234567890987654321d) + .setScale(15, BigDecimal.ROUND_DOWN) + .movePointLeft(307) + .doubleValue(); // 1.234567890987654E-307 + + graph().addVertex(T.label, "number", "id", 1, "double", 7); + graph().addVertex(T.label, "number", "id", 2, "double", 3.14f); + graph().addVertex(T.label, "number", "id", 3, "double", Math.PI); + graph().addVertex(T.label, "number", "id", 4, + "double", 12345678901234.567d); // 12345678901234.566 + graph().addVertex(T.label, "number", "id", 5, "double", max7); + graph().addVertex(T.label, "number", "id", 6, "double", -max7); + graph().addVertex(T.label, "number", "id", 7, "double", max15); + graph().addVertex(T.label, "number", "id", 8, "double", -max15); + graph().addVertex(T.label, "number", "id", 9, "double", min15); + graph().addVertex(T.label, "number", "id", 10, "double", -min15); + + graph().tx().commit(); + + List vertices = graph.traversal().V().hasLabel("number") + .has("double", 7).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 1, "double", 7d); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", 3.14f).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 2, "double", 3.14d); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", Math.PI).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 3, "double", Math.PI); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", 12345678901234.567d).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 4, + "double", 12345678901234.567d); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", Float.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 5, "double", max7); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", -Float.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 6, "double", -max7); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", max15).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 7, "double", max15); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", -max15).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 8, -max15); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", min15).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 9, "double", min15); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", -min15).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 10, -min15); + } + + @Test + public void testQueryByDoublePropertyWithMaxMinValue() { + HugeGraph graph = graph(); + + SchemaManager schema = graph.schema(); + schema.propertyKey("double").asDouble().create(); + schema.vertexLabel("number").primaryKeys("id") + .properties("id", "double").create(); + schema.indexLabel("numberByDouble").range() + .onV("number").by("double").create(); + + graph().addVertex(T.label, "number", "id", 0, + "double", 0.123456789012345678901d); + graph().addVertex(T.label, "number", "id", 1, + "double", Double.MAX_VALUE); + graph().addVertex(T.label, "number", "id", 2, + "double", -Double.MAX_VALUE); + graph().addVertex(T.label, "number", "id", 3, + "double", Double.MIN_VALUE); + graph().addVertex(T.label, "number", "id", 4, + "double", -Double.MIN_VALUE); + + graph().tx().commit(); + + List vertices = graph.traversal().V().hasLabel("number") + .has("double", 0.123456789012345678901d) + .toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 0, + "double", 0.123456789012345678901d); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", Double.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 1, + "double", Double.MAX_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", -Double.MAX_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 2, + "double", -Double.MAX_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", Double.MIN_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 3, + "double", Double.MIN_VALUE); + + vertices = graph.traversal().V().hasLabel("number") + .has("double", -Double.MIN_VALUE).toList(); + Assert.assertEquals(1, vertices.size()); + assertContains(vertices, T.label, "number", "id", 4, + "double", -Double.MIN_VALUE); + } + @Test public void testQueryByDateProperty() { HugeGraph graph = graph(); @@ -1490,7 +1973,7 @@ public void testQueryByDatePropertyInString() { @Test @SuppressWarnings("unchecked") - public void testQueryByUnionHasDate() { + public void testQuerytestQueryByDatePropertyWithUnion() { HugeGraph graph = graph(); initPersonIndex(false); init5Persons(); @@ -4264,13 +4747,11 @@ private Vertex vertex(String label, String pkName, Object pkValue) { private static void assertContains(List vertices, Object... keyValues) { - Assert.assertTrue(Utils.contains(vertices, - new FakeVertex(keyValues))); + Assert.assertTrue(Utils.contains(vertices, new FakeVertex(keyValues))); } private static void assertNotContains(List vertices, Object... keyValues) { - Assert.assertFalse(Utils.contains(vertices, - new FakeVertex(keyValues))); + Assert.assertFalse(Utils.contains(vertices, new FakeVertex(keyValues))); } }