From 85f194844344c56f94448a3c6f03f3b5fafb3afb Mon Sep 17 00:00:00 2001 From: Jannik Clausen Date: Wed, 15 Jun 2022 14:18:35 +0200 Subject: [PATCH] docs and drift test --- dialect/sql/schema/migrate_test.go | 24 ++++++++++++---- doc/md/migrate.md | 7 +++++ doc/md/versioned-migrations.md | 45 +++++++++++++++++++++++++----- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/dialect/sql/schema/migrate_test.go b/dialect/sql/schema/migrate_test.go index fe9ec8e35a..44b05d8b1f 100644 --- a/dialect/sql/schema/migrate_test.go +++ b/dialect/sql/schema/migrate_test.go @@ -170,13 +170,16 @@ func TestMigrate_Diff(t *testing.T) { // Running diff against an existing database without having a types file yet // will result in the types file respect the "old" order of pk allocations. - for _, stmt := range []string{ - "DELETE FROM `ent_types`;", - "INSERT INTO `ent_types` (`type`) VALUES ('groups'), ('users');", // switched allocations - } { - _, err = db.ExecContext(context.Background(), stmt) - require.NoError(t, err) + switchAllocs := func(one, two string) { + for _, stmt := range []string{ + "DELETE FROM `ent_types`;", + fmt.Sprintf("INSERT INTO `ent_types` (`type`) VALUES ('%s'), ('%s');", one, two), + } { + _, err = db.ExecContext(context.Background(), stmt) + require.NoError(t, err) + } } + switchAllocs("groups", "users") p = t.TempDir() d, err = migrate.NewLocalDir(p) require.NoError(t, err) @@ -189,6 +192,15 @@ func TestMigrate_Diff(t *testing.T) { )) requireFileEqual(t, filepath.Join(p, ".ent_types"), atlasDirective+"groups,users") require.NoFileExists(t, filepath.Join(p, "changes.sql")) + + // Drifts in the types file and types database will be detected, + switchAllocs("users", "groups") + require.ErrorContains(t, m.Diff(context.Background()), fmt.Sprintf( + "type allocation range drift detected: %v <> %v: see %s for more information", + []string{"users", "groups"}, + []string{"groups", "users"}, + "https://entgo.io/docs/versioned-migrations#moving-from-auto-migration-to-versioned-migrations", + )) } func requireFileEqual(t *testing.T, name, contents string) { diff --git a/doc/md/migrate.md b/doc/md/migrate.md index 093543a663..e2f4c7c1b4 100755 --- a/doc/md/migrate.md +++ b/doc/md/migrate.md @@ -79,6 +79,13 @@ the object ID to be unique. To enable the Universal-IDs support for your project, pass the `WithGlobalUniqueID` option to the migration. +:::note +Be aware, that `WithGlobalUniqueID` and [versioned migration](versioned-migrations.md) files are not working together. +After understanding the +[risks](https://github.com/ent/ent/blob/8eeb23ce56bcb6ac4ee0354a6c847558586c9a46/dialect/sql/schema/atlas.go#L276-L283), +you can use `WithDeterministicGlobalUniqueID` instead. +::: + ```go package main diff --git a/doc/md/versioned-migrations.md b/doc/md/versioned-migrations.md index d4a32a25eb..d2c79b8189 100644 --- a/doc/md/versioned-migrations.md +++ b/doc/md/versioned-migrations.md @@ -163,16 +163,47 @@ migrate -source file://migrations -database mysql://root:pass@tcp(localhost:3306 In case you already have an Ent application in production and want to switch over from auto migration to the new versioned migration, you need to take some extra steps. -1. Create an initial migration file (or several files if you want) reflecting the currently deployed state. +### Create an initial migration file reflecting the currently deployed state - To do this make sure your schema definition is in sync with your deployed version. Then spin up an empty database and - run the diff command once as described above. This will create the statements needed to create the current state of - your schema graph. +To do this make sure your schema definition is in sync with your deployed version. Then spin up an empty database and +run the diff command once as described above. This will create the statements needed to create the current state of +your schema graph. +If you happened to have [universal IDs](migrate.md#universal-ids) enabled before, the above command will create a +file called `.ent_types` containing a list of schema names similar to the following: -2. Configure the tool you use to manage migrations to consider this file as **applied**. +```text title=".ent_types" +atlas.sum ignore +users,groups +``` +Once that has been created, one of the migration files will contain statements to create a table called +`ent_types`, as well as some inserts to it: + +```sql +CREATE TABLE `users` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT); +CREATE TABLE `groups` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT); +INSERT INTO sqlite_sequence (name, seq) VALUES ("groups", 4294967296); +CREATE TABLE `ent_types` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `type` text NOT NULL); +CREATE UNIQUE INDEX `ent_types_type_key` ON `ent_types` (`type`); +INSERT INTO `ent_types` (`type`) VALUES ('users'), ('groups'); +``` + +In order to ensure to not break existing code, make sure the contents of that file are equal to the contents in the +table present in the database you created the diff from. For example, if you consider the `.ent_types` file from +above (`users,groups`) but your deployed table looks like the one below (`groups,users`): + +| id | type | +|-----|--------| +| 1 | groups | +| 2 | users | + +You can see, that the order differs. In that case, you have to manually change both the entries in the +`.ent_types` file, as well in the generated migrations file. As a safety feature, Ent will warn you about type +drifts if you attempt to run a migration diff. + +### Configure the tool you use to manage migrations to consider this file as applied - In case of `golang-migrate` this can be done by forcing your database version as - described [here](https://github.com/golang-migrate/migrate/blob/master/GETTING_STARTED.md#forcing-your-database-version). +In case of `golang-migrate` this can be done by forcing your database version as +described [here](https://github.com/golang-migrate/migrate/blob/master/GETTING_STARTED.md#forcing-your-database-version). ## Use a Custom Formatter