on main help sign in
Add new `remove_enum` action
commit16f64181f02c56b754a377344af0562f4fe2355a authorfabianlindfors <fabian@flapplabs.se> dateWed 19 Jan 2022, 23:14 (5 years ago) parent953be4d
4 files changed+138
README.md+15 src/migrations/mod.rs+3 src/migrations/remove_enum.rs+51 tests/remove_enum.rs+69
README.md+15
@@ -30,6 +30,7 @@ Designed for Postgres 12 and later.
3030 - [Remove index](#remove-index)
3131 - [Enums](#enums)
3232 - [Create enum](#create-enum)
33+ - [Remove enum](#remove-enum)
3334- [Commands and options](#commands-and-options)
3435 - [`reshape migrate`](#reshape-migrate)
3536 - [`reshape complete`](#reshape-complete)
@@ -443,6 +444,8 @@ index = "name_idx"
443444
444445The `create_enum` action will create a new [enum type](https://www.postgresql.org/docs/current/datatype-enum.html) with the specified values.
445446
447+*Example: add a new `mood` enum type with three possible values*
448+
446449```toml
447450[[actions]]
448451type = "create_enum"
@@ -450,6 +453,18 @@ name = "mood"
450453values = ["happy", "ok", "sad"]
451454```
452455
456+#### Remove enum
457+
458+The `remove_enum` action will remove an existing [enum type](https://www.postgresql.org/docs/current/datatype-enum.html). Make sure all usages of the enum has been removed before running the migration. The enum will only be removed once the migration is completed.
459+
460+*Example: remove the `mood` enum type*
461+
462+```toml
463+[[actions]]
464+type = "remove_enum"
465+enum = "mood"
466+```
467+
453468## Commands and options
454469
455470### `reshape migrate`
src/migrations/mod.rs+3
@@ -36,6 +36,9 @@ pub use rename_table::RenameTable;
3636mod create_enum;
3737pub use create_enum::CreateEnum;
3838
39+mod remove_enum;
40+pub use remove_enum::RemoveEnum;
41+
3942#[derive(Serialize, Deserialize, Debug)]
4043pub struct Migration {
4144 pub name: String,
src/migrations/remove_enum.rsnew file+51
@@ -0,0 +1,51 @@
1+use super::{Action, MigrationContext};
2+use crate::{
3+ db::{Conn, Transaction},
4+ schema::Schema,
5+};
6+use anyhow::Context;
7+use serde::{Deserialize, Serialize};
8+
9+#[derive(Serialize, Deserialize, Debug)]
10+pub struct RemoveEnum {
11+ #[serde(rename = "enum")]
12+ pub enum_name: String,
13+}
14+
15+#[typetag::serde(name = "remove_enum")]
16+impl Action for RemoveEnum {
17+ fn describe(&self) -> String {
18+ format!("Removing enum \"{}\"", self.enum_name)
19+ }
20+
21+ fn run(
22+ &self,
23+ _ctx: &MigrationContext,
24+ _db: &mut dyn Conn,
25+ _schema: &Schema,
26+ ) -> anyhow::Result<()> {
27+ Ok(())
28+ }
29+
30+ fn complete<'a>(
31+ &self,
32+ _ctx: &MigrationContext,
33+ db: &'a mut dyn Conn,
34+ ) -> anyhow::Result<Option<Transaction<'a>>> {
35+ db.run(&format!(
36+ r#"
37+ DROP TYPE IF EXISTS {name}
38+ "#,
39+ name = self.enum_name,
40+ ))
41+ .context("failed to drop enum")?;
42+
43+ Ok(None)
44+ }
45+
46+ fn update_schema(&self, _ctx: &MigrationContext, _schema: &mut Schema) {}
47+
48+ fn abort(&self, _ctx: &MigrationContext, _db: &mut dyn Conn) -> anyhow::Result<()> {
49+ Ok(())
50+ }
51+}
tests/remove_enum.rsnew file+69
@@ -0,0 +1,69 @@
1+mod common;
2+use common::Test;
3+
4+#[test]
5+fn remove_enum() {
6+ let mut test = Test::new("Remove enum");
7+
8+ test.first_migration(
9+ r#"
10+ name = "create_enum"
11+
12+ [[actions]]
13+ type = "create_enum"
14+ name = "mood"
15+ values = ["happy", "ok", "sad"]
16+ "#,
17+ );
18+
19+ test.second_migration(
20+ r#"
21+ name = "remove_enum"
22+
23+ [[actions]]
24+ type = "remove_enum"
25+ enum = "mood"
26+ "#,
27+ );
28+
29+ test.after_first(|db| {
30+ // Ensure enum was created
31+ let enum_exists = !db
32+ .query(
33+ "
34+ SELECT typname
35+ FROM pg_catalog.pg_type
36+ WHERE typcategory = 'E'
37+ AND typname = 'mood'
38+ ",
39+ &[],
40+ )
41+ .unwrap()
42+ .is_empty();
43+
44+ assert!(enum_exists, "expected mood enum to have been created");
45+ });
46+
47+ test.after_completion(|db| {
48+ // Ensure enum was removed after completion
49+ let enum_does_not_exist = db
50+ .query(
51+ "
52+ SELECT typname
53+ FROM pg_catalog.pg_type
54+ WHERE typcategory = 'E'
55+ AND typname = 'mood'
56+ ",
57+ &[],
58+ )
59+ .unwrap()
60+ .is_empty();
61+
62+ assert!(
63+ enum_does_not_exist,
64+ "expected mood enum to have been removed"
65+ );
66+ });
67+
68+ test.run();
69+}