Migrations - circuitsacul/apgorm GitHub Wiki

Basics

When it comes to migrations, there are two steps: Creating migrations and applying them. Creating migrations should be done every time you modify the structure of the database and should be pushed to your repo (don't .gitignore the migrations folder). This way every person has the same migration files, which avoids confusing bugs. Applying migrations needs to be done for each database.

The simplest way to integrate migrations in your code is to add something like this at its start:

if db.must_create_migrations():
    db.create_migrations()
if await db.must_apply_migrations():
    await db.apply_migrations()

Every time a new migration is created, a new folder with the id of the migration is made. In that folder are two files: describe.json and migrations.sql. describe.json contains the "description" of the database. This is so that the next migration can compare the differences between that migration and the current database. migrations.sql contains the raw SQL that is run when you call apply_migrations (if it hasn't been run yet).

Manual Migrations

The migration system isn't super advanced; It supports basic things such as dropping/adding columns/tables/indexes/constraints. If you need to change the datatype of a column or rename a field, the easiest way to do that is to write a manual migration.

Say you have the following table:

class User(apgorm.Model):
    name = VarChar(32).field()

If you wanted to increase the length of name to say, 64, simply editing the field won't work (apgorm won't detect any changes in type parameters). So, after changing the length to 64, you would call db.create_migrations(allow_empty=True). This will create a new migration with an empty migrations.sql file (assuming it didn't detect any changes). Now, you can open that file and modify it to say this:

ALTER TABLE users ALTER COLUMN name SET DATA TYPE VARCHAR(64) USING name::VARCHAR(64);

Now, you can call await db.apply_migrations() and the datatype will be changed.

IMPORTANT: If you call await db.apply_migrations() before modifying migrations.sql, you won't be able to re-apply the migration (since apgorm thinks it has been applied). If you did this by accident, you can run DELETE FROM _migrations WHERE id_=<id of migration> and then rerun `db.apply_migrations(). This is also a good reason to never modify or delete an existing migration folder.