New ACM paper, free-tier cloud, and open-source license

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

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:

  1. Open the Type Editor window by double-clicking on the selected type in the Type Browser.

  2. At the very top, click on the pencil icon immediately right from the type name.

  3. Edit the name in the Label field and press the Rename button to save the changes.

  4. Commit the transaction by the Commit (studio check) 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:

  1. Open the Type Editor window by double-clicking on the selected type in the Type Browser.

  2. At the very bottom, click the Delete button and then the Confirm button.

  3. Commit the transaction by the Commit (studio check) 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

Driver API schema modification
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.

Driver API schema modification
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.

Driver API schema modification
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.

Driver API schema modification
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.

Driver API schema modification
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.

Driver API schema modification
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.

Driver API schema modification
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.

Learn more

Learn more about Define queries in TypeQL: syntax, behavior, and query examples.

Learn how to write some data to a database with the schema you just defined.

Check out the Defining schemas section of our TypeDB Learning course.

Learn more about existing TypeDB drivers for various programming languages/frameworks.

Provide Feedback