Add builder for create_table migration

The builder will help simplify the tests and avoid boilerplate updates
when need fields are added to the create_table migration. We might want
to add builders all migrations later.
This commit is contained in:
fabianlindfors 2022-01-10 21:59:20 +01:00
parent 435a40695a
commit c76ea1fba6
11 changed files with 197 additions and 192 deletions

View File

@ -19,4 +19,5 @@ anyhow = { version = "1.0.44", features = ["backtrace"] }
clap = { version = "3.0.0", features = ["derive"] }
toml = "0.5"
version = "3.0.0"
colored = "2"
colored = "2"
"derive_builder" = "0.10.2"

View File

@ -1,9 +1,11 @@
use derive_builder::Builder;
use postgres::types::{FromSql, ToSql};
use serde::{Deserialize, Serialize};
use crate::db::Conn;
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Builder, Clone, Debug)]
#[builder(setter(into))]
pub struct Column {
pub name: String,
@ -11,10 +13,13 @@ pub struct Column {
pub data_type: String,
#[serde(default = "nullable_default")]
#[builder(default = "true")]
pub nullable: bool,
#[builder(setter(name = "default_value", strip_option), default)]
pub default: Option<String>,
#[builder(setter(strip_option), default)]
pub generated: Option<String>,
}

View File

@ -1,18 +1,22 @@
use super::{Action, Column, MigrationContext};
use crate::{db::Conn, schema::Schema};
use anyhow::Context;
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Builder, Debug)]
#[builder(setter(into))]
pub struct CreateTable {
pub name: String,
pub columns: Vec<Column>,
pub primary_key: Vec<String>,
#[serde(default)]
#[builder(default)]
pub foreign_keys: Vec<ForeignKey>,
}
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ForeignKey {
pub columns: Vec<String>,
pub referenced_table: String,

View File

@ -4,10 +4,10 @@ use serde::{Deserialize, Serialize};
// Re-export migration types
mod common;
pub use common::Column;
pub use common::{Column, ColumnBuilder};
mod create_table;
pub use create_table::{CreateTable, ForeignKey};
pub use create_table::{CreateTable, CreateTableBuilder, ForeignKey};
mod alter_column;
pub use alter_column::{AlterColumn, ColumnChanges};

View File

@ -1,4 +1,4 @@
use reshape::migrations::{AddColumn, Column, CreateTable, Migration};
use reshape::migrations::{AddColumn, Column, ColumnBuilder, CreateTableBuilder, Migration};
use reshape::Status;
mod common;
@ -7,27 +7,26 @@ mod common;
fn add_column() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_users_table = Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![
Column {
name: "id".to_string(),
data_type: "SERIAL".to_string(),
nullable: true,
default: None,
generated: None,
},
Column {
name: "name".to_string(),
data_type: "TEXT".to_string(),
nullable: false,
default: None,
generated: None,
},
],
});
let create_users_table = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![
ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap(),
ColumnBuilder::default()
.name("name")
.data_type("TEXT")
.build()
.unwrap(),
])
.build()
.unwrap(),
);
let add_first_last_name_columns = Migration::new("add_first_and_last_name_columns", None)
.with_action(AddColumn {
table: "users".to_string(),
@ -127,18 +126,18 @@ fn add_column() {
fn add_column_nullable() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_users_table = Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: true,
default: None,
generated: None,
}],
});
let create_users_table = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap()])
.build()
.unwrap(),
);
let add_name_column = Migration::new("add_nullable_name_column", None).with_action(AddColumn {
table: "users".to_string(),
column: Column {
@ -225,18 +224,18 @@ fn add_column_nullable() {
fn add_column_with_default() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_users_table = Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: true,
default: None,
generated: None,
}],
});
let create_users_table = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap()])
.build()
.unwrap(),
);
let add_name_column =
Migration::new("add_name_column_with_default", None).with_action(AddColumn {
table: "users".to_string(),

View File

@ -1,4 +1,4 @@
use reshape::migrations::{AddIndex, Column, CreateTable, Migration};
use reshape::migrations::{AddIndex, ColumnBuilder, CreateTableBuilder, Migration};
mod common;
@ -6,28 +6,25 @@ mod common;
fn add_index() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_table_migration =
Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![
Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: true,
default: None,
generated: None,
},
Column {
name: "name".to_string(),
data_type: "TEXT".to_string(),
nullable: false,
default: None,
generated: None,
},
],
});
let create_table_migration = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![
ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap(),
ColumnBuilder::default()
.name("name")
.data_type("TEXT")
.build()
.unwrap(),
])
.build()
.unwrap(),
);
let add_index_migration = Migration::new("add_name_index", None).with_action(AddIndex {
table: "users".to_string(),
name: "name_idx".to_string(),

View File

@ -37,6 +37,7 @@ fn alter_column_data() {
data_type: None,
nullable: None,
name: None,
default: None,
},
});
@ -142,6 +143,7 @@ fn alter_column_set_not_null() {
data_type: None,
nullable: Some(false),
name: None,
default: None,
},
});
@ -248,6 +250,7 @@ fn alter_column_rename() {
data_type: None,
nullable: None,
name: Some("full_name".to_string()),
default: None,
},
});
@ -336,6 +339,7 @@ fn alter_column_multiple() {
data_type: None,
nullable: None,
name: None,
default: None,
},
})
.with_action(AlterColumn {
@ -347,6 +351,7 @@ fn alter_column_multiple() {
data_type: None,
nullable: None,
name: None,
default: None,
},
});

View File

@ -1,5 +1,5 @@
use reshape::{
migrations::{Column, CreateTable, ForeignKey, Migration},
migrations::{ColumnBuilder, CreateTableBuilder, ForeignKey, Migration},
Status,
};
@ -9,35 +9,33 @@ mod common;
fn create_table() {
let (mut reshape, mut db, _) = common::setup();
let create_table_migration =
Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![
Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: true,
default: None,
generated: Some("ALWAYS AS IDENTITY".to_string()),
},
Column {
name: "name".to_string(),
data_type: "TEXT".to_string(),
nullable: true,
default: None,
generated: None,
},
Column {
name: "created_at".to_string(),
data_type: "TIMESTAMP".to_string(),
nullable: false,
default: Some("NOW()".to_string()),
generated: None,
},
],
});
let create_table_migration = Migration::new("create_users_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![
ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.generated("ALWAYS AS IDENTITY")
.build()
.unwrap(),
ColumnBuilder::default()
.name("name")
.data_type("TEXT")
.build()
.unwrap(),
ColumnBuilder::default()
.name("created_at")
.data_type("TIMESTAMP")
.nullable(false)
.default_value("NOW()")
.build()
.unwrap(),
])
.build()
.unwrap(),
);
reshape
.migrate(vec![create_table_migration.clone()])
@ -127,46 +125,46 @@ fn create_table() {
fn create_table_with_foreign_keys() {
let (mut reshape, mut db, _) = common::setup();
let create_table_migration =
Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![Column {
name: "id".to_string(),
data_type: "SERIAL".to_string(),
nullable: true, // Will be ignored by Postgres as the column is a SERIAL
default: None,
generated: None,
}],
});
let create_table_migration = Migration::new("create_users_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.generated("ALWAYS AS IDENTITY")
.build()
.unwrap()])
.build()
.unwrap(),
);
let create_second_table_migration =
Migration::new("create_items_table", None).with_action(CreateTable {
name: "items".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![ForeignKey {
let create_second_table_migration = Migration::new("create_items_table", None).with_action(
CreateTableBuilder::default()
.name("items")
.primary_key(vec!["id".to_string()])
.foreign_keys(vec![ForeignKey {
columns: vec!["user_id".to_string()],
referenced_table: "users".to_string(),
referenced_columns: vec!["id".to_string()],
}],
columns: vec![
Column {
name: "id".to_string(),
data_type: "SERIAL".to_string(),
nullable: true,
default: None,
generated: None,
},
Column {
name: "user_id".to_string(),
data_type: "INTEGER".to_string(),
nullable: false,
default: None,
generated: None,
},
],
});
}])
.columns(vec![
ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.generated("ALWAYS AS IDENTITY")
.build()
.unwrap(),
ColumnBuilder::default()
.name("user_id")
.data_type("INTEGER")
.nullable(false)
.build()
.unwrap(),
])
.build()
.unwrap(),
);
reshape
.migrate(vec![

View File

@ -1,4 +1,4 @@
use reshape::migrations::{Column, CreateTable, Migration, RemoveColumn};
use reshape::migrations::{ColumnBuilder, CreateTableBuilder, Migration, RemoveColumn};
mod common;
@ -6,28 +6,26 @@ mod common;
fn remove_column() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_table_migration =
Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![
Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: true,
default: None,
generated: None,
},
Column {
name: "name".to_string(),
data_type: "TEXT".to_string(),
nullable: false,
default: None,
generated: None,
},
],
});
let create_table_migration = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![
ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap(),
ColumnBuilder::default()
.name("name")
.data_type("TEXT")
.nullable(false)
.build()
.unwrap(),
])
.build()
.unwrap(),
);
let remove_column_migration =
Migration::new("remove_name_column", None).with_action(RemoveColumn {
table: "users".to_string(),

View File

@ -1,4 +1,4 @@
use reshape::migrations::{Column, CreateTable, Migration, RemoveTable};
use reshape::migrations::{ColumnBuilder, CreateTableBuilder, Migration, RemoveTable};
mod common;
@ -6,19 +6,18 @@ mod common;
fn remove_table() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_table_migration =
Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: false,
default: None,
generated: None,
}],
});
let create_table_migration = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap()])
.build()
.unwrap(),
);
let remove_table_migration =
Migration::new("remove_users_table", None).with_action(RemoveTable {
table: "users".to_string(),

View File

@ -1,4 +1,4 @@
use reshape::migrations::{Column, CreateTable, Migration, RenameTable};
use reshape::migrations::{ColumnBuilder, CreateTableBuilder, Migration, RenameTable};
mod common;
@ -6,19 +6,18 @@ mod common;
fn rename_table() {
let (mut reshape, mut old_db, mut new_db) = common::setup();
let create_table_migration =
Migration::new("create_users_table", None).with_action(CreateTable {
name: "users".to_string(),
primary_key: vec!["id".to_string()],
foreign_keys: vec![],
columns: vec![Column {
name: "id".to_string(),
data_type: "INTEGER".to_string(),
nullable: false,
default: None,
generated: None,
}],
});
let create_table_migration = Migration::new("create_user_table", None).with_action(
CreateTableBuilder::default()
.name("users")
.primary_key(vec!["id".to_string()])
.columns(vec![ColumnBuilder::default()
.name("id")
.data_type("INTEGER")
.build()
.unwrap()])
.build()
.unwrap(),
);
let rename_table_migration = Migration::new("rename_users_table_to_customers", None)
.with_action(RenameTable {
table: "users".to_string(),