When using RelationType.set_relates(transaction, "role", "superrole") where the relation type already has a role with name role, the method executes succesfully and the transaction is committed, but then any future attempts to read the role (tested with Database.schema and with the Studio type browser) throw a null pointer exception.
Environment
TypeDB distribution: Core
TypeDB version: 2.25.7
Environment: MacOS
Driver version: Python 2.26.1
Reproducible Steps
Run following code:
database = "social-media"
with TypeDB.core_driver("localhost:1729") as driver:
driver.databases.create(database)
with driver.session(database, SessionType.SCHEMA) as session:
with session.transaction(TransactionType.WRITE) as transaction:
person = transaction.concepts.put_entity_type("person").resolve()
marriage = transaction.concepts.put_relation_type("marriage").resolve()
marriage.set_relates(transaction, "spouse").resolve()
spouse = marriage.get_relates(transaction, "spouse").resolve()
person.set_plays(transaction, spouse).resolve()
dating = transaction.concepts.put_relation_type("dating").resolve()
dating.set_relates(transaction, "partner").resolve()
partner = dating.get_relates(transaction, "partner").resolve()
person.set_plays(transaction, partner).resolve()
transaction.commit()
print(driver.databases.get(database).schema())
with session.transaction(TransactionType.WRITE) as transaction:
relationship = transaction.concepts.put_relation_type("relationship").resolve()
relationship.set_relates(transaction, "related").resolve()
marriage = transaction.concepts.get_relation_type("marriage").resolve()
marriage.set_supertype(transaction, relationship).resolve()
marriage.set_relates(transaction, "spouse", "related").resolve()
dating = transaction.concepts.get_relation_type("dating").resolve()
dating.set_supertype(transaction, relationship).resolve()
dating.set_relates(transaction, "partner", "related").resolve()
transaction.commit()
with TypeDB.core_driver("localhost:1729") as driver:
print(driver.databases.get(database).schema())
Expected result
Either:
The existing role is correctly made a subtype of the superrole.
An error is thrown and the transaction is rolled back.
The first outcome is preferable, because otherwise there is currently no way to reassign the supertype of an existing role.
Additional information
Relevant logs from TypeDB or Driver:
Dec 20, 2023 12:24:26 PM io.grpc.internal.SerializingExecutor run
SEVERE: Exception while executing runnable io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed@2904758a
java.lang.NullPointerException
at com.vaticle.typedb.core.graph.vertex.impl.TypeVertexImpl$Persisted.<init>(TypeVertexImpl.java:409)
at com.vaticle.typedb.core.graph.TypeGraph.lambda$convert$51(TypeGraph.java:439)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705)
at com.vaticle.typedb.core.graph.TypeGraph.convert(TypeGraph.java:438)
at com.vaticle.typedb.core.graph.edge.impl.TypeEdgeImpl$Persisted.overridden(TypeEdgeImpl.java:489)
at com.vaticle.typedb.core.concept.type.impl.RelationTypeImpl.getRelatesOverridden(RelationTypeImpl.java:213)
at com.vaticle.typedb.core.concept.type.impl.RelationTypeImpl.lambda$writeRelates$19(RelationTypeImpl.java:307)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at com.vaticle.typedb.core.concept.type.impl.RelationTypeImpl.writeRelates(RelationTypeImpl.java:303)
at com.vaticle.typedb.core.concept.type.impl.RelationTypeImpl.getSyntax(RelationTypeImpl.java:297)
at com.vaticle.typedb.core.concept.type.impl.ThingTypeImpl.getSyntaxRecursive(ThingTypeImpl.java:159)
at com.vaticle.typedb.core.concept.type.impl.ThingTypeImpl.lambda$getSyntaxRecursive$1(ThingTypeImpl.java:162)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at com.vaticle.typedb.core.concept.type.impl.ThingTypeImpl.getSyntaxRecursive(ThingTypeImpl.java:162)
at com.vaticle.typedb.core.concept.ConceptManager.lambda$typesSyntax$18(ConceptManager.java:396)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at com.vaticle.typedb.core.concept.ConceptManager.typesSyntax(ConceptManager.java:396)
at com.vaticle.typedb.core.database.CoreDatabase.schema(CoreDatabase.java:443)
at com.vaticle.typedb.core.server.TypeDBService.databaseSchema(TypeDBService.java:263)
at com.vaticle.typedb.protocol.TypeDBGrpc$MethodHandlers.invoke(TypeDBGrpc.java:1553)
at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:182)
at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:355)
at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:867)
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:829)
Description
When using
RelationType.set_relates(transaction, "role", "superrole")
where the relation type already has a role with namerole
, the method executes succesfully and the transaction is committed, but then any future attempts to read the role (tested withDatabase.schema
and with the Studio type browser) throw a null pointer exception.Environment
Reproducible Steps
Run following code:
Expected result
Either:
The first outcome is preferable, because otherwise there is currently no way to reassign the supertype of an existing role.
Additional information
Relevant logs from TypeDB or Driver: