Schema editing
In this guide, you will learn how to edit the schema of your database without sending Define and Undefine queries. This page assumes you’ve already followed instructions from the Connecting to TypeDB section pages.
Understanding query-less editing
Besides using Define and Undefine queries, TypeDB also provides a program interface for editing the database schema directly. TypeDB clients and drivers may implement this interface. On this page, we discuss two yields additional ways of modifying the schema of a database in this way: with Studio’s Type Editor and with driver API methods.
To learn more about Define queries, see the Define query page.
TypeDB Studio’s Type Editor
Type Editor is a powerful instrument that combines easy to use GUI with API calls that can modify schema types directly, without TypeQL queries. With Type Editor, it’s much easier to rename a type or change type hierarchy by changing a supertype of a type. And it works even for types that already have data inserted for them.
Type Editor window gives you a full overview of the selected type: its label, parent, owned attributes, played roles, owners (for attributes), related roles (for relations), subtypes, and whether it’s an abstract type.
Type Editor can rename a type, change its supertype, change whether it’s an abstract type, add or remove owned attributes, related roles, played roles, as well as just delete a type or export its full definition.
For the Type Editor be able to modify a schema,
make sure to switch to the schema
session and write
transaction in the top toolbar.
Rename a type
To rename a type:
-
Open the Type Editor window by double-clicking on the selected type in the Type Browser.
-
At the very top, click on the pencil icon immediately right from the type name.
-
Edit the name in the Label field and press the Rename button to save the changes.
-
Commit the transaction by the Commit button at the top toolbar.
You can also do the same by right-clicking on the type in the Type Browser panel and choosing the Rename Type option.
Renaming a type in any of these two ways updates the relevant type references in the schema and does not lead to loosing existing data. All existing instances of the type will be available under the new label.
Delete a type
To delete a type:
-
Open the Type Editor window by double-clicking on the selected type in the Type Browser.
-
At the very bottom, click the Delete button and then the Confirm button.
-
Commit the transaction by the Commit button at the top toolbar.
You can also do the same by right-clicking on the type in the Type browser panel and choosing the Delete option, then clicking the Confirm button.
In some cases, the Delete option and button can be unavailable. That means there are some conditions that prevent you from deleting this type. For example, we can’t delete a type that has a subtype.
Schema edits with driver API
Driver API has methods can be used to work with schema types and rules. These methods can vary from driver to driver due to language-specific details.
Example
See below an example of schema manipulation using driver API methods: creating an attribute type (tag
),
retrieving the entity
root type, getting all subtypes of a type,
traversing all subtypes to assign ownership of the new attribute type, and committing the transaction.
-
Rust
-
Python
-
Node.js
-
Java
-
C#
-
C++
-
C
let db = databases.get(DB_NAME)?;
{
let session = Session::new(db, SessionType::Schema)?;
{
let tx = session.transaction(TransactionType::Write)?;
let tag = &tx.concept().put_attribute_type("tag".to_owned(), ValueType::String).resolve()?;
let entities = tx
.concept()
.get_entity_type("entity".to_owned())
.resolve()?
.ok_or("No root entity")?
.get_subtypes(&tx, Transitivity::Explicit)?;
for entity in entities {
let mut e = entity?;
println!("{}", e.label);
if !(e.is_abstract()) {
let _ = e.set_owns(&tx, tag.clone(), None, vec![]);
}
}
let _ = tx.commit().resolve();
}
}
For more details about these and other API methods, see the API reference.
with driver.session(DB_NAME, SessionType.SCHEMA) as session:
with session.transaction(TransactionType.WRITE) as tx:
tag = tx.concepts.put_attribute_type("tag", ValueType.STRING).resolve()
entities = tx.concepts.get_root_entity_type().get_subtypes(tx, Transitivity.EXPLICIT)
for entity in entities:
print(entity.get_label())
if not entity.is_abstract():
entity.set_owns(tx, tag).resolve()
tx.commit()
For more details about these and other API methods, see the API reference.
try {
session = await driver.session(DB_NAME, SessionType.SCHEMA);
try {
tx = await session.transaction(TransactionType.WRITE);
let tag = await tx.concepts.putAttributeType("tag", Concept.ValueType.STRING);
let rootEntity = await tx.concepts.getRootEntityType();
let entites = await rootEntity.getSubtypes(tx, Concept.Transitivity.EXPLICIT);
await entites.forEach(entity => entity.setOwns(tx, tag));
await tx.commit();
}
finally {if (tx.isOpen()) {await tx.close()};}
}
finally {await session?.close();}
For more details about these and other API methods, see the API reference.
try (TypeDBSession session = driver.session(DB_NAME, TypeDBSession.Type.SCHEMA)) {
try (TypeDBTransaction tx = session.transaction(TypeDBTransaction.Type.WRITE)) {
AttributeType tag = tx.concepts().putAttributeType("tag", Value.Type.STRING).resolve();
tx.concepts().getRootEntityType().getSubtypes(tx, Concept.Transitivity.EXPLICIT).forEach(result -> {
System.out.println(result.getLabel().toString());
if (! result.isAbstract()) {
result.setOwns(tx,tag).resolve();
}
});
tx.commit();
}
}
For more details about these and other API methods, see the API reference.
using (ITypeDBSession session = driver.Session(DB_NAME, SessionType.Schema)) {
using (ITypeDBTransaction tx = session.Transaction(TransactionType.Write)) {
IAttributeType tag = tx.Concepts.PutAttributeType("tag", IValue.ValueType.String).Resolve()!;
IEnumerable<IType> entities = tx.Concepts.RootEntityType.GetSubtypes(tx, IConcept.Transitivity.Explicit);
foreach (IType entity in entities) {
Console.WriteLine(entity.Label);
if (!entity.IsAbstract()) {
entity.AsThingType().SetOwns(tx, tag);
}
}
}
}
For more details about these and other API methods, see the API reference.
TypeDB::Session session = driver.session(DB_NAME, TypeDB::SessionType::SCHEMA, options);
{
TypeDB::Transaction tx = session.transaction(TypeDB::TransactionType::WRITE, options);
std::unique_ptr<TypeDB::AttributeType> tag = tx.concepts.putAttributeType("tag", TypeDB::ValueType::STRING).get();
TypeDB::ConceptIterable<TypeDB::EntityType> entities = tx.concepts.getRootEntityType().get()->getSubtypes(tx);
for (std::unique_ptr<TypeDB::EntityType>& entity : entities) {
std::cout << entity.get()->getLabel() << std::endl;
if (!(entity.get()->isAbstract())) {
(void) entity.get()->setOwns(tx, tag.get());
};
}
tx.commit();
}
For more details about these and other API methods, see the API reference.
session = session_new(databaseManager, DB_NAME, Schema, opts);
tx = transaction_new(session, Write, opts);
if ((tx == NULL) || FAILED()) {
handle_error("Transaction failed to start.");
goto cleanup;
}
Concept* tag = concept_promise_resolve(concepts_put_attribute_type(tx, "tag", String));
ConceptIterator* entities = entity_type_get_subtypes(tx, concepts_get_root_entity_type(), Explicit);
Concept* entity;
while ((entity = concept_iterator_next(entities)) != NULL) {
printf("Direct subtype of the entity root type: %s\n", thing_type_get_label(entity));
if (!thing_type_is_abstract(entity)) {
const struct Annotation* emptyAnnotations[] = {NULL};
thing_type_set_owns(tx, entity, tag, NULL, emptyAnnotations);
}
}
transaction_close(tx);
if (FAILED()) {
handle_error("Transaction close failed.");
goto cleanup;
}
session_close(session);
For more details about these and other API methods, see the API reference.