Skip to content

Commit 7d906bc

Browse files
committed
fix(core): retain unsafe label predicates for filtering
1 parent bc2a999 commit 7d906bc

5 files changed

Lines changed: 141 additions & 12 deletions

File tree

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,13 @@ public boolean containsLabelOrUserpropRelation() {
262262
* This method keeps the historical behavior for existing callers:
263263
* <ul>
264264
* <li>returns {@code null} if no top-level EQ/IN relation exists</li>
265-
* <li>returns {@code null} if top-level EQ/IN relations resolve to empty</li>
266-
* <li>returns the single value if only one value is resolved</li>
267-
* <li>returns the raw IN list if there is exactly one top-level IN relation</li>
265+
* <li>returns the single EQ value if there is exactly one top-level EQ
266+
* relation and no top-level IN relation</li>
267+
* <li>returns the raw IN list, including an empty list, if there is exactly
268+
* one top-level IN relation and no top-level EQ relation</li>
269+
* <li>returns {@code null} if several top-level EQ/IN relations resolve to
270+
* an empty set</li>
271+
* <li>returns the single value if several relations resolve to one value</li>
268272
* <li>throws if multiple values remain after resolving several relations</li>
269273
* </ul>
270274
*

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -446,29 +446,38 @@ private static boolean extractHasContainers(HugeVertexStep<?> newStep,
446446
private static boolean canExtractHasContainers(HugeGraph graph,
447447
HasContainerHolder holder) {
448448
List<HasContainer> hasContainers = holder.getHasContainers();
449-
// Keep pure label non-EQ/IN predicates on GraphStep for TinkerPop filtering.
450-
if (hasContainers.size() == 1 &&
451-
isOnlyNonEqInLabelPredicate(hasContainers.get(0))) {
452-
return false;
449+
// Keep pure label non-EQ/IN predicates for TinkerPop filtering.
450+
if (isPureLabelPredicateHolder(hasContainers)) {
451+
for (HasContainer has : hasContainers) {
452+
if (!isEqInLabelPredicate(has)) {
453+
return false;
454+
}
455+
}
453456
}
454-
for (HasContainer has : holder.getHasContainers()) {
457+
for (HasContainer has : hasContainers) {
455458
if (!canExtractHasContainer(graph, has)) {
456459
return false;
457460
}
458461
}
459462
return true;
460463
}
461464

462-
private static boolean isOnlyNonEqInLabelPredicate(HasContainer has) {
463-
if (!has.getKey().equals(T.label.getAccessor())) {
464-
return false;
465+
private static boolean isPureLabelPredicateHolder(
466+
List<HasContainer> hasContainers) {
467+
for (HasContainer has : hasContainers) {
468+
if (!has.getKey().equals(T.label.getAccessor())) {
469+
return false;
470+
}
465471
}
472+
return true;
473+
}
466474

475+
private static boolean isEqInLabelPredicate(HasContainer has) {
467476
List<P<Object>> predicates = new ArrayList<>();
468477
collectPredicates(predicates, ImmutableList.of(has.getPredicate()));
469478
for (P<Object> predicate : predicates) {
470479
BiPredicate<?, ?> bp = predicate.getBiPredicate();
471-
if (bp == Compare.eq || bp == Contains.within) {
480+
if (bp != Compare.eq && bp != Contains.within) {
472481
return false;
473482
}
474483
}

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3633,6 +3633,57 @@ public void testQueryEdgesByNonEqLabel() {
36333633
}
36343634
}
36353635

3636+
@Test
3637+
public void testQueryEdgesByMixedConnectiveLabel() {
3638+
HugeGraph graph = graph();
3639+
init18Edges();
3640+
3641+
GraphTraversalSource g = graph.traversal();
3642+
3643+
List<Edge> edges = g.E()
3644+
.has(T.label, P.eq("created")
3645+
.or(P.neq("authored")))
3646+
.toList();
3647+
Assert.assertEquals(15, edges.size());
3648+
for (Edge edge : edges) {
3649+
Assert.assertNotEquals("authored", edge.label());
3650+
}
3651+
3652+
edges = g.E()
3653+
.has(T.label, P.eq("created")
3654+
.and(P.neq("authored")))
3655+
.toList();
3656+
Assert.assertEquals(2, edges.size());
3657+
for (Edge edge : edges) {
3658+
Assert.assertEquals("created", edge.label());
3659+
}
3660+
}
3661+
3662+
@Test
3663+
public void testQueryEdgesByMultipleNegativeLabelContainers() {
3664+
HugeGraph graph = graph();
3665+
init18Edges();
3666+
3667+
GraphTraversalSource g = graph.traversal();
3668+
3669+
List<Edge> edges = g.E().hasLabel("created")
3670+
.has(T.label, P.neq("authored"))
3671+
.toList();
3672+
Assert.assertEquals(2, edges.size());
3673+
for (Edge edge : edges) {
3674+
Assert.assertEquals("created", edge.label());
3675+
}
3676+
3677+
edges = g.E().has(T.label, P.neq("created"))
3678+
.has(T.label, P.neq("authored"))
3679+
.toList();
3680+
Assert.assertEquals(13, edges.size());
3681+
for (Edge edge : edges) {
3682+
Assert.assertNotEquals("created", edge.label());
3683+
Assert.assertNotEquals("authored", edge.label());
3684+
}
3685+
}
3686+
36363687
@Test
36373688
public void testQueryOutEdgesOfVertexBySortkeyWithRange() {
36383689
// FIXME: skip this test for hstore

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9111,6 +9111,56 @@ public void testQueryByNonEqLabel() {
91119111
}
91129112
}
91139113

9114+
@Test
9115+
public void testQueryByMixedConnectiveLabel() {
9116+
HugeGraph graph = graph();
9117+
init10Vertices();
9118+
9119+
GraphTraversalSource g = graph.traversal();
9120+
9121+
List<Vertex> vertices = g.V()
9122+
.has(T.label, P.eq("language")
9123+
.or(P.neq("author")))
9124+
.toList();
9125+
Assert.assertEquals(8, vertices.size());
9126+
for (Vertex vertex : vertices) {
9127+
Assert.assertNotEquals("author", vertex.label());
9128+
}
9129+
9130+
vertices = g.V()
9131+
.has(T.label, P.eq("language")
9132+
.and(P.neq("author")))
9133+
.toList();
9134+
Assert.assertEquals(3, vertices.size());
9135+
for (Vertex vertex : vertices) {
9136+
Assert.assertEquals("language", vertex.label());
9137+
}
9138+
}
9139+
9140+
@Test
9141+
public void testQueryByMultipleNegativeLabelContainers() {
9142+
HugeGraph graph = graph();
9143+
init10Vertices();
9144+
9145+
GraphTraversalSource g = graph.traversal();
9146+
9147+
List<Vertex> vertices = g.V().hasLabel("language")
9148+
.has(T.label, P.neq("author"))
9149+
.toList();
9150+
Assert.assertEquals(3, vertices.size());
9151+
for (Vertex vertex : vertices) {
9152+
Assert.assertEquals("language", vertex.label());
9153+
}
9154+
9155+
vertices = g.V().has(T.label, P.neq("author"))
9156+
.has(T.label, P.neq("book"))
9157+
.toList();
9158+
Assert.assertEquals(3, vertices.size());
9159+
for (Vertex vertex : vertices) {
9160+
Assert.assertEquals("language", vertex.label());
9161+
}
9162+
}
9163+
91149164
@Test
91159165
public void testCollectMatchedIndexesByJointLabelsWithIndexedProperties() {
91169166
HugeGraph graph = graph();

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@ public void testConditionWithSingleInValues() {
102102
query.condition(HugeKeys.LABEL));
103103
}
104104

105+
@Test
106+
public void testConditionWithEmptyInValues() {
107+
ConditionQuery query = new ConditionQuery(HugeType.EDGE);
108+
query.query(Condition.in(HugeKeys.LABEL, ImmutableList.of()));
109+
110+
Assert.assertTrue(query.containsCondition(HugeKeys.LABEL));
111+
Assert.assertTrue(query.containsConditionValues(HugeKeys.LABEL));
112+
Assert.assertEquals(ImmutableSet.of(),
113+
query.conditionValues(HugeKeys.LABEL));
114+
Assert.assertNull(query.uniqueConditionValue(HugeKeys.LABEL));
115+
Assert.assertNull(query.conditionValue(HugeKeys.LABEL));
116+
Assert.assertEquals(ImmutableList.of(),
117+
query.condition(HugeKeys.LABEL));
118+
}
119+
105120
@Test
106121
public void testConditionWithConflictingEqAndIn() {
107122
Id label1 = IdGenerator.of(1);

0 commit comments

Comments
 (0)