Add new remove_enum action

This commit is contained in:
fabianlindfors 2022-01-19 23:14:24 +01:00
parent 953be4d3eb
commit 16f64181f0
4 changed files with 138 additions and 0 deletions

View File

@ -30,6 +30,7 @@ Designed for Postgres 12 and later.
- [Remove index](#remove-index)
- [Enums](#enums)
- [Create enum](#create-enum)
- [Remove enum](#remove-enum)
- [Commands and options](#commands-and-options)
- [`reshape migrate`](#reshape-migrate)
- [`reshape complete`](#reshape-complete)
@ -443,6 +444,8 @@ index = "name_idx"
The `create_enum` action will create a new [enum type](https://www.postgresql.org/docs/current/datatype-enum.html) with the specified values.
*Example: add a new `mood` enum type with three possible values*
```toml
[[actions]]
type = "create_enum"
@ -450,6 +453,18 @@ name = "mood"
values = ["happy", "ok", "sad"]
```
#### Remove enum
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.
*Example: remove the `mood` enum type*
```toml
[[actions]]
type = "remove_enum"
enum = "mood"
```
## Commands and options
### `reshape migrate`

View File

@ -36,6 +36,9 @@ pub use rename_table::RenameTable;
mod create_enum;
pub use create_enum::CreateEnum;
mod remove_enum;
pub use remove_enum::RemoveEnum;
#[derive(Serialize, Deserialize, Debug)]
pub struct Migration {
pub name: String,

View File

@ -0,0 +1,51 @@
use super::{Action, MigrationContext};
use crate::{
db::{Conn, Transaction},
schema::Schema,
};
use anyhow::Context;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct RemoveEnum {
#[serde(rename = "enum")]
pub enum_name: String,
}
#[typetag::serde(name = "remove_enum")]
impl Action for RemoveEnum {
fn describe(&self) -> String {
format!("Removing enum \"{}\"", self.enum_name)
}
fn run(
&self,
_ctx: &MigrationContext,
_db: &mut dyn Conn,
_schema: &Schema,
) -> anyhow::Result<()> {
Ok(())
}
fn complete<'a>(
&self,
_ctx: &MigrationContext,
db: &'a mut dyn Conn,
) -> anyhow::Result<Option<Transaction<'a>>> {
db.run(&format!(
r#"
DROP TYPE IF EXISTS {name}
"#,
name = self.enum_name,
))
.context("failed to drop enum")?;
Ok(None)
}
fn update_schema(&self, _ctx: &MigrationContext, _schema: &mut Schema) {}
fn abort(&self, _ctx: &MigrationContext, _db: &mut dyn Conn) -> anyhow::Result<()> {
Ok(())
}
}

69
tests/remove_enum.rs Normal file
View File

@ -0,0 +1,69 @@
mod common;
use common::Test;
#[test]
fn remove_enum() {
let mut test = Test::new("Remove enum");
test.first_migration(
r#"
name = "create_enum"
[[actions]]
type = "create_enum"
name = "mood"
values = ["happy", "ok", "sad"]
"#,
);
test.second_migration(
r#"
name = "remove_enum"
[[actions]]
type = "remove_enum"
enum = "mood"
"#,
);
test.after_first(|db| {
// Ensure enum was created
let enum_exists = !db
.query(
"
SELECT typname
FROM pg_catalog.pg_type
WHERE typcategory = 'E'
AND typname = 'mood'
",
&[],
)
.unwrap()
.is_empty();
assert!(enum_exists, "expected mood enum to have been created");
});
test.after_completion(|db| {
// Ensure enum was removed after completion
let enum_does_not_exist = db
.query(
"
SELECT typname
FROM pg_catalog.pg_type
WHERE typcategory = 'E'
AND typname = 'mood'
",
&[],
)
.unwrap()
.is_empty();
assert!(
enum_does_not_exist,
"expected mood enum to have been removed"
);
});
test.run();
}