Strange query throws null pointer exception
Description
The following query throws a null pointer exception:
match
$x type entity;
$g isa gene, has official-gene-symbol $s;
not { $x type relation; $t isa tissue, has tissue-name "hello"; };
limit 10;
This is likely because of multiple type constraints on $x, as without them the query gives the expected response.
Environment
- OS (where TypeDB server runs): MacOS 12.6.1
- TypeDB version (and platform): TypeDB 2.18.0
- TypeDB client: Studio
Expected Output
Query either runs or throws a proper exception.
Actual Output
11:48:52.501 [typedb-service::0] ERROR com.vaticle.typedb.core.database.RocksStorage -
java.lang.NullPointerException: null
at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:351)
at com.vaticle.typedb.core.pattern.variable.Variable.setInferredTypes(Variable.java:96)
at com.vaticle.typedb.core.logic.tool.TypeInference$InferenceTraversal.lambda$applyTypes$13(TypeInference.java:238)
at java.base/java.util.HashMap.forEach(HashMap.java:1337)
at com.vaticle.typedb.core.logic.tool.TypeInference$InferenceTraversal.applyTypes(TypeInference.java:237)
at com.vaticle.typedb.core.logic.tool.TypeInference$InferenceTraversal.applyCombination(TypeInference.java:225)
at com.vaticle.typedb.core.logic.tool.TypeInference.applyCombination(TypeInference.java:110)
at com.vaticle.typedb.core.logic.tool.TypeInference.lambda$applyCombination$0(TypeInference.java:94)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at com.vaticle.typedb.core.logic.tool.TypeInference.applyCombination(TypeInference.java:94)
at com.vaticle.typedb.core.logic.tool.TypeInference.lambda$applyCombination$1(TypeInference.java:113)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1085)
at com.vaticle.typedb.core.logic.tool.TypeInference.applyCombination(TypeInference.java:113)
at com.vaticle.typedb.core.logic.tool.TypeInference.lambda$applyCombination$0(TypeInference.java:94)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at com.vaticle.typedb.core.logic.tool.TypeInference.applyCombination(TypeInference.java:94)
at com.vaticle.typedb.core.logic.tool.TypeInference.applyCombination(TypeInference.java:90)
at com.vaticle.typedb.core.reasoner.Reasoner.inferAndValidateTypes(Reasoner.java:136)
at com.vaticle.typedb.core.reasoner.Reasoner.execute(Reasoner.java:103)
at com.vaticle.typedb.core.query.Matcher.execute(Matcher.java:110)
at com.vaticle.typedb.core.query.Matcher.execute(Matcher.java:106)
at com.vaticle.typedb.core.query.QueryManager.match(QueryManager.java:72)
at com.vaticle.typedb.core.server.query.QueryService.match(QueryService.java:131)
at com.vaticle.typedb.core.server.query.QueryService.execute(QueryService.java:84)
at com.vaticle.typedb.core.server.TransactionService.executeRequest(TransactionService.java:178)
at com.vaticle.typedb.core.server.TransactionService.execute(TransactionService.java:153)
at com.vaticle.typedb.core.server.TransactionService.onNext(TransactionService.java:127)
at com.vaticle.typedb.core.server.TransactionService.onNext(TransactionService.java:82)
at io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener.onMessage(ServerCalls.java:262)
at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.messagesAvailableInternal(ServerCallImpl.java:318)
at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.messagesAvailable(ServerCallImpl.java:301)
at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1MessagesAvailable.runInContext(ServerImpl.java:834)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
11:48:52.507 [typedb-service::0] ERROR com.vaticle.typedb.core.server.TransactionService - java.lang.NullPointerException
Looks like this is caused by type inference not adding the offending variable (The $x inside the not) to the traversal.
The $x outside the not is added via restrictTypes in register(TypeVariable).
The $x inside loses its inferredTypes when the bounds are applied in applyCombination, so restrictTypes is not called on it. Since it's not in the traversal, applyTypes fails.
This would be solved if we could enforce that a type variable can at most one type constraint (currently, we don't seem to if the second type constraint is inside a not - Maybe we don't want to?)