Skip to content

Commit 98fef9a

Browse files
committed
fix: support boolean range predicates in condition query
1 parent c0a2b93 commit 98fef9a

6 files changed

Lines changed: 148 additions & 2 deletions

File tree

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ private static boolean equals(final Object first,
195195
*
196196
* @param first is actual value, might be Number/Date or String, It is
197197
* probably that the `first` is serialized to String.
198-
* @param second is value in query condition, must be Number/Date
198+
* @param second is value in query condition, must be Number/Date/Boolean
199199
* @return the value 0 if first is numerically equal to second;
200200
* a value less than 0 if first is numerically less than
201201
* second; and a value greater than 0 if first is
@@ -208,6 +208,8 @@ private static int compare(final Object first, final Object second) {
208208
(Number) second);
209209
} else if (second instanceof Date) {
210210
return compareDate(first, (Date) second);
211+
} else if (second instanceof Boolean) {
212+
return compareBoolean(first, (Boolean) second);
211213
}
212214

213215
throw new IllegalArgumentException(String.format(
@@ -230,6 +232,20 @@ private static int compareDate(Object first, Date second) {
230232
second, second.getClass().getSimpleName()));
231233
}
232234

235+
private static int compareBoolean(Object first, Boolean second) {
236+
if (first == null) {
237+
first = false;
238+
}
239+
if (first instanceof Boolean) {
240+
return Boolean.compare((Boolean) first, second);
241+
}
242+
243+
throw new IllegalArgumentException(String.format(
244+
"Can't compare between %s(%s) and %s(%s)",
245+
first, first.getClass().getSimpleName(),
246+
second, second.getClass().getSimpleName()));
247+
}
248+
233249
private void checkBaseType(Object value, Class<?> clazz) {
234250
if (!clazz.isInstance(value)) {
235251
String valueClass = value == null ? "null" :

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,9 @@ private static int compare(Relation first, Relation second) {
507507
return NumericUtil.compareNumber(firstValue, (Number) secondValue);
508508
} else if (firstValue instanceof Date && secondValue instanceof Date) {
509509
return ((Date) firstValue).compareTo((Date) secondValue);
510+
} else if (firstValue instanceof Boolean &&
511+
secondValue instanceof Boolean) {
512+
return Boolean.compare((Boolean) firstValue, (Boolean) secondValue);
510513
} else {
511514
throw new IllegalArgumentException(String.format("Can't compare between %s and %s",
512515
first, second));

hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7117,6 +7117,48 @@ public void testQueryEdgeWithNullablePropertyInCompositeIndex() {
71177117
Assert.assertEquals(1, (int) el.get(0).value("id"));
71187118
}
71197119

7120+
@Test
7121+
public void testQueryEdgeByBooleanRangePredicate() {
7122+
HugeGraph graph = graph();
7123+
initStrikeIndex();
7124+
7125+
Vertex louise = graph.addVertex(T.label, "person", "name", "Louise",
7126+
"city", "Beijing", "age", 21);
7127+
Vertex sean = graph.addVertex(T.label, "person", "name", "Sean",
7128+
"city", "Beijing", "age", 23);
7129+
long current = System.currentTimeMillis();
7130+
louise.addEdge("strike", sean, "id", 1,
7131+
"timestamp", current, "place", "park",
7132+
"tool", "shovel", "reason", "jeer",
7133+
"arrested", false);
7134+
louise.addEdge("strike", sean, "id", 2,
7135+
"timestamp", current + 1, "place", "street",
7136+
"tool", "shovel", "reason", "jeer",
7137+
"arrested", true);
7138+
7139+
List<Edge> hasEdges = graph.traversal().E()
7140+
.has("arrested", P.lt(true))
7141+
.toList();
7142+
Assert.assertEquals(1, hasEdges.size());
7143+
Assert.assertEquals(1, (int) hasEdges.get(0).value("id"));
7144+
7145+
List<Edge> whereEdges = graph.traversal().E()
7146+
.where(__.has("arrested", P.lt(true)))
7147+
.toList();
7148+
Assert.assertEquals(1, whereEdges.size());
7149+
Assert.assertEquals(1, (int) whereEdges.get(0).value("id"));
7150+
7151+
List<Edge> matchEdges = graph.traversal().E()
7152+
.as("e")
7153+
.match(__.as("e")
7154+
.has("arrested", P.lt(true)))
7155+
.<Edge>select("e")
7156+
.dedup()
7157+
.toList();
7158+
Assert.assertEquals(1, matchEdges.size());
7159+
Assert.assertEquals(1, (int) matchEdges.get(0).value("id"));
7160+
}
7161+
71207162
@Test
71217163
public void testQueryEdgeByPage() {
71227164
Assume.assumeTrue("Not support paging",

hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionQueryFlattenTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,5 +256,48 @@ public void testFlattenWithNotIn() {
256256
Collection<Condition> actual = queries.iterator().next().conditions();
257257
Assert.assertEquals(expect, actual);
258258
}
259+
260+
@Test
261+
public void testFlattenWithBooleanRangeUpperBound() {
262+
Id key = IdGenerator.of("c1");
263+
264+
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
265+
query.query(Condition.lt(key, true));
266+
query.query(Condition.lt(key, false));
267+
268+
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
269+
Assert.assertEquals(1, queries.size());
270+
271+
Collection<Condition> actual = queries.iterator().next().conditions();
272+
Assert.assertEquals(ImmutableList.of(Condition.lt(key, false)), actual);
273+
}
274+
275+
@Test
276+
public void testFlattenWithBooleanRangeWindow() {
277+
Id key = IdGenerator.of("c1");
278+
279+
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
280+
query.query(Condition.gte(key, false));
281+
query.query(Condition.lt(key, true));
282+
283+
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
284+
Assert.assertEquals(1, queries.size());
285+
286+
Collection<Condition> actual = queries.iterator().next().conditions();
287+
Assert.assertEquals(ImmutableList.of(Condition.gte(key, false),
288+
Condition.lt(key, true)), actual);
289+
}
290+
291+
@Test
292+
public void testFlattenWithConflictingBooleanRange() {
293+
Id key = IdGenerator.of("c1");
294+
295+
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
296+
query.query(Condition.gt(key, false));
297+
query.query(Condition.lt(key, true));
298+
299+
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
300+
Assert.assertEquals(0, queries.size());
301+
}
259302
}
260303

hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,32 @@ public void testConditionLte() {
293293
});
294294
}
295295

296+
@Test
297+
public void testConditionBooleanRange() {
298+
Condition lt = Condition.lt(HugeKeys.ID, true);
299+
Assert.assertTrue(lt.test(false));
300+
Assert.assertFalse(lt.test(true));
301+
302+
Condition lte = Condition.lte(HugeKeys.ID, false);
303+
Assert.assertTrue(lte.test(false));
304+
Assert.assertFalse(lte.test(true));
305+
306+
Condition gt = Condition.gt(HugeKeys.ID, false);
307+
Assert.assertTrue(gt.test(true));
308+
Assert.assertFalse(gt.test(false));
309+
310+
Condition gte = Condition.gte(HugeKeys.ID, true);
311+
Assert.assertTrue(gte.test(true));
312+
Assert.assertFalse(gte.test(false));
313+
314+
Assert.assertThrows(IllegalArgumentException.class, () -> {
315+
Condition.lt(HugeKeys.ID, true).test(1);
316+
}, e -> {
317+
String err = "Can't compare between 1(Integer) and true(Boolean)";
318+
Assert.assertEquals(err, e.getMessage());
319+
});
320+
}
321+
296322
@Test
297323
public void testConditionNeq() {
298324
Condition c1 = Condition.neq(HugeKeys.ID, 123);

hugegraph-struct/src/main/java/org/apache/hugegraph/query/Condition.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ private static boolean equals(final Object first,
437437
*
438438
* @param first is actual value, might be Number/Date or String, It is
439439
* probably that the `first` is serialized to String.
440-
* @param second is value in query condition, must be Number/Date
440+
* @param second is value in query condition, must be Number/Date/Boolean
441441
* @return the value 0 if first is numerically equal to second;
442442
* a value less than 0 if first is numerically less than
443443
* second; and a value greater than 0 if first is
@@ -450,6 +450,8 @@ private static int compare(final Object first, final Object second) {
450450
(Number) second);
451451
} else if (second instanceof Date) {
452452
return compareDate(first, (Date) second);
453+
} else if (second instanceof Boolean) {
454+
return compareBoolean(first, (Boolean) second);
453455
}
454456

455457
throw new IllegalArgumentException(String.format(
@@ -472,6 +474,20 @@ private static int compareDate(Object first, Date second) {
472474
second, second.getClass().getSimpleName()));
473475
}
474476

477+
private static int compareBoolean(Object first, Boolean second) {
478+
if (first == null) {
479+
first = false;
480+
}
481+
if (first instanceof Boolean) {
482+
return Boolean.compare((Boolean) first, second);
483+
}
484+
485+
throw new IllegalArgumentException(String.format(
486+
"Can't compare between %s(%s) and %s(%s)",
487+
first, first.getClass().getSimpleName(),
488+
second, second.getClass().getSimpleName()));
489+
}
490+
475491
public static List<String> tokenize(String str) {
476492
final ArrayList<String> tokens = new ArrayList<>();
477493
int previous = 0;

0 commit comments

Comments
 (0)