This is an automated email from the ASF dual-hosted git repository.
imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph.git
The following commit(s) were added to refs/heads/master by this push:
new 36811483a fix(server): filter index results before input ordering
(#3182)
36811483a is described below
commit 36811483a2040f70ca6923a288a8c28cad0086c0
Author: contrueCT <[email protected]>
AuthorDate: Thu Sep 3 20:50:23 2026 +0800
fix(server): filter index results before input ordering (#3182)
HStore does not sort these backend results by input IDs. HugeGraph
therefore restores input order with InputOrderIterator, which may prefetch the
next flattened subquery. That prefetch updates the shared origin query's
resultsFilter. Previously, record matching happened after input-order
restoration, so rows from subquery A could be checked with subquery B's filter.
---
.../hugegraph/auth/HugeFactoryAuthProxy.java | 12 ++-
.../backend/cache/CachedGraphTransaction.java | 14 ++-
.../hugegraph/backend/tx/GraphTransaction.java | 117 +++++++++++++++++----
.../hugegraph/backend/tx/GraphTransactionTest.java | 90 ++++++++++++++++
.../org/apache/hugegraph/core/EdgeCoreTest.java | 10 ++
.../org/apache/hugegraph/core/VertexCoreTest.java | 31 +++++-
.../org/apache/hugegraph/unit/UnitTestSuite.java | 2 +
.../unit/cache/CachedGraphTransactionTest.java | 65 ++++++++++++
8 files changed, 311 insertions(+), 30 deletions(-)
diff --git
a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java
b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java
index 93095e0e2..c9ce7cca4 100644
---
a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java
+++
b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java
@@ -262,17 +262,23 @@ public final class HugeFactoryAuthProxy {
"checkVertexExistIfCustomizedId",
"checkAggregateProperty",
"checkAggregateProperty",
"checkNonnullProperty",
"queryEdgesFromBackend",
+ "queryValidEdgesFromBackend",
"commitPartOfEdgeDeletions",
"optimizeQueries",
"checkVertexLabel", "checkId",
- "queryVerticesFromBackend",
"joinTxVertices",
+ "queryVerticesFromBackend",
+ "queryValidVerticesFromBackend",
"joinTxVertices",
"joinTxEdges",
"lockForUpdateProperty", "optimizeQuery",
"verifyVerticesConditionQuery",
"verifyEdgesConditionQuery",
"indexQuery",
"joinTxRecords", "propertyUpdated",
"parseEntry",
"traverseByLabel", "reset",
"queryVerticesByIds",
- "filterUnmatchedRecords",
"skipOffsetOrStopLimit",
+ "filterInvalidRecords",
"filterUnmatchedRecords",
+ "invalidRecord", "warnLeftRecord",
+ "skipOffsetOrStopLimit",
"filterExpiredResultFromFromBackend", "queryEdgesByIds",
- "matchEdgeSortKeys",
"rightResultFromIndexQuery");
+ "matchEdgeSortKeys",
"rightResultFromIndexQuery",
+ "queryNeedsPostFilter",
+ "conditionQueryNeedsPostFilter");
Reflection.registerFieldsToFilter(IndexableTransaction.class,
"$assertionsDisabled");
Reflection.registerMethodsToFilter(IndexableTransaction.class,
"indexTransaction",
"commit2Backend", "reset");
diff --git
a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java
b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java
index cf4384d81..1543d7315 100644
---
a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java
+++
b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java
@@ -318,7 +318,8 @@ public final class CachedGraphTransaction extends
GraphTransaction {
@Watched(prefix = "graphcache")
protected Iterator<HugeVertex> queryVerticesFromBackend(Query query) {
if (this.enableCacheVertex() &&
- query.idsSize() > 0 && query.conditionsSize() == 0) {
+ query.idsSize() > 0 && query.conditionsSize() == 0 &&
+ !queryNeedsPostFilter(query)) {
return this.queryVerticesByIds((IdQuery) query);
} else {
return super.queryVerticesFromBackend(query);
@@ -394,9 +395,9 @@ public final class CachedGraphTransaction extends
GraphTransaction {
return ramtable.query(query);
}
- if (!this.enableCacheEdge() || query.empty() ||
- query.paging() || query.bigCapacity()) {
- // Query all edges or query edges in paging, don't cache it
+ if (!this.enableCacheEdge() || query.empty() || query.paging() ||
+ query.bigCapacity() || queryNeedsPostFilter(query)) {
+ // Don't cache all-edge, paging, large, or post-filtered queries
return super.queryEdgesFromBackend(query);
}
@@ -420,6 +421,11 @@ public final class CachedGraphTransaction extends
GraphTransaction {
}
Iterator<HugeEdge> rs = super.queryEdgesFromBackend(query);
+ if (queryNeedsPostFilter(query)) {
+ // The backend query may promote query.optimized() through origin-
+ // query propagation, so re-check before caching
+ return rs;
+ }
/*
* Iterator can't be cached, caching list instead
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 0c962b11a..d47b2825c 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
@@ -844,8 +844,8 @@ public class GraphTransaction extends IndexableTransaction {
query.resetActualOffset();
- Iterator<HugeVertex> results = this.queryVerticesFromBackend(query);
- results = this.filterUnmatchedRecords(results, query);
+ Iterator<HugeVertex> results =
+ this.queryValidVerticesFromBackend(query);
@SuppressWarnings("unchecked")
Iterator<Vertex> r = (Iterator<Vertex>) joinTxVertices(query, results);
@@ -861,6 +861,7 @@ public class GraphTransaction extends IndexableTransaction {
Iterator<HugeVertex> vertices = new MapperIterator<>(entries,
this::parseEntry);
vertices = this.filterExpiredResultFromBackend(query, vertices);
+ vertices = this.filterUnmatchedRecords(vertices, query);
if (!this.store().features().supportsQuerySortByInputIds()) {
// There is no id in BackendEntry, so sort after deserialization
@@ -869,6 +870,11 @@ public class GraphTransaction extends IndexableTransaction
{
return vertices;
}
+ private Iterator<HugeVertex> queryValidVerticesFromBackend(Query query) {
+ Iterator<HugeVertex> results = this.queryVerticesFromBackend(query);
+ return this.filterInvalidRecords(results, query);
+ }
+
@Watched(prefix = "graph")
public HugeEdge addEdge(HugeEdge edge) {
this.checkOwnerThread();
@@ -1010,8 +1016,8 @@ public class GraphTransaction extends
IndexableTransaction {
query.resetActualOffset();
- Iterator<HugeEdge> results = this.queryEdgesFromBackend(query);
- results = this.filterUnmatchedRecords(results, query);
+ Iterator<HugeEdge> results =
+ this.queryValidEdgesFromBackend(query);
/*
* Without repeated edges if not querying by BOTH all edges
@@ -1079,6 +1085,11 @@ public class GraphTransaction extends
IndexableTransaction {
return queryEdgesFromBackendInternal(query);
}
+ private Iterator<HugeEdge> queryValidEdgesFromBackend(Query query) {
+ Iterator<HugeEdge> results = this.queryEdgesFromBackend(query);
+ return this.filterInvalidRecords(results, query);
+ }
+
private Iterator<HugeEdge> queryEdgesFromBackendInternal(Query query) {
assert query.resultType().isEdge();
@@ -1100,6 +1111,7 @@ public class GraphTransaction extends
IndexableTransaction {
});
edges = this.filterExpiredResultFromBackend(query, edges);
+ edges = this.filterUnmatchedRecords(edges, query);
if (!this.store().features().supportsQuerySortByInputIds()) {
// There is no id in BackendEntry, so sort after deserialization
@@ -1870,33 +1882,67 @@ public class GraphTransaction extends
IndexableTransaction {
}
}
+ private <T extends HugeElement> Iterator<T> filterInvalidRecords(
+ Iterator<T> results,
+ Query query) {
+ // Filter unused records
+ return new FilterIterator<>(results, elem -> {
+ warnLeftRecord(elem);
+ return !invalidRecord(elem, query);
+ });
+ }
+
private <T extends HugeElement> Iterator<T> filterUnmatchedRecords(
Iterator<T> results,
Query query) {
- // Filter unused or incorrect records
+ /*
+ * Filter against the current index sub-query before restoring input
+ * order, since the order iterator may prefetch the next sub-query and
+ * update the results filter of the origin query.
+ * FilterIterator tests and buffers each element before its upstream
+ * iterator is advanced again, so the element is always tested with
+ * the results filter of the sub-query that produced it.
+ */
return new FilterIterator<>(results, elem -> {
- // TODO: Left vertex/edge should to be auto removed via async task
- if (elem.schemaLabel().undefined()) {
- LOG.warn("Left record is found: id={}, label={},
properties={}",
- elem.id(), elem.schemaLabel().id(),
- elem.getPropertiesMap());
- }
- // Filter hidden results
- if (!query.showHidden() && Graph.Hidden.isHidden(elem.label())) {
- return false;
- }
- // Filter vertices/edges of deleting label
- if (elem.schemaLabel().status().deleting() &&
- !query.showDeleting()) {
- return false;
+ /*
+ * Preserve the original predicate order: hidden records and
+ * records of deleting labels must be handled by the downstream
+ * invalid-record filter without triggering left-index cleanup.
+ */
+ if (invalidRecord(elem, query)) {
+ return true;
}
// Process results that query from left index or primary-key
// Only index query will come here
- return query.resultType().isVertex() != elem.type().isVertex() ||
- rightResultFromIndexQuery(query, elem);
+ boolean matched =
+ query.resultType().isVertex() != elem.type().isVertex() ||
+ rightResultFromIndexQuery(query, elem);
+ if (!matched) {
+ warnLeftRecord(elem);
+ }
+ return matched;
});
}
+ private static boolean invalidRecord(HugeElement elem, Query query) {
+ // Filter hidden results
+ if (!query.showHidden() && Graph.Hidden.isHidden(elem.label())) {
+ return true;
+ }
+ // Filter vertices/edges of deleting label
+ return elem.schemaLabel().status().deleting() &&
+ !query.showDeleting();
+ }
+
+ private static void warnLeftRecord(HugeElement elem) {
+ // TODO: Left vertex/edge should to be auto removed via async task
+ if (elem.schemaLabel().undefined()) {
+ LOG.warn("Left record is found: id={}, label={}, properties={}",
+ elem.id(), elem.schemaLabel().id(),
+ elem.getPropertiesMap());
+ }
+ }
+
private boolean rightResultFromIndexQuery(Query query, HugeElement elem) {
/*
* If query is ConditionQuery or query.originQuery() is ConditionQuery
@@ -1930,7 +1976,7 @@ public class GraphTransaction extends
IndexableTransaction {
}
}
- if (cq.optimized() == OptimizedType.NONE || cq.test(elem)) {
+ if (!conditionQueryNeedsPostFilter(cq) || cq.test(elem)) {
if (cq.existLeftIndex(elem.id())) {
/*
* Both have correct and left index, wo should return true
@@ -1963,6 +2009,33 @@ public class GraphTransaction extends
IndexableTransaction {
return false;
}
+ protected static boolean queryNeedsPostFilter(Query query) {
+ while (query != null) {
+ if (query instanceof ConditionQuery) {
+ ConditionQuery cq = (ConditionQuery) query;
+ /*
+ * Search conditions need post-filtering even before query
+ * optimization marks the query with an optimized type.
+ */
+ boolean edgeIndexWithLabel =
+ cq.resultType().isEdge() &&
+ cq.optimized() == OptimizedType.INDEX &&
+ cq.condition(HugeKeys.LABEL) != null;
+ if (cq.hasSearchCondition() ||
+ (conditionQueryNeedsPostFilter(cq) &&
+ !edgeIndexWithLabel)) {
+ return true;
+ }
+ }
+ query = query.originQuery();
+ }
+ return false;
+ }
+
+ private static boolean conditionQueryNeedsPostFilter(ConditionQuery query)
{
+ return query.optimized() != OptimizedType.NONE;
+ }
+
private <T extends HugeElement> Iterator<T> filterExpiredResultFromBackend(
Query query, Iterator<T> results) {
if (this.store().features().supportsTtl() || query.showExpired()) {
diff --git
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java
new file mode 100644
index 000000000..85b3c0e76
--- /dev/null
+++
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hugegraph.backend.tx;
+
+import java.util.Collections;
+
+import org.apache.hugegraph.backend.id.Id;
+import org.apache.hugegraph.backend.id.IdGenerator;
+import org.apache.hugegraph.backend.query.Condition;
+import org.apache.hugegraph.backend.query.ConditionQuery;
+import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType;
+import org.apache.hugegraph.backend.query.IdQuery;
+import org.apache.hugegraph.backend.query.Query;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.type.HugeType;
+import org.apache.hugegraph.type.define.HugeKeys;
+import org.junit.Test;
+
+public class GraphTransactionTest {
+
+ @Test
+ public void testQueryNeedsPostFilter() {
+ Id key = IdGenerator.of(1);
+ ConditionQuery search = new ConditionQuery(HugeType.EDGE);
+ search.query(Condition.textContains(key, "word"));
+
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(search));
+ IdQuery searchIds = new IdQuery(search, IdGenerator.of(2));
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(searchIds));
+
+ ConditionQuery searchAny = new ConditionQuery(HugeType.EDGE);
+ searchAny.query(Condition.textContainsAny(
+ key, Collections.singleton("word")));
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(searchAny));
+
+ ConditionQuery exact = new ConditionQuery(HugeType.EDGE);
+ exact.query(Condition.eq(key, "word"));
+ Assert.assertFalse(GraphTransaction.queryNeedsPostFilter(exact));
+ exact.optimized(OptimizedType.INDEX_FILTER);
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(exact));
+
+ ConditionQuery index = new ConditionQuery(HugeType.EDGE);
+ index.query(Condition.eq(key, "word"));
+ index.optimized(OptimizedType.INDEX);
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(index));
+
+ ConditionQuery labelIndex = new ConditionQuery(HugeType.EDGE);
+ labelIndex.query(Condition.eq(HugeKeys.LABEL, IdGenerator.of(2)));
+ labelIndex.query(Condition.eq(key, "word"));
+ labelIndex.optimized(OptimizedType.INDEX);
+ Assert.assertFalse(GraphTransaction.queryNeedsPostFilter(labelIndex));
+ IdQuery labelIndexIds = new IdQuery(labelIndex, IdGenerator.of(2));
+
Assert.assertFalse(GraphTransaction.queryNeedsPostFilter(labelIndexIds));
+
+ ConditionQuery vertexLabelIndex =
+ new ConditionQuery(HugeType.VERTEX);
+ vertexLabelIndex.query(Condition.eq(HugeKeys.LABEL,
+ IdGenerator.of(2)));
+ vertexLabelIndex.query(Condition.eq(key, "word"));
+ vertexLabelIndex.optimized(OptimizedType.INDEX);
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(
+ vertexLabelIndex));
+
+ ConditionQuery primaryKey = new ConditionQuery(HugeType.VERTEX);
+ primaryKey.optimized(OptimizedType.PRIMARY_KEY);
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(primaryKey));
+
+ ConditionQuery sortKeys = new ConditionQuery(HugeType.EDGE);
+ sortKeys.query(Condition.eq(key, "word"));
+ sortKeys.optimized(OptimizedType.SORT_KEYS);
+ Assert.assertTrue(GraphTransaction.queryNeedsPostFilter(sortKeys));
+ Assert.assertFalse(GraphTransaction.queryNeedsPostFilter(
+ new Query(HugeType.EDGE)));
+ }
+}
diff --git
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java
index cbb2b7d04..fccb49513 100644
---
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java
+++
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java
@@ -5161,6 +5161,16 @@ public class EdgeCoreTest extends BaseCoreTest {
.toList();
Assert.assertEquals(2, edges.size());
+ edges = graph.traversal().E().hasLabel("authored")
+ .has("score", P.within(3, 4, 5))
+ .has("contribution", Text.contains("2"))
+ .toList();
+ Assert.assertEquals(2, edges.size());
+ assertContains(edges, "authored", james, book2,
+ "contribution", "1992 2 2", "score", 4);
+ assertContains(edges, "authored", james, book3,
+ "contribution", "1993 3 2", "score", 3);
+
edges = graph.traversal().E().hasLabel("authored")
.has("score", P.gt(3))
.has("contribution", Text.contains("3"))
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 9aa144542..80c4aef50 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
@@ -3348,6 +3348,25 @@ public class VertexCoreTest extends BaseCoreTest {
Assert.assertEquals(0, vertices.size());
}
+ @Test
+ public void testQueryByPrimaryValuesAndPropsWithCachedVertex() {
+ HugeGraph graph = graph();
+ Vertex vertex = graph.addVertex(T.label, "person",
+ "name", "marko", "age", 29,
+ "city", "Beijing");
+ this.commitTx();
+
+ Vertex cached = graph.vertices(vertex.id()).next();
+ Assert.assertEquals(vertex.id(), cached.id());
+
+ long count = graph.traversal().V().hasLabel("person")
+ .has("name", "marko")
+ .has("age", 30)
+ .count()
+ .next();
+ Assert.assertEquals(0L, count);
+ }
+
@Test
public void testQueryFilterByPropName() {
HugeGraph graph = graph();
@@ -5424,8 +5443,12 @@ public class VertexCoreTest extends BaseCoreTest {
graph.addVertex(T.label, "test", "name", "诚信文明",
"confirmType", 3, "type", 1, "kid", 3);
- this.mayCommitTx();
+ this.assertQueryByJointIndexesWithSearchAndTwoRangeIndexesAndWithin();
+ this.commitTx();
+ this.assertQueryByJointIndexesWithSearchAndTwoRangeIndexesAndWithin();
+ }
+ private void
assertQueryByJointIndexesWithSearchAndTwoRangeIndexesAndWithin() {
List<Vertex> vertices;
vertices = graph().traversal().V()
.has("type", 1)
@@ -5433,6 +5456,9 @@ public class VertexCoreTest extends BaseCoreTest {
.has("name", Text.contains("诚信"))
.toList();
Assert.assertEquals(3, vertices.size());
+ assertContains(vertices, T.label, "test", "kid", 1);
+ assertContains(vertices, T.label, "test", "kid", 2);
+ assertContains(vertices, T.label, "test", "kid", 3);
vertices = graph().traversal().V()
.has("type", 1)
@@ -5440,6 +5466,8 @@ public class VertexCoreTest extends BaseCoreTest {
.has("name", Text.contains("文明"))
.toList();
Assert.assertEquals(2, vertices.size());
+ assertContains(vertices, T.label, "test", "kid", 2);
+ assertContains(vertices, T.label, "test", "kid", 3);
vertices = graph().traversal().V()
.has("type", 0)
@@ -5447,6 +5475,7 @@ public class VertexCoreTest extends BaseCoreTest {
.has("name", Text.contains("诚信"))
.toList();
Assert.assertEquals(1, vertices.size());
+ assertContains(vertices, T.label, "test", "kid", 0);
}
@Test
diff --git
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java
index efc38395a..d48738b84 100644
---
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java
+++
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java
@@ -18,6 +18,7 @@
package org.apache.hugegraph.unit;
import org.apache.hugegraph.backend.tx.GraphIndexTransactionTest;
+import org.apache.hugegraph.backend.tx.GraphTransactionTest;
import org.apache.hugegraph.api.auth.GraphSpaceAuthPayloadTest;
import org.apache.hugegraph.api.auth.GraphSpaceGroupAPITest;
import org.apache.hugegraph.auth.StandardAuthManagerV2Test;
@@ -152,6 +153,7 @@ import org.junit.runners.Suite;
StandardHugeGraphClearBackendTest.class,
ConditionQueryFlattenTest.class,
GraphIndexTransactionTest.class,
+ GraphTransactionTest.class,
QueryTest.class,
QueryResultsTest.class,
RangeTest.class,
diff --git
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java
index b128f277c..e01a8d799 100644
---
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java
+++
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java
@@ -18,6 +18,8 @@
package org.apache.hugegraph.unit.cache;
import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -30,6 +32,10 @@ import org.apache.hugegraph.backend.cache.Cache;
import org.apache.hugegraph.backend.cache.CachedGraphTransaction;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
+import org.apache.hugegraph.backend.query.Condition;
+import org.apache.hugegraph.backend.query.ConditionQuery;
+import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType;
+import org.apache.hugegraph.backend.query.Query;
import org.apache.hugegraph.backend.store.BackendStoreProvider;
import org.apache.hugegraph.event.EventHub;
import org.apache.hugegraph.event.EventListener;
@@ -41,6 +47,7 @@ import org.apache.hugegraph.testutil.Assert;
import org.apache.hugegraph.testutil.Whitebox;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.IdStrategy;
+import org.apache.hugegraph.type.define.SchemaStatus;
import org.apache.hugegraph.unit.BaseUnitTest;
import org.apache.hugegraph.unit.FakeObjects;
import org.apache.hugegraph.util.Events;
@@ -521,6 +528,64 @@ public class CachedGraphTransactionTest extends
BaseUnitTest {
Assert.assertFalse(cache.queryEdgesByVertex(IdGenerator.of(2)).hasNext());
}
+ @Test
+ public void testPostFilterDefersDeletingLabelToInvalidFilter() {
+ HugeVertex vertex = this.newVertex(IdGenerator.of(1));
+ vertex.schemaLabel().status(SchemaStatus.DELETING);
+
+ Id name = this.graph.propertyKey("name").id();
+ ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
+ query.query(Condition.eq(name, "marko"));
+ query.optimized(OptimizedType.INDEX);
+
+ Class<?>[] classes = new Class<?>[]{Iterator.class, Query.class};
+ Iterator<HugeVertex> unmatched = Whitebox.invoke(
+ CachedGraphTransaction.class, classes,
+ "filterUnmatchedRecords", this.cache,
+ Collections.singleton(vertex).iterator(), query);
+ Assert.assertTrue(unmatched.hasNext());
+
+ Iterator<HugeVertex> invalid = Whitebox.invoke(
+ CachedGraphTransaction.class, classes,
+ "filterInvalidRecords", this.cache,
+ Collections.singleton(vertex).iterator(), query);
+ Assert.assertFalse(invalid.hasNext());
+ }
+
+ @Test
+ public void testQueryVertexByIdKeepsDeletingLabel() {
+ CachedGraphTransaction cache = this.cache();
+ HugeVertex v1 = this.newVertex(IdGenerator.of(1));
+ cache.addVertex(v1);
+ cache.commit();
+
+ v1.schemaLabel().status(SchemaStatus.DELETING);
+
+ Assert.assertTrue(cache.queryVertices(v1.id()).hasNext());
+ // Re-query to exercise cached records too
+ Assert.assertTrue(cache.queryVertices(v1.id()).hasNext());
+ }
+
+ @Test
+ public void testQueryEdgeByIdKeepsDeletingLabel() {
+ CachedGraphTransaction cache = this.cache();
+ HugeVertex v1 = this.newVertex(IdGenerator.of(1));
+ HugeVertex v2 = this.newVertex(IdGenerator.of(2));
+ cache.addVertex(v1);
+ cache.addVertex(v2);
+ cache.commit();
+
+ HugeEdge edge = this.newEdge(v1, v2);
+ cache.addEdge(edge);
+ cache.commit();
+
+ edge.schemaLabel().status(SchemaStatus.DELETING);
+
+ Assert.assertTrue(cache.queryEdges(edge.id()).hasNext());
+ // Re-query to exercise cached records too
+ Assert.assertTrue(cache.queryEdges(edge.id()).hasNext());
+ }
+
@Test
public void testEdgeCacheClearWhenUpdateVertex() {
CachedGraphTransaction cache = this.cache();