aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-02 16:50:54 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-02 16:50:54 +0100
commit8cb6537188dd3ea3875798b35f07a5220f64dd21 (patch)
treeb3387b93e5c4036ee505d10fcfe7d1f16994645f
parentfeat: model query functional dependencies (diff)
downloadrefinery-8cb6537188dd3ea3875798b35f07a5220f64dd21.tar.gz
refinery-8cb6537188dd3ea3875798b35f07a5220f64dd21.tar.zst
refinery-8cb6537188dd3ea3875798b35f07a5220f64dd21.zip
feat: track ModelQuery pending changes
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java7
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java8
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java4
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java15
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java30
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java2
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java10
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java10
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java13
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java14
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java6
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java7
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java7
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java2
14 files changed, 87 insertions, 48 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java
index ecac570b..677e3c7d 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java
@@ -3,15 +3,14 @@ package tools.refinery.store.query.viatra;
3import tools.refinery.store.adapter.ModelAdapterBuilderFactory; 3import tools.refinery.store.adapter.ModelAdapterBuilderFactory;
4import tools.refinery.store.model.ModelStoreBuilder; 4import tools.refinery.store.model.ModelStoreBuilder;
5import tools.refinery.store.query.ModelQuery; 5import tools.refinery.store.query.ModelQuery;
6import tools.refinery.store.query.ModelQueryAdapter;
7import tools.refinery.store.query.viatra.internal.ViatraModelQueryBuilderImpl; 6import tools.refinery.store.query.viatra.internal.ViatraModelQueryBuilderImpl;
8 7
9public final class ViatraModelQuery extends ModelAdapterBuilderFactory<ModelQueryAdapter, ViatraModelQueryStoreAdapter, 8public final class ViatraModelQuery extends ModelAdapterBuilderFactory<ViatraModelQueryAdapter,
10 ViatraModelQueryBuilder> { 9 ViatraModelQueryStoreAdapter, ViatraModelQueryBuilder> {
11 public static final ViatraModelQuery ADAPTER = new ViatraModelQuery(); 10 public static final ViatraModelQuery ADAPTER = new ViatraModelQuery();
12 11
13 private ViatraModelQuery() { 12 private ViatraModelQuery() {
14 super(ModelQueryAdapter.class, ViatraModelQueryStoreAdapter.class, ViatraModelQueryBuilder.class); 13 super(ViatraModelQueryAdapter.class, ViatraModelQueryStoreAdapter.class, ViatraModelQueryBuilder.class);
15 extendsAdapter(ModelQuery.ADAPTER); 14 extendsAdapter(ModelQuery.ADAPTER);
16 } 15 }
17 16
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java
new file mode 100644
index 00000000..7e21476b
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java
@@ -0,0 +1,8 @@
1package tools.refinery.store.query.viatra;
2
3import tools.refinery.store.query.ModelQueryAdapter;
4
5public interface ViatraModelQueryAdapter extends ModelQueryAdapter {
6 @Override
7 ViatraModelQueryStoreAdapter getStoreAdapter();
8}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java
index d52575d2..1ee02f12 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java
@@ -1,8 +1,12 @@
1package tools.refinery.store.query.viatra; 1package tools.refinery.store.query.viatra;
2 2
3import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; 3import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions;
4import tools.refinery.store.model.Model;
4import tools.refinery.store.query.ModelQueryStoreAdapter; 5import tools.refinery.store.query.ModelQueryStoreAdapter;
5 6
6public interface ViatraModelQueryStoreAdapter extends ModelQueryStoreAdapter { 7public interface ViatraModelQueryStoreAdapter extends ModelQueryStoreAdapter {
7 ViatraQueryEngineOptions getEngineOptions(); 8 ViatraQueryEngineOptions getEngineOptions();
9
10 @Override
11 ViatraModelQueryAdapter createModelAdapter(Model model);
8} 12}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java
index b4d43ef8..8328e759 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java
@@ -5,25 +5,18 @@ import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
5import org.eclipse.viatra.query.runtime.api.scope.IEngineContext; 5import org.eclipse.viatra.query.runtime.api.scope.IEngineContext;
6import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener; 6import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener;
7import org.eclipse.viatra.query.runtime.api.scope.QueryScope; 7import org.eclipse.viatra.query.runtime.api.scope.QueryScope;
8import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.query.viatra.internal.context.RelationalEngineContext; 8import tools.refinery.store.query.viatra.internal.context.RelationalEngineContext;
11import tools.refinery.store.query.view.AnyRelationView;
12
13import java.util.Map;
14 9
15public class RelationalScope extends QueryScope { 10public class RelationalScope extends QueryScope {
16 private final Model model; 11 private final ViatraModelQueryAdapterImpl adapter;
17 private final Map<AnyRelationView, IInputKey> relationViews;
18 12
19 public RelationalScope(Model model, Map<AnyRelationView, IInputKey> relationViews) { 13 public RelationalScope(ViatraModelQueryAdapterImpl adapter) {
20 this.model = model; 14 this.adapter = adapter;
21 this.relationViews = relationViews;
22 } 15 }
23 16
24 @Override 17 @Override
25 protected IEngineContext createEngineContext(ViatraQueryEngine engine, IIndexingErrorListener errorListener, 18 protected IEngineContext createEngineContext(ViatraQueryEngine engine, IIndexingErrorListener errorListener,
26 Logger logger) { 19 Logger logger) {
27 return new RelationalEngineContext(model, relationViews); 20 return new RelationalEngineContext(adapter);
28 } 21 }
29} 22}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java
index 810d2c32..039f46fa 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java
@@ -8,15 +8,17 @@ import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; 8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
9import tools.refinery.store.model.Model; 9import tools.refinery.store.model.Model;
10import tools.refinery.store.query.DNF; 10import tools.refinery.store.query.DNF;
11import tools.refinery.store.query.ModelQueryAdapter;
12import tools.refinery.store.query.ModelQueryStoreAdapter;
13import tools.refinery.store.query.ResultSet; 11import tools.refinery.store.query.ResultSet;
12import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
14 13
15import java.lang.invoke.MethodHandle; 14import java.lang.invoke.MethodHandle;
16import java.lang.invoke.MethodHandles; 15import java.lang.invoke.MethodHandles;
17import java.util.*; 16import java.util.Collection;
17import java.util.Collections;
18import java.util.HashMap;
19import java.util.Map;
18 20
19public class ViatraModelQueryAdapterImpl implements ModelQueryAdapter { 21public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter {
20 private static final String DELAY_MESSAGE_DELIVERY_FIELD_NAME = "delayMessageDelivery"; 22 private static final String DELAY_MESSAGE_DELIVERY_FIELD_NAME = "delayMessageDelivery";
21 private static final String QUERY_BACKENDS_FIELD_NAME = "queryBackends"; 23 private static final String QUERY_BACKENDS_FIELD_NAME = "queryBackends";
22 24
@@ -26,11 +28,12 @@ public class ViatraModelQueryAdapterImpl implements ModelQueryAdapter {
26 private final MethodHandle setUpdatePropagationDelayedHandle; 28 private final MethodHandle setUpdatePropagationDelayedHandle;
27 private final MethodHandle getQueryBackendsHandle; 29 private final MethodHandle getQueryBackendsHandle;
28 private final Map<DNF, ResultSet> resultSets; 30 private final Map<DNF, ResultSet> resultSets;
31 private boolean pendingChanges;
29 32
30 ViatraModelQueryAdapterImpl(Model model, ViatraModelQueryStoreAdapterImpl storeAdapter) { 33 ViatraModelQueryAdapterImpl(Model model, ViatraModelQueryStoreAdapterImpl storeAdapter) {
31 this.model = model; 34 this.model = model;
32 this.storeAdapter = storeAdapter; 35 this.storeAdapter = storeAdapter;
33 var scope = new RelationalScope(model, storeAdapter.getInputKeys()); 36 var scope = new RelationalScope(this);
34 queryEngine = (ViatraQueryEngineImpl) AdvancedViatraQueryEngine.createUnmanagedEngine(scope); 37 queryEngine = (ViatraQueryEngineImpl) AdvancedViatraQueryEngine.createUnmanagedEngine(scope);
35 38
36 try { 39 try {
@@ -87,7 +90,7 @@ public class ViatraModelQueryAdapterImpl implements ModelQueryAdapter {
87 } 90 }
88 91
89 @Override 92 @Override
90 public ModelQueryStoreAdapter getStoreAdapter() { 93 public ViatraModelQueryStoreAdapterImpl getStoreAdapter() {
91 return storeAdapter; 94 return storeAdapter;
92 } 95 }
93 96
@@ -101,10 +104,24 @@ public class ViatraModelQueryAdapterImpl implements ModelQueryAdapter {
101 } 104 }
102 105
103 @Override 106 @Override
107 public boolean hasPendingChanges() {
108 return pendingChanges;
109 }
110
111 public void markAsPending() {
112 if (!pendingChanges) {
113 pendingChanges = true;
114 }
115 }
116
117 @Override
104 public void flushChanges() { 118 public void flushChanges() {
105 if (!queryEngine.isUpdatePropagationDelayed()) { 119 if (!queryEngine.isUpdatePropagationDelayed()) {
106 throw new IllegalStateException("Trying to flush changes while changes are already being flushed"); 120 throw new IllegalStateException("Trying to flush changes while changes are already being flushed");
107 } 121 }
122 if (!pendingChanges) {
123 return;
124 }
108 setUpdatePropagationDelayed(false); 125 setUpdatePropagationDelayed(false);
109 try { 126 try {
110 for (var queryBackend : getQueryBackends()) { 127 for (var queryBackend : getQueryBackends()) {
@@ -113,5 +130,6 @@ public class ViatraModelQueryAdapterImpl implements ModelQueryAdapter {
113 } finally { 130 } finally {
114 setUpdatePropagationDelayed(true); 131 setUpdatePropagationDelayed(true);
115 } 132 }
133 pendingChanges = false;
116 } 134 }
117} 135}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java
index 69f1f146..394e407e 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java
@@ -37,7 +37,7 @@ public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAd
37 return inputKeys.keySet(); 37 return inputKeys.keySet();
38 } 38 }
39 39
40 Map<AnyRelationView, IInputKey> getInputKeys() { 40 public Map<AnyRelationView, IInputKey> getInputKeys() {
41 return inputKeys; 41 return inputKeys;
42 } 42 }
43 43
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java
index 3bad01b9..28bc69d0 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java
@@ -2,19 +2,15 @@ package tools.refinery.store.query.viatra.internal.context;
2 2
3import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex; 3import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex;
4import org.eclipse.viatra.query.runtime.api.scope.IEngineContext; 4import org.eclipse.viatra.query.runtime.api.scope.IEngineContext;
5import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
6import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext; 5import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
7import tools.refinery.store.model.Model; 6import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
8import tools.refinery.store.query.view.AnyRelationView;
9
10import java.util.Map;
11 7
12public class RelationalEngineContext implements IEngineContext { 8public class RelationalEngineContext implements IEngineContext {
13 private final IBaseIndex baseIndex = new DummyBaseIndexer(); 9 private final IBaseIndex baseIndex = new DummyBaseIndexer();
14 private final RelationalRuntimeContext runtimeContext; 10 private final RelationalRuntimeContext runtimeContext;
15 11
16 public RelationalEngineContext(Model model, Map< AnyRelationView, IInputKey> inputKeys) { 12 public RelationalEngineContext(ViatraModelQueryAdapterImpl adapter) {
17 runtimeContext = new RelationalRuntimeContext(model, inputKeys); 13 runtimeContext = new RelationalRuntimeContext(adapter);
18 } 14 }
19 15
20 @Override 16 @Override
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java
index 71ab5cb4..01d20d3e 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java
@@ -7,13 +7,13 @@ import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
7import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 7import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
8import org.eclipse.viatra.query.runtime.matchers.util.Accuracy; 8import org.eclipse.viatra.query.runtime.matchers.util.Accuracy;
9import tools.refinery.store.model.Model; 9import tools.refinery.store.model.Model;
10import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
10import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; 11import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper;
11import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener; 12import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener;
12import tools.refinery.store.query.view.AnyRelationView; 13import tools.refinery.store.query.view.AnyRelationView;
13 14
14import java.lang.reflect.InvocationTargetException; 15import java.lang.reflect.InvocationTargetException;
15import java.util.Iterator; 16import java.util.Iterator;
16import java.util.Map;
17import java.util.Optional; 17import java.util.Optional;
18import java.util.concurrent.Callable; 18import java.util.concurrent.Callable;
19 19
@@ -27,10 +27,10 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext {
27 27
28 private final Model model; 28 private final Model model;
29 29
30 RelationalRuntimeContext(Model model, Map<AnyRelationView, IInputKey> inputKeys) { 30 RelationalRuntimeContext(ViatraModelQueryAdapterImpl adapter) {
31 this.model = model; 31 model = adapter.getModel();
32 metaContext = new RelationalQueryMetaContext(inputKeys); 32 metaContext = new RelationalQueryMetaContext(adapter.getStoreAdapter().getInputKeys());
33 modelUpdateListener = new ModelUpdateListener(model, inputKeys.keySet()); 33 modelUpdateListener = new ModelUpdateListener(adapter);
34 } 34 }
35 35
36 @Override 36 @Override
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java
index 1ae3daa7..8a467066 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java
@@ -3,26 +3,27 @@ package tools.refinery.store.query.viatra.internal.update;
3import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; 3import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
4import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; 4import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
5import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; 5import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
6import tools.refinery.store.model.Model; 6import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
7import tools.refinery.store.query.view.AnyRelationView; 7import tools.refinery.store.query.view.AnyRelationView;
8import tools.refinery.store.query.view.RelationView; 8import tools.refinery.store.query.view.RelationView;
9 9
10import java.util.Collection;
11import java.util.HashMap; 10import java.util.HashMap;
12import java.util.Map; 11import java.util.Map;
13 12
14public class ModelUpdateListener { 13public class ModelUpdateListener {
15 private final Map<AnyRelationView, RelationViewUpdateListener<?>> relationViewUpdateListeners; 14 private final Map<AnyRelationView, RelationViewUpdateListener<?>> relationViewUpdateListeners;
16 15
17 public ModelUpdateListener(Model model, Collection<AnyRelationView> relationViews) { 16 public ModelUpdateListener(ViatraModelQueryAdapterImpl adapter) {
17 var relationViews = adapter.getStoreAdapter().getInputKeys().keySet();
18 relationViewUpdateListeners = new HashMap<>(relationViews.size()); 18 relationViewUpdateListeners = new HashMap<>(relationViews.size());
19 for (var relationView : relationViews) { 19 for (var relationView : relationViews) {
20 registerView(model, (RelationView<?>) relationView); 20 registerView(adapter, (RelationView<?>) relationView);
21 } 21 }
22 } 22 }
23 23
24 private <T> void registerView(Model model, RelationView<T> relationView) { 24 private <T> void registerView(ViatraModelQueryAdapterImpl adapter, RelationView<T> relationView) {
25 var listener = RelationViewUpdateListener.of(relationView); 25 var listener = RelationViewUpdateListener.of(adapter, relationView);
26 var model = adapter.getModel();
26 var interpretation = model.getInterpretation(relationView.getSymbol()); 27 var interpretation = model.getInterpretation(relationView.getSymbol());
27 interpretation.addListener(listener, true); 28 interpretation.addListener(listener, true);
28 relationViewUpdateListeners.put(relationView, listener); 29 relationViewUpdateListeners.put(relationView, listener);
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java
index e0d44e34..bf6b4197 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java
@@ -5,6 +5,7 @@ import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextLis
5import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; 5import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
6import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; 6import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
7import tools.refinery.store.model.InterpretationListener; 7import tools.refinery.store.model.InterpretationListener;
8import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
8import tools.refinery.store.query.view.RelationView; 9import tools.refinery.store.query.view.RelationView;
9import tools.refinery.store.query.view.TuplePreservingRelationView; 10import tools.refinery.store.query.view.TuplePreservingRelationView;
10 11
@@ -12,8 +13,13 @@ import java.util.ArrayList;
12import java.util.List; 13import java.util.List;
13 14
14public abstract class RelationViewUpdateListener<T> implements InterpretationListener<T> { 15public abstract class RelationViewUpdateListener<T> implements InterpretationListener<T> {
16 private final ViatraModelQueryAdapterImpl adapter;
15 private final List<RelationViewFilter> filters = new ArrayList<>(); 17 private final List<RelationViewFilter> filters = new ArrayList<>();
16 18
19 protected RelationViewUpdateListener(ViatraModelQueryAdapterImpl adapter) {
20 this.adapter = adapter;
21 }
22
17 public void addFilter(IInputKey inputKey, ITuple seed, IQueryRuntimeContextListener listener) { 23 public void addFilter(IInputKey inputKey, ITuple seed, IQueryRuntimeContextListener listener) {
18 filters.add(new RelationViewFilter(inputKey, seed, listener)); 24 filters.add(new RelationViewFilter(inputKey, seed, listener));
19 } 25 }
@@ -23,6 +29,7 @@ public abstract class RelationViewUpdateListener<T> implements InterpretationLis
23 } 29 }
24 30
25 protected void processUpdate(Tuple tuple, boolean isInsertion) { 31 protected void processUpdate(Tuple tuple, boolean isInsertion) {
32 adapter.markAsPending();
26 int size = filters.size(); 33 int size = filters.size();
27 // Use a for loop instead of a for-each loop to avoid <code>Iterator</code> allocation overhead. 34 // Use a for loop instead of a for-each loop to avoid <code>Iterator</code> allocation overhead.
28 //noinspection ForLoopReplaceableByForEach 35 //noinspection ForLoopReplaceableByForEach
@@ -31,10 +38,11 @@ public abstract class RelationViewUpdateListener<T> implements InterpretationLis
31 } 38 }
32 } 39 }
33 40
34 public static <T> RelationViewUpdateListener<T> of(RelationView<T> relationView) { 41 public static <T> RelationViewUpdateListener<T> of(ViatraModelQueryAdapterImpl adapter,
42 RelationView<T> relationView) {
35 if (relationView instanceof TuplePreservingRelationView<T> tuplePreservingRelationView) { 43 if (relationView instanceof TuplePreservingRelationView<T> tuplePreservingRelationView) {
36 return new TuplePreservingRelationViewUpdateListener<>(tuplePreservingRelationView); 44 return new TuplePreservingRelationViewUpdateListener<>(adapter, tuplePreservingRelationView);
37 } 45 }
38 return new TupleChangingRelationViewUpdateListener<>(relationView); 46 return new TupleChangingRelationViewUpdateListener<>(adapter, relationView);
39 } 47 }
40} 48}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java
index 0d43eac1..14142884 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java
@@ -1,6 +1,7 @@
1package tools.refinery.store.query.viatra.internal.update; 1package tools.refinery.store.query.viatra.internal.update;
2 2
3import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 3import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
4import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
4import tools.refinery.store.query.view.RelationView; 5import tools.refinery.store.query.view.RelationView;
5import tools.refinery.store.tuple.Tuple; 6import tools.refinery.store.tuple.Tuple;
6 7
@@ -9,8 +10,9 @@ import java.util.Arrays;
9public class TupleChangingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> { 10public class TupleChangingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> {
10 private final RelationView<T> relationView; 11 private final RelationView<T> relationView;
11 12
12 TupleChangingRelationViewUpdateListener(RelationView<T> relationView) { 13 TupleChangingRelationViewUpdateListener(ViatraModelQueryAdapterImpl adapter, RelationView<T> relationView) {
13 this.relationView = relationView; 14 super(adapter);
15 this.relationView = relationView;
14 } 16 }
15 17
16 @Override 18 @Override
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java
index 9c3ef61c..288e018a 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java
@@ -1,14 +1,17 @@
1package tools.refinery.store.query.viatra.internal.update; 1package tools.refinery.store.query.viatra.internal.update;
2 2
3import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 3import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
4import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
4import tools.refinery.store.query.view.TuplePreservingRelationView; 5import tools.refinery.store.query.view.TuplePreservingRelationView;
5import tools.refinery.store.tuple.Tuple; 6import tools.refinery.store.tuple.Tuple;
6 7
7public class TuplePreservingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> { 8public class TuplePreservingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> {
8 private final TuplePreservingRelationView<T> view; 9 private final TuplePreservingRelationView<T> view;
9 10
10 TuplePreservingRelationViewUpdateListener(TuplePreservingRelationView<T> view) { 11 TuplePreservingRelationViewUpdateListener(ViatraModelQueryAdapterImpl adapter,
11 this.view = view; 12 TuplePreservingRelationView<T> view) {
13 super(adapter);
14 this.view = view;
12 } 15 }
13 16
14 @Override 17 @Override
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java
index 49087a8d..ec2e7647 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java
@@ -10,7 +10,7 @@ import tools.refinery.store.query.view.KeyOnlyRelationView;
10import tools.refinery.store.representation.Symbol; 10import tools.refinery.store.representation.Symbol;
11import tools.refinery.store.tuple.Tuple; 11import tools.refinery.store.tuple.Tuple;
12 12
13import static org.junit.jupiter.api.Assertions.assertEquals; 13import static org.junit.jupiter.api.Assertions.*;
14 14
15class QueryTransactionTest { 15class QueryTransactionTest {
16 @Test 16 @Test
@@ -38,6 +38,7 @@ class QueryTransactionTest {
38 var predicateResultSet = queryEngine.getResultSet(predicate); 38 var predicateResultSet = queryEngine.getResultSet(predicate);
39 39
40 assertEquals(0, predicateResultSet.countResults()); 40 assertEquals(0, predicateResultSet.countResults());
41 assertFalse(queryEngine.hasPendingChanges());
41 42
42 personInterpretation.put(Tuple.of(0), true); 43 personInterpretation.put(Tuple.of(0), true);
43 personInterpretation.put(Tuple.of(1), true); 44 personInterpretation.put(Tuple.of(1), true);
@@ -46,14 +47,18 @@ class QueryTransactionTest {
46 assetInterpretation.put(Tuple.of(2), true); 47 assetInterpretation.put(Tuple.of(2), true);
47 48
48 assertEquals(0, predicateResultSet.countResults()); 49 assertEquals(0, predicateResultSet.countResults());
50 assertTrue(queryEngine.hasPendingChanges());
49 51
50 queryEngine.flushChanges(); 52 queryEngine.flushChanges();
51 assertEquals(2, predicateResultSet.countResults()); 53 assertEquals(2, predicateResultSet.countResults());
54 assertFalse(queryEngine.hasPendingChanges());
52 55
53 personInterpretation.put(Tuple.of(4), true); 56 personInterpretation.put(Tuple.of(4), true);
54 assertEquals(2, predicateResultSet.countResults()); 57 assertEquals(2, predicateResultSet.countResults());
58 assertTrue(queryEngine.hasPendingChanges());
55 59
56 queryEngine.flushChanges(); 60 queryEngine.flushChanges();
57 assertEquals(3, predicateResultSet.countResults()); 61 assertEquals(3, predicateResultSet.countResults());
62 assertFalse(queryEngine.hasPendingChanges());
58 } 63 }
59} 64}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java
index d0cdf02d..7449e39b 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java
@@ -7,5 +7,7 @@ public interface ModelQueryAdapter extends ModelAdapter {
7 7
8 ResultSet getResultSet(DNF query); 8 ResultSet getResultSet(DNF query);
9 9
10 boolean hasPendingChanges();
11
10 void flushChanges(); 12 void flushChanges();
11} 13}