1 /*******************************************************************************
2 * Copyright (c) 2007, 2018 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.impl.query;
14 import org.simantics.db.RelationInfo;
15 import org.simantics.db.common.exception.DebugException;
16 import org.simantics.db.exception.DatabaseException;
17 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
18 import org.simantics.db.impl.graph.ReadGraphImpl;
19 import org.simantics.db.impl.procedure.InternalProcedure;
20 import org.simantics.db.impl.procedure.TripleIntProcedureAdapter;
21 import org.simantics.db.procedure.ListenerBase;
22 import org.simantics.db.request.RequestFlags;
24 public final class Statements extends CollectionBinaryQuery<TripleIntProcedure> implements TripleIntProcedure {
26 public Statements(final int r1, final int r2) {
30 final public static void queryEach(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final TripleIntProcedure procedure) throws DatabaseException {
35 if(parent == null && listener == null) {
36 Statements.computeForEach(graph, r1, r2, null, procedure);
40 QueryCache.runnerStatements(graph, r1, r2, parent, listener, procedure);
45 final public void removeEntry(QueryProcessor provider) {
46 provider.cache.remove(this);
49 final static TripleIntProcedure NOPT = new TripleIntProcedure() {
53 public void exception(ReadGraphImpl graph, Throwable throwable) {
57 public void execute(ReadGraphImpl graph, int s, int p, int o) {
61 public void finished(ReadGraphImpl graph) {
66 final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Statements entry) throws DatabaseException {
68 class AssertionMapProc implements IntProcedure {
72 private IntArray result;
74 public void addStatement(int s, int p, int o) {
76 if(result.size() == 0) {
81 for(int i = 0;i < result.sizeOrData ; i+=3) {
82 int existingP = result.data[i+1];
84 int existingO = result.data[i+2];
85 if(existingO == o) return;
96 public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
98 result = QueryCache.resultAssertedStatements(graph, type, r2, entry, null);
101 IntArray ia = result;
102 result = new IntArray();
103 if(ia.data != null) {
104 for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
108 IntArray ia = QueryCache.resultAssertedStatements(graph, type, r2, entry, null);
109 if(ia.data != null) {
110 for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
116 public void finished(ReadGraphImpl graph) {
120 public void exception(ReadGraphImpl graph, Throwable throwable) {
125 AssertionMapProc amp = new AssertionMapProc();
127 // This dependency could be cut
128 QueryCache.runnerPrincipalTypes(graph, r1, entry, null, amp);
134 final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final TripleIntProcedure procedure) throws DatabaseException {
136 IntArray map = getAssertionMap(graph, r1, r2, parent);
138 procedure.finished(graph);
142 int size = map.size();
149 procedure.execute(graph, s,p,o);
150 procedure.finished(graph);
152 } else if(size == 0) {
154 procedure.finished(graph);
158 int candidateS = map.data[0];
159 int candidateP = map.data[1];
160 int candidateO = map.data[2];
162 IntSet candidateIs = null;
164 candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
165 } catch (DatabaseException e) {
166 procedure.exception(graph, e);
170 for(int i=3;i<map.size();i+=3) {
172 int nextS = map.data[i];
173 int nextP = map.data[i+1];
174 int nextO = map.data[i+2];
176 if(nextS != candidateS) {
178 if(candidateIs.contains(nextS)) {
180 // Next is a super type of candidate => ignore next
184 IntSet nextIs = null;
186 nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
187 } catch (DatabaseException e) {
188 procedure.exception(graph, e);
192 if(nextIs.contains(candidateS)) {
194 // Candidate is a super type of next => next is the new candidate
199 candidateIs = nextIs;
202 // candidate and next are unrelated => error
203 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions.", r1);
204 procedure.exception(graph, exception);
214 procedure.execute(graph, candidateS, candidateP, candidateO);
215 procedure.finished(graph);
221 final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
224 public void execute(ReadGraphImpl graph, IntSet result) {
228 public void exception(ReadGraphImpl graph, Throwable throwable) {
233 // Search for one statement
234 final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final RelationInfo ri, final TripleIntProcedure procedure) throws DatabaseException {
238 int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
242 // Check for assertions
243 forSingleAssertion(graph, r1, r2, parent, procedure);
245 } else if(result == -1) {
247 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
250 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
251 procedure.execute(graph, r1, r2, i);
255 public void exception(ReadGraphImpl graph, Throwable t) {
256 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
260 public void finished(ReadGraphImpl graph) {
265 // Check for assertions
266 forSingleAssertion(graph, r1, r2, parent, procedure);
270 // If functional relation was found there is no need to check assertions
271 procedure.execute(graph, r1, r2, result);
272 procedure.finished(graph);
279 // Note! The dependency is intentionally cut!
280 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
281 direct.forEach(graph, new SyncIntProcedure() {
291 public void run(ReadGraphImpl graph) throws DatabaseException {
295 procedure.finished(graph);
297 } else if(found == 0) {
299 // Check for assertions
300 forSingleAssertion(graph, r1, r2, parent, procedure);
307 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
314 // Note! The dependency is intentionally cut!
315 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
318 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
322 procedure.execute(graph, r1, pred, i);
327 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement.", r1);
328 procedure.exception(graph, exception);
336 public void finished(ReadGraphImpl graph) throws DatabaseException {
340 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
342 procedure.exception(graph, t);
351 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
354 public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
359 if(result.contains(r2)) {
363 // Note! The dependency is intentionally cut!
364 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
367 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
371 procedure.execute(graph, r1, pred, i);
376 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
377 procedure.exception(graph, exception);
385 public void finished(ReadGraphImpl graph) throws DatabaseException {
389 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
390 procedure.exception(graph, t);
401 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
402 procedure.exception(graph, t);
413 public void finished(ReadGraphImpl graph) throws DatabaseException {
423 final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final TripleIntProcedure procedure) throws DatabaseException {
425 QueryCache.runnerPrincipalTypes(graph, r1, parent, null, new SyncIntProcedure() {
428 public void run(ReadGraphImpl graph) throws DatabaseException {
429 procedure.finished(graph);
432 TripleIntProcedure proc = new TripleIntProcedureAdapter() {
435 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
436 procedure.execute(graph, s, p, o);
440 public void finished(ReadGraphImpl graph) throws DatabaseException {
445 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
447 procedure.exception(graph, t);
453 public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
455 QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
459 public void finished(ReadGraphImpl graph) throws DatabaseException {
464 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
473 final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final RelationInfo ri, final TripleIntProcedure procedure) throws DatabaseException {
477 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
480 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
481 procedure.execute(graph, r1, r2, i);
485 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
486 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
487 procedure.exception(graph, t);
491 public void finished(ReadGraphImpl graph) {
497 forAssertions(graph, r1, r2, parent, procedure);
499 procedure.finished(graph);
504 // Note! The dependency is intentionally cut!
505 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
506 direct.forEach(graph, new SyncIntProcedure() {
509 public void run(ReadGraphImpl graph) throws DatabaseException {
510 forAssertions(graph, r1, r2, parent, procedure);
514 public void execute(ReadGraphImpl graph, final int pred2) throws DatabaseException {
518 // Note! The dependency is intentionally cut!
519 QueryCache.runnerDirectObjects(graph, r1, pred2, null, null, new IntProcedure() {
522 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
523 procedure.execute(graph, r1, pred2, i);
527 public void finished(ReadGraphImpl graph) throws DatabaseException {
531 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
532 procedure.exception(graph, t);
541 IntSet result = QueryCache.resultSuperRelations(graph, pred2, parent, null);
542 if(result.contains(r2)) {
546 // Note! The dependency is intentionally cut!
547 QueryCache.runnerDirectObjects(graph, r1, pred2, null, null, new IntProcedure() {
550 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
551 procedure.execute(graph, r1, pred2, i);
556 public void finished(ReadGraphImpl graph) throws DatabaseException {
561 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
562 procedure.exception(graph, t);
570 } catch (Throwable e) {
571 procedure.exception(graph, e);
579 public void finished(ReadGraphImpl graph) throws DatabaseException {
589 public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Statements entry, final TripleIntProcedure procedure_) throws DatabaseException {
591 TripleIntProcedure procedure = entry != null ? entry : procedure_;
593 RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
594 graph.ensureLoaded(r1, r2);
595 if(ri.isFunctional) {
596 computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
598 computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
601 if(entry != null) entry.performFromCache(graph, procedure_);
606 public String toString() {
607 return "Statements[" + r1() + " - " + r2() + "]";
610 final private void finish(ReadGraphImpl graph, TripleIntProcedure procedure) throws DatabaseException {
612 assert(assertPending());
616 //new Exception(toString() + " is READY").printStackTrace();
619 IntArray v = (IntArray)getResult();
620 final IntArray value = (IntArray)getResult();
622 for(int i=0;i<value.size();i+=3) {
623 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
626 procedure.finished(graph);
630 synchronized public void addOrSet(int s, int p, int o) {
632 assert(assertPending());
634 IntArray value = (IntArray)getResult();
641 final static public int r1(long id) {
642 return (int)(id>>>32);
645 final static public int r2(long id) {
649 final public void addOrSetFunctional(int s, long po) {
651 addOrSetFunctional(s, r1(po), r2(po));
655 final public void addOrSetFunctional(int s, int p, int o) {
657 assert(assertPending());
659 IntArray value = (IntArray)getResult();
667 public Object performFromCache(ReadGraphImpl graph, final TripleIntProcedure procedure) throws DatabaseException {
671 final IntArray value = (IntArray)getResult();
673 if(handleException(graph, procedure)) return value;
675 for(int i=0;i<value.size();i+=3) {
676 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
679 procedure.finished(graph);
686 public void recompute(ReadGraphImpl graph) throws DatabaseException {
688 computeForEach(graph, r1(), r2(), this, new TripleIntProcedureAdapter() {
691 public void finished(ReadGraphImpl graph) {
695 public void exception(ReadGraphImpl graph, Throwable t) {
696 new Error("Error in recompute.", t).printStackTrace();
705 return RequestFlags.IMMEDIATE_UPDATE;
710 boolean isImmutable(ReadGraphImpl graph) {
711 return graph.processor.isImmutable(r1());
715 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
720 public void finished(ReadGraphImpl graph) throws DatabaseException {
725 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {