From 7e95e5e0415fff564b2d6085d246710b40eb30c1 Mon Sep 17 00:00:00 2001 From: contrueCT Date: Sun, 12 Apr 2026 21:39:46 +0800 Subject: [PATCH 1/2] improve(query): clarify condition resolution semantics Add explicit condition resolution APIs to ConditionQuery while preserving the legacy condition() behavior. Introduce containsCondition(Object), conditionValues(Object), and conditionValue(Object) so callers can distinguish missing, empty, unique, and multi-value results without overloading null semantics. Migrate LABEL-specific consumers in graph/index transactions, serializers, traversers, and stores to use the new APIs for unique-label resolution and conservative fallback behavior. Extend QueryTest and VertexCoreTest to cover absent, conflicting, and multi-value label conditions as well as collectMatchedIndexes() behavior for multi-label and conflicting label queries. --- .../backend/query/ConditionQuery.java | 124 +++++++++++++++--- .../backend/serializer/BinarySerializer.java | 5 +- .../backend/serializer/TextSerializer.java | 5 +- .../hugegraph/backend/store/ram/RamTable.java | 12 +- .../backend/tx/GraphIndexTransaction.java | 31 +++-- .../backend/tx/GraphTransaction.java | 16 ++- .../traversal/algorithm/HugeTraverser.java | 2 +- .../backend/store/hstore/HstoreStore.java | 14 +- .../apache/hugegraph/core/VertexCoreTest.java | 44 +++++++ .../apache/hugegraph/unit/core/QueryTest.java | 46 +++++++ 10 files changed, 261 insertions(+), 38 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java index 063d23aa6d..5b37622514 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java @@ -256,24 +256,26 @@ public boolean containsLabelOrUserpropRelation() { return false; } + /** + * Returns the legacy condition value of the specified key. + * + * This method keeps the historical behavior for existing callers: + * + * + * Prefer {@link #conditionValues(Object)} or {@link #conditionValue(Object)} + * for new code that needs explicit semantics. + */ @Watched public T condition(Object key) { List valuesEQ = InsertionOrderUtil.newList(); List valuesIN = InsertionOrderUtil.newList(); - for (Condition c : this.conditions) { - if (c.isRelation()) { - Condition.Relation r = (Condition.Relation) c; - if (r.key().equals(key)) { - if (r.relation() == RelationType.EQ) { - valuesEQ.add(r.value()); - } else if (r.relation() == RelationType.IN) { - Object value = r.value(); - assert value instanceof List; - valuesIN.add(value); - } - } - } - } + this.collectConditionValues(key, valuesEQ, valuesIN); if (valuesEQ.isEmpty() && valuesIN.isEmpty()) { return null; } @@ -323,20 +325,110 @@ public T condition(Object key) { return value; } + /** + * Returns whether there is any top-level relation for the specified key. + */ + public boolean containsCondition(Object key) { + for (Condition c : this.conditions) { + if (c.isRelation()) { + Condition.Relation r = (Condition.Relation) c; + if (r.key().equals(key)) { + return true; + } + } + } + return false; + } + + /** + * Returns the resolved candidate values of the specified key from + * top-level EQ/IN relations. + * + * Use {@link #containsCondition(Object)} to distinguish "no condition" + * from "conditions exist but resolve to an empty intersection". + */ + public Set conditionValues(Object key) { + List valuesEQ = InsertionOrderUtil.newList(); + List valuesIN = InsertionOrderUtil.newList(); + this.collectConditionValues(key, valuesEQ, valuesIN); + if (valuesEQ.isEmpty() && valuesIN.isEmpty()) { + return InsertionOrderUtil.newSet(); + } + return this.resolveConditionValues(valuesEQ, valuesIN); + } + + /** + * Returns the unique resolved value of the specified key from top-level + * EQ/IN relations. + * + * Returns {@code null} when the resolved candidate set is empty. Throws + * if multiple values remain after resolution. + */ + public T conditionValue(Object key) { + Set values = this.conditionValues(key); + if (values.isEmpty()) { + return null; + } + E.checkState(values.size() == 1, + "Illegal key '%s' with more than one value: %s", + key, values); + @SuppressWarnings("unchecked") + T value = (T) values.iterator().next(); + return value; + } + public void unsetCondition(Object key) { this.conditions.removeIf(c -> c.isRelation() && ((Relation) c).key().equals(key)); } public boolean containsCondition(HugeKeys key) { + return this.containsCondition((Object) key); + } + + private void collectConditionValues(Object key, List valuesEQ, + List valuesIN) { for (Condition c : this.conditions) { if (c.isRelation()) { Condition.Relation r = (Condition.Relation) c; if (r.key().equals(key)) { - return true; + if (r.relation() == RelationType.EQ) { + valuesEQ.add(r.value()); + } else if (r.relation() == RelationType.IN) { + Object value = r.value(); + assert value instanceof List; + valuesIN.add(value); + } } } } - return false; + } + + private Set resolveConditionValues(List valuesEQ, + List valuesIN) { + boolean initialized = false; + Set intersectValues = InsertionOrderUtil.newSet(); + for (Object value : valuesEQ) { + List valueAsList = ImmutableList.of(value); + if (!initialized) { + intersectValues.addAll(valueAsList); + initialized = true; + } else { + CollectionUtil.intersectWithModify(intersectValues, + valueAsList); + } + } + for (Object value : valuesIN) { + @SuppressWarnings("unchecked") + List valueAsList = (List) value; + if (!initialized) { + intersectValues.addAll(valueAsList); + initialized = true; + } else { + CollectionUtil.intersectWithModify(intersectValues, + valueAsList); + } + } + return intersectValues; } public boolean containsCondition(Condition.RelationType type) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java index 0bb07760a5..6f1eec58a6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java @@ -674,7 +674,7 @@ private Query writeQueryEdgeRangeCondition(ConditionQuery cq) { if (direction == null) { direction = Directions.OUT; } - Id label = cq.condition(HugeKeys.LABEL); + Id label = cq.conditionValue(HugeKeys.LABEL); BytesBuffer start = BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID); writePartitionedId(HugeType.EDGE, vertex, start); @@ -722,7 +722,8 @@ private Query writeQueryEdgePrefixCondition(ConditionQuery cq) { int count = 0; BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID); for (HugeKeys key : EdgeId.KEYS) { - Object value = cq.condition(key); + Object value = key == HugeKeys.LABEL ? + cq.conditionValue(key) : cq.condition(key); if (value != null) { count++; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java index 2d5cb81ec1..61830b3c54 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java @@ -457,7 +457,7 @@ private Query writeQueryEdgeRangeCondition(ConditionQuery cq) { if (direction == null) { direction = Directions.OUT; } - Object label = cq.condition(HugeKeys.LABEL); + Object label = cq.conditionValue(HugeKeys.LABEL); List start = new ArrayList<>(cq.conditionsSize()); start.add(writeEntryId((Id) vertex)); @@ -491,7 +491,8 @@ private Query writeQueryEdgePrefixCondition(ConditionQuery cq) { List condParts = new ArrayList<>(cq.conditionsSize()); for (HugeKeys key : EdgeId.KEYS) { - Object value = cq.condition(key); + Object value = key == HugeKeys.LABEL ? + cq.conditionValue(key) : cq.condition(key); if (value == null) { break; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java index 0e2c58bddc..c282fe384b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java @@ -269,7 +269,7 @@ public boolean matched(Query query) { int conditionsSize = cq.conditionsSize(); Object owner = cq.condition(HugeKeys.OWNER_VERTEX); Directions direction = cq.condition(HugeKeys.DIRECTION); - Id label = cq.condition(HugeKeys.LABEL); + Id label = uniqueLabel(cq); if (direction == null && conditionsSize > 1) { for (Condition cond : cq.conditions()) { @@ -316,7 +316,7 @@ private Iterator query(ConditionQuery query) { if (dir == null) { dir = Directions.BOTH; } - Id label = query.condition(HugeKeys.LABEL); + Id label = uniqueLabel(query); if (label == null) { label = IdGenerator.ZERO; } @@ -377,6 +377,14 @@ private static void ensureNumberId(Id id) { } } + private static Id uniqueLabel(ConditionQuery query) { + java.util.Set labels = query.conditionValues(HugeKeys.LABEL); + if (labels.size() != 1) { + return null; + } + return (Id) labels.iterator().next(); + } + private static long encode(long target, Directions direction, int label) { // TODO: support property assert (label & 0x0fffffff) == label; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java index 7388425167..6b358b2619 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java @@ -415,8 +415,9 @@ private IdHolderList queryByLabel(ConditionQuery query) { HugeType queryType = query.resultType(); IndexLabel il = IndexLabel.label(queryType); validateIndexLabel(il); - Id label = query.condition(HugeKeys.LABEL); - assert label != null; + Id label = query.conditionValue(HugeKeys.LABEL); + E.checkState(label != null, "Expect one label value for query: %s", + query); HugeType indexType; SchemaLabel schemaLabel; @@ -482,7 +483,7 @@ private IdHolderList queryByUserprop(ConditionQuery query) { } Set indexes = this.collectMatchedIndexes(query); if (indexes.isEmpty()) { - Id label = query.condition(HugeKeys.LABEL); + Id label = uniqueLabel(query); throw noIndexException(this.graph(), query, label); } @@ -756,11 +757,16 @@ private PageIds doIndexQueryOnce(IndexLabel indexLabel, @Watched(prefix = "index") private Set collectMatchedIndexes(ConditionQuery query) { ISchemaTransaction schema = this.params().schemaTransaction(); - Id label = query.condition(HugeKeys.LABEL); + boolean hasLabel = query.containsCondition(HugeKeys.LABEL); + Set labels = query.conditionValues(HugeKeys.LABEL); List schemaLabels; - if (label != null) { - // Query has LABEL condition + if (hasLabel && labels.isEmpty()) { + return Collections.emptySet(); + } + if (labels.size() == 1) { + Id label = (Id) labels.iterator().next(); + // Query has one resolved LABEL condition SchemaLabel schemaLabel; if (query.resultType().isVertex()) { schemaLabel = schema.getVertexLabel(label); @@ -773,7 +779,8 @@ private Set collectMatchedIndexes(ConditionQuery query) { } schemaLabels = ImmutableList.of(schemaLabel); } else { - // Query doesn't have LABEL condition + // Query doesn't have LABEL condition or it doesn't resolve + // to a single label, so keep the conservative fallback. if (query.resultType().isVertex()) { schemaLabels = schema.getVertexLabels(); } else if (query.resultType().isEdge()) { @@ -1781,7 +1788,7 @@ protected long removeIndexLeft(ConditionQuery query, } // Check label is matched - Id label = query.condition(HugeKeys.LABEL); + Id label = uniqueLabel(query); // NOTE: original condition query may not have label condition, // which means possibly label == null. if (label != null && !element.schemaLabel().id().equals(label)) { @@ -1981,4 +1988,12 @@ public Long reduce(Long t1, Long t2) { return t1 + t2; } } + + private static Id uniqueLabel(ConditionQuery query) { + Set labels = query.conditionValues(HugeKeys.LABEL); + if (labels.size() != 1) { + return null; + } + return (Id) labels.iterator().next(); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java index 763ccaa0ee..17f062f9bc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java @@ -1059,7 +1059,7 @@ protected Iterator queryEdgesFromBackend(Query query) { ConditionQueryFlatten.flatten((ConditionQuery) query, supportIn).stream(); Stream> edgeIterators = flattenedQueries.map(cq -> { - Id label = cq.condition(HugeKeys.LABEL); + Id label = uniqueLabel(cq); if (this.storeFeatures().supportsFatherAndSubEdgeLabel() && label != null && graph().edgeLabel(label).isFather() && @@ -1389,7 +1389,7 @@ private static boolean matchEdgeSortKeys(ConditionQuery query, boolean matchAll, HugeGraph graph) { assert query.resultType().isEdge(); - Id label = query.condition(HugeKeys.LABEL); + Id label = uniqueLabel(query); if (label == null) { return false; } @@ -1522,7 +1522,7 @@ private Query optimizeQuery(ConditionQuery query) { throw new HugeException("Not supported querying by id and conditions: %s", query); } - Id label = query.condition(HugeKeys.LABEL); + Id label = uniqueLabel(query); // Optimize vertex query if (label != null && query.resultType().isVertex()) { @@ -1914,7 +1914,7 @@ private boolean rightResultFromIndexQuery(Query query, HugeElement elem) { } ConditionQuery cq = (ConditionQuery) query; - if (cq.condition(HugeKeys.LABEL) != null && cq.resultType().isEdge()) { + if (uniqueLabel(cq) != null && cq.resultType().isEdge()) { if (cq.conditions().size() == 1) { // g.E().hasLabel(xxx) return true; @@ -1966,6 +1966,14 @@ private boolean rightResultFromIndexQuery(Query query, HugeElement elem) { return false; } + private static Id uniqueLabel(ConditionQuery query) { + Set labels = query.conditionValues(HugeKeys.LABEL); + if (labels.size() != 1) { + return null; + } + return (Id) labels.iterator().next(); + } + private Iterator filterExpiredResultFromBackend( Query query, Iterator results) { if (this.store().features().supportsTtl() || query.showExpired()) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java index 8122c79080..a19c32a04f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java @@ -582,7 +582,7 @@ private void fillFilterBySortKeys(Query query, Id[] edgeLabels, ConditionQuery condQuery = (ConditionQuery) query; if (!GraphTransaction.matchFullEdgeSortKeys(condQuery, this.graph())) { - Id label = condQuery.condition(HugeKeys.LABEL); + Id label = condQuery.conditionValue(HugeKeys.LABEL); E.checkArgument(false, "The properties %s does not match " + "sort keys of edge label '%s'", this.graph().mapPkId2Name(properties.keySet()), diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java index 6439096674..713511490d 100644 --- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java +++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java @@ -402,8 +402,8 @@ public IdPrefixQuery next() { List queryList = Lists.newArrayList(); if (hugeGraph != null) { for (ConditionQuery conditionQuery : - ConditionQueryFlatten.flatten(cq)) { - Id label = conditionQuery.condition(HugeKeys.LABEL); + ConditionQueryFlatten.flatten(cq)) { + Id label = this.uniqueLabel(conditionQuery); /* Parent type + sortKeys: g.V("V.id").outE("parentLabel") .has("sortKey","value") converted to all subtypes + sortKeys */ if ((this.subEls == null || @@ -455,11 +455,19 @@ public IdPrefixQuery next() { buffer.bytes(), ownerId)); } + private Id uniqueLabel(ConditionQuery query) { + Set labels = query.conditionValues(HugeKeys.LABEL); + if (labels.size() != 1) { + return null; + } + return (Id) labels.iterator().next(); + } + private boolean matchEdgeSortKeys(ConditionQuery query, boolean matchAll, HugeGraph graph) { assert query.resultType().isEdge(); - Id label = query.condition(HugeKeys.LABEL); + Id label = this.uniqueLabel(query); if (label == null) { return false; } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java index a329de3afb..786e204ec2 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java @@ -53,6 +53,7 @@ import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; +import org.apache.hugegraph.schema.SchemaLabel; import org.apache.hugegraph.schema.Userdata; import org.apache.hugegraph.schema.VertexLabel; import org.apache.hugegraph.structure.HugeElement; @@ -8936,6 +8937,49 @@ public void testQueryByJointLabels() { Assert.assertEquals(0, vertices.size()); } + @Test + public void testCollectMatchedIndexesByJointLabelsWithIndexedProperties() { + HugeGraph graph = graph(); + initPersonIndex(true); + init5Persons(); + init5Computers(); + init10Vertices(); + + VertexLabel person = graph.vertexLabel("person"); + VertexLabel computer = graph.vertexLabel("computer"); + PropertyKey city = graph.propertyKey("city"); + + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.query(Condition.in(HugeKeys.LABEL, + ImmutableList.of(person.id(), computer.id()))); + query.query(Condition.eq(city.id(), "Beijing")); + + Set matchedIndexes = Whitebox.invoke(params().graphTransaction(), + "indexTx", + "collectMatchedIndexes", + query); + Assert.assertEquals(1, matchedIndexes.size()); + Object matchedIndex = matchedIndexes.iterator().next(); + SchemaLabel schemaLabel = Whitebox.getInternalState(matchedIndex, + "schemaLabel"); + Assert.assertEquals("person", schemaLabel.name()); + + ConditionQuery conflicting = new ConditionQuery(HugeType.VERTEX); + conflicting.eq(HugeKeys.LABEL, person.id()); + conflicting.eq(HugeKeys.LABEL, computer.id()); + conflicting.query(Condition.eq(city.id(), "Beijing")); + + Assert.assertTrue(conflicting.containsCondition(HugeKeys.LABEL)); + Assert.assertEquals(ImmutableSet.of(), + conflicting.conditionValues(HugeKeys.LABEL)); + + matchedIndexes = Whitebox.invoke(params().graphTransaction(), + "indexTx", + "collectMatchedIndexes", + conflicting); + Assert.assertEquals(0, matchedIndexes.size()); + } + @Test public void testQueryByHasIdEmptyList() { HugeGraph graph = graph(); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java index 7d48084dbf..bb2951c8ea 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java @@ -48,6 +48,17 @@ public void testOrderBy() { query.orders()); } + @Test + public void testConditionWithoutLabel() { + ConditionQuery query = new ConditionQuery(HugeType.EDGE); + + Assert.assertFalse(query.containsCondition(HugeKeys.LABEL)); + Assert.assertEquals(ImmutableSet.of(), + query.conditionValues(HugeKeys.LABEL)); + Assert.assertNull(query.conditionValue(HugeKeys.LABEL)); + Assert.assertNull(query.condition(HugeKeys.LABEL)); + } + @Test public void testConditionWithEqAndIn() { Id label1 = IdGenerator.of(1); @@ -58,9 +69,33 @@ public void testConditionWithEqAndIn() { query.query(Condition.in(HugeKeys.LABEL, ImmutableList.of(label1, label2))); + Assert.assertTrue(query.containsCondition(HugeKeys.LABEL)); + Assert.assertEquals(ImmutableSet.of(label1), + query.conditionValues(HugeKeys.LABEL)); + Assert.assertEquals(label1, query.conditionValue(HugeKeys.LABEL)); Assert.assertEquals(label1, query.condition(HugeKeys.LABEL)); } + @Test + public void testConditionWithSingleInValues() { + Id label1 = IdGenerator.of(1); + Id label2 = IdGenerator.of(2); + + ConditionQuery query = new ConditionQuery(HugeType.EDGE); + query.query(Condition.in(HugeKeys.LABEL, + ImmutableList.of(label1, label2))); + + Assert.assertTrue(query.containsCondition(HugeKeys.LABEL)); + Assert.assertEquals(ImmutableSet.of(label1, label2), + query.conditionValues(HugeKeys.LABEL)); + Assert.assertThrows(IllegalStateException.class, + () -> query.conditionValue(HugeKeys.LABEL), + e -> Assert.assertContains("Illegal key 'LABEL'", + e.getMessage())); + Assert.assertEquals(ImmutableList.of(label1, label2), + query.condition(HugeKeys.LABEL)); + } + @Test public void testConditionWithConflictingEqAndIn() { Id label1 = IdGenerator.of(1); @@ -73,6 +108,10 @@ public void testConditionWithConflictingEqAndIn() { query.query(Condition.in(HugeKeys.LABEL, ImmutableList.of(label1, label3))); + Assert.assertTrue(query.containsCondition(HugeKeys.LABEL)); + Assert.assertEquals(ImmutableSet.of(), + query.conditionValues(HugeKeys.LABEL)); + Assert.assertNull(query.conditionValue(HugeKeys.LABEL)); Assert.assertNull(query.condition(HugeKeys.LABEL)); } @@ -89,6 +128,13 @@ public void testConditionWithMultipleMatchedInValues() { query.query(Condition.in(HugeKeys.LABEL, ImmutableList.of(label1, label2, label4))); + Assert.assertTrue(query.containsCondition(HugeKeys.LABEL)); + Assert.assertEquals(ImmutableSet.of(label1, label2), + query.conditionValues(HugeKeys.LABEL)); + Assert.assertThrows(IllegalStateException.class, + () -> query.conditionValue(HugeKeys.LABEL), + e -> Assert.assertContains("Illegal key 'LABEL'", + e.getMessage())); Assert.assertThrows(IllegalStateException.class, () -> query.condition(HugeKeys.LABEL), e -> Assert.assertContains("Illegal key 'LABEL'", From 43d45410415ad1557735d1c274f1be0f274c5d3b Mon Sep 17 00:00:00 2001 From: contrueCT Date: Mon, 13 Apr 2026 22:08:29 +0800 Subject: [PATCH 2/2] test(core): avoid unnecessary data setup in label index regression --- .../main/java/org/apache/hugegraph/core/VertexCoreTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java index 786e204ec2..6462d0d9ec 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java @@ -8941,9 +8941,6 @@ public void testQueryByJointLabels() { public void testCollectMatchedIndexesByJointLabelsWithIndexedProperties() { HugeGraph graph = graph(); initPersonIndex(true); - init5Persons(); - init5Computers(); - init10Vertices(); VertexLabel person = graph.vertexLabel("person"); VertexLabel computer = graph.vertexLabel("computer");