mirror of
https://github.com/fabianlindfors/reshape.git
synced 2024-11-26 04:07:06 +03:00
Add context to errors
This commit is contained in:
parent
6e005144f4
commit
0bac1245cd
@ -2,7 +2,7 @@ use anyhow::Context;
|
|||||||
|
|
||||||
use crate::db::Conn;
|
use crate::db::Conn;
|
||||||
|
|
||||||
pub fn setup_helpers(db: &mut dyn Conn, current_migration: &Option<String>) -> anyhow::Result<()> {
|
pub fn set_up_helpers(db: &mut dyn Conn, current_migration: &Option<String>) -> anyhow::Result<()> {
|
||||||
let predicate = if let Some(current_migration) = current_migration {
|
let predicate = if let Some(current_migration) = current_migration {
|
||||||
format!(
|
format!(
|
||||||
"current_setting('search_path') = 'migration_{}' OR setting_bool",
|
"current_setting('search_path') = 'migration_{}' OR setting_bool",
|
||||||
@ -32,7 +32,7 @@ pub fn setup_helpers(db: &mut dyn Conn, current_migration: &Option<String>) -> a
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn teardown_helpers(db: &mut dyn Conn) -> anyhow::Result<()> {
|
pub fn tear_down_helpers(db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||||
db.query("DROP FUNCTION reshape.is_old_schema;")?;
|
db.query("DROP FUNCTION reshape.is_old_schema;")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
109
src/lib.rs
109
src/lib.rs
@ -3,7 +3,7 @@ use crate::{
|
|||||||
schema::Schema,
|
schema::Schema,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::{anyhow, Context};
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use db::{Conn, DbConn};
|
use db::{Conn, DbConn};
|
||||||
use postgres::Config;
|
use postgres::Config;
|
||||||
@ -96,7 +96,8 @@ impl Reshape {
|
|||||||
|
|
||||||
println!(" Applying {} migrations\n", remaining_migrations.len());
|
println!(" Applying {} migrations\n", remaining_migrations.len());
|
||||||
|
|
||||||
helpers::setup_helpers(&mut self.db, current_migration)?;
|
helpers::set_up_helpers(&mut self.db, current_migration)
|
||||||
|
.context("failed to set up helpers")?;
|
||||||
|
|
||||||
let mut new_schema = Schema::new();
|
let mut new_schema = Schema::new();
|
||||||
let mut processed_migrations: &[Migration] = &[];
|
let mut processed_migrations: &[Migration] = &[];
|
||||||
@ -107,10 +108,13 @@ impl Reshape {
|
|||||||
processed_migrations = &remaining_migrations[..migration_index + 1];
|
processed_migrations = &remaining_migrations[..migration_index + 1];
|
||||||
|
|
||||||
for (action_index, action) in migration.actions.iter().enumerate() {
|
for (action_index, action) in migration.actions.iter().enumerate() {
|
||||||
print!(" + {} ", action.describe());
|
let description = action.describe();
|
||||||
|
print!(" + {} ", description);
|
||||||
|
|
||||||
let ctx = MigrationContext::new(migration_index, action_index);
|
let ctx = MigrationContext::new(migration_index, action_index);
|
||||||
result = action.run(&ctx, &mut self.db, &new_schema);
|
result = action
|
||||||
|
.run(&ctx, &mut self.db, &new_schema)
|
||||||
|
.with_context(|| format!("failed to {}", description));
|
||||||
|
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
action.update_schema(&ctx, &mut new_schema);
|
action.update_schema(&ctx, &mut new_schema);
|
||||||
@ -133,16 +137,22 @@ impl Reshape {
|
|||||||
|
|
||||||
// Create schema and views for migration
|
// Create schema and views for migration
|
||||||
let target_migration = remaining_migrations.last().unwrap().name.to_string();
|
let target_migration = remaining_migrations.last().unwrap().name.to_string();
|
||||||
self.create_schema_for_migration(&target_migration, &new_schema)?;
|
self.create_schema_for_migration(&target_migration, &new_schema)
|
||||||
|
.with_context(|| {
|
||||||
|
format!("failed to create schema for migration {}", target_migration)
|
||||||
|
})?;
|
||||||
|
|
||||||
// Update state once migrations have been performed
|
// Update state once migrations have been performed
|
||||||
self.state.in_progress(remaining_migrations);
|
self.state.in_progress(remaining_migrations);
|
||||||
self.state.save(&mut self.db)?;
|
self.state
|
||||||
|
.save(&mut self.db)
|
||||||
|
.context("failed to save in-progress state")?;
|
||||||
|
|
||||||
// If we started from a blank slate, we can finish the migration immediately
|
// If we started from a blank slate, we can finish the migration immediately
|
||||||
if current_migration.is_none() {
|
if current_migration.is_none() {
|
||||||
println!("Automatically completing migrations\n");
|
println!("Automatically completing migrations\n");
|
||||||
self.complete_migration()?;
|
self.complete_migration()
|
||||||
|
.context("failed to automatically complete migrations")?;
|
||||||
|
|
||||||
println!("Migrations complete:");
|
println!("Migrations complete:");
|
||||||
println!(
|
println!(
|
||||||
@ -176,41 +186,61 @@ impl Reshape {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
helpers::teardown_helpers(&mut self.db)?;
|
helpers::tear_down_helpers(&mut self.db).context("failed to tear down helpers")?;
|
||||||
|
|
||||||
let mut temp_schema = Schema::new();
|
let mut temp_schema = Schema::new();
|
||||||
|
|
||||||
// Run all the completion changes as a transaction to avoid incomplete updates
|
// Run all the completion changes as a transaction to avoid incomplete updates
|
||||||
let mut transaction = self.db.transaction()?;
|
let mut transaction = self
|
||||||
|
.db
|
||||||
|
.transaction()
|
||||||
|
.context("failed to start transaction")?;
|
||||||
|
|
||||||
// Remove previous migration's schema
|
// Remove previous migration's schema
|
||||||
if let Some(current_migration) = &self.state.current_migration {
|
if let Some(current_migration) = &self.state.current_migration {
|
||||||
transaction.run(&format!(
|
transaction
|
||||||
"DROP SCHEMA IF EXISTS {} CASCADE",
|
.run(&format!(
|
||||||
schema_name_for_migration(current_migration)
|
"DROP SCHEMA IF EXISTS {} CASCADE",
|
||||||
))?;
|
schema_name_for_migration(current_migration)
|
||||||
|
))
|
||||||
|
.context("failed to remove previous migration's schema")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (migration_index, migration) in remaining_migrations.iter().enumerate() {
|
for (migration_index, migration) in remaining_migrations.iter().enumerate() {
|
||||||
println!("Completing '{}':", migration.name);
|
println!("Completing '{}':", migration.name);
|
||||||
|
|
||||||
for (action_index, action) in migration.actions.iter().enumerate() {
|
for (action_index, action) in migration.actions.iter().enumerate() {
|
||||||
print!(" + {} ", action.describe());
|
let description = action.describe();
|
||||||
|
print!(" + {} ", description);
|
||||||
|
|
||||||
let ctx = MigrationContext::new(migration_index, action_index);
|
let ctx = MigrationContext::new(migration_index, action_index);
|
||||||
action.complete(&ctx, &mut transaction, &temp_schema)?;
|
let result = action
|
||||||
action.update_schema(&ctx, &mut temp_schema);
|
.complete(&ctx, &mut transaction, &temp_schema)
|
||||||
|
.with_context(|| format!("failed to complete migration {}", migration.name))
|
||||||
|
.with_context(|| format!("failed to complete action: {}", description));
|
||||||
|
|
||||||
println!("{}", "done".green());
|
if result.is_ok() {
|
||||||
|
action.update_schema(&ctx, &mut temp_schema);
|
||||||
|
println!("{}", "done".green());
|
||||||
|
} else {
|
||||||
|
println!("{}", "failed".green());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.complete()?;
|
self.state
|
||||||
self.state.save(&mut transaction)?;
|
.complete()
|
||||||
|
.context("failed to update state as completed")?;
|
||||||
|
self.state
|
||||||
|
.save(&mut transaction)
|
||||||
|
.context("failed to save state after setting as completed")?;
|
||||||
|
|
||||||
transaction.commit()?;
|
transaction
|
||||||
|
.commit()
|
||||||
|
.context("failed to apply transaction")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -223,7 +253,13 @@ impl Reshape {
|
|||||||
// Create schema for migration
|
// Create schema for migration
|
||||||
let schema_name = schema_name_for_migration(migration_name);
|
let schema_name = schema_name_for_migration(migration_name);
|
||||||
self.db
|
self.db
|
||||||
.run(&format!("CREATE SCHEMA IF NOT EXISTS {}", schema_name))?;
|
.run(&format!("CREATE SCHEMA IF NOT EXISTS {}", schema_name))
|
||||||
|
.with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed to create schema {} for migration {}",
|
||||||
|
schema_name, migration_name
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
// Create views inside schema
|
// Create views inside schema
|
||||||
for table in schema.get_tables(&mut self.db)? {
|
for table in schema.get_tables(&mut self.db)? {
|
||||||
@ -252,7 +288,8 @@ impl Reshape {
|
|||||||
table_name = table.real_name,
|
table_name = table.real_name,
|
||||||
view_name = table.name,
|
view_name = table.name,
|
||||||
columns = select_columns.join(","),
|
columns = select_columns.join(","),
|
||||||
))?;
|
))
|
||||||
|
.with_context(|| format!("failed to create view for table {}", table.name))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -300,16 +337,19 @@ impl Reshape {
|
|||||||
};
|
};
|
||||||
let target_migration = remaining_migrations.last().unwrap().name.to_string();
|
let target_migration = remaining_migrations.last().unwrap().name.to_string();
|
||||||
|
|
||||||
helpers::teardown_helpers(&mut self.db)?;
|
helpers::tear_down_helpers(&mut self.db).context("failed to tear down helpers")?;
|
||||||
|
|
||||||
// Run all the abort changes as a transaction to avoid incomplete changes
|
// Run all the abort changes as a transaction to avoid incomplete changes
|
||||||
let mut transaction = self.db.transaction()?;
|
let mut transaction = self
|
||||||
|
.db
|
||||||
|
.transaction()
|
||||||
|
.context("failed to start transaction")?;
|
||||||
|
|
||||||
// Remove new migration's schema
|
// Remove new migration's schema
|
||||||
transaction.run(&format!(
|
let schema_name = schema_name_for_migration(&target_migration);
|
||||||
"DROP SCHEMA IF EXISTS {} CASCADE",
|
transaction
|
||||||
schema_name_for_migration(&target_migration)
|
.run(&format!("DROP SCHEMA IF EXISTS {} CASCADE", schema_name,))
|
||||||
))?;
|
.with_context(|| format!("failed to drop schema {}", schema_name))?;
|
||||||
|
|
||||||
// Abort all pending migrations
|
// Abort all pending migrations
|
||||||
abort_migrations(&mut transaction, &remaining_migrations)?;
|
abort_migrations(&mut transaction, &remaining_migrations)?;
|
||||||
@ -317,9 +357,13 @@ impl Reshape {
|
|||||||
let keep_count = self.state.migrations.len() - remaining_migrations.len();
|
let keep_count = self.state.migrations.len() - remaining_migrations.len();
|
||||||
self.state.migrations.truncate(keep_count);
|
self.state.migrations.truncate(keep_count);
|
||||||
self.state.status = state::Status::Idle;
|
self.state.status = state::Status::Idle;
|
||||||
self.state.save(&mut transaction)?;
|
self.state
|
||||||
|
.save(&mut transaction)
|
||||||
|
.context("failed to save state")?;
|
||||||
|
|
||||||
transaction.commit()?;
|
transaction
|
||||||
|
.commit()
|
||||||
|
.context("failed to commit transaction")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -331,7 +375,10 @@ fn abort_migrations(db: &mut dyn Conn, migrations: &[Migration]) -> anyhow::Resu
|
|||||||
print!("Aborting '{}' ", migration.name);
|
print!("Aborting '{}' ", migration.name);
|
||||||
for (action_index, action) in migration.actions.iter().rev().enumerate() {
|
for (action_index, action) in migration.actions.iter().rev().enumerate() {
|
||||||
let ctx = MigrationContext::new(migration_index, action_index);
|
let ctx = MigrationContext::new(migration_index, action_index);
|
||||||
action.abort(&ctx, db)?;
|
action
|
||||||
|
.abort(&ctx, db)
|
||||||
|
.with_context(|| format!("failed to abort migration {}", migration.name))
|
||||||
|
.with_context(|| format!("failed to abort action: {}", action.describe()))?;
|
||||||
}
|
}
|
||||||
println!("{}", "done".green());
|
println!("{}", "done".green());
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{common, Action, Column, MigrationContext};
|
use super::{common, Action, Column, MigrationContext};
|
||||||
use crate::{db::Conn, schema::Schema};
|
use crate::{db::Conn, schema::Schema};
|
||||||
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -80,7 +81,7 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
definition = definition_parts.join(" "),
|
definition = definition_parts.join(" "),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to add column")?;
|
||||||
|
|
||||||
if let Some(up) = &self.up {
|
if let Some(up) = &self.up {
|
||||||
let table = schema.get_table(db, &self.table)?;
|
let table = schema.get_table(db, &self.table)?;
|
||||||
@ -124,12 +125,13 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
declarations = declarations.join("\n"),
|
declarations = declarations.join("\n"),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to create up trigger")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backfill values in batches
|
// Backfill values in batches
|
||||||
if self.up.is_some() {
|
if self.up.is_some() {
|
||||||
common::batch_touch_rows(db, &table.real_name, &temp_column_name)?;
|
common::batch_touch_rows(db, &table.real_name, &temp_column_name)
|
||||||
|
.context("failed to batch update existing rows")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a temporary NOT NULL constraint if the column shouldn't be nullable.
|
// Add a temporary NOT NULL constraint if the column shouldn't be nullable.
|
||||||
@ -147,7 +149,8 @@ impl Action for AddColumn {
|
|||||||
constraint_name = self.not_null_constraint_name(&ctx),
|
constraint_name = self.not_null_constraint_name(&ctx),
|
||||||
column = temp_column_name,
|
column = temp_column_name,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to add NOT NULL constraint")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -170,7 +173,7 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
trigger_name = self.trigger_name(ctx),
|
trigger_name = self.trigger_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to drop up trigger")?;
|
||||||
|
|
||||||
// Update column to be NOT NULL if necessary
|
// Update column to be NOT NULL if necessary
|
||||||
if !self.column.nullable {
|
if !self.column.nullable {
|
||||||
@ -184,7 +187,8 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
constraint_name = self.not_null_constraint_name(ctx),
|
constraint_name = self.not_null_constraint_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to validate NOT NULL constraint")?;
|
||||||
|
|
||||||
// Update the column to be NOT NULL.
|
// Update the column to be NOT NULL.
|
||||||
// This requires an exclusive lock but since PG 12 it can check
|
// This requires an exclusive lock but since PG 12 it can check
|
||||||
@ -198,7 +202,7 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
column = self.temp_column_name(ctx),
|
column = self.temp_column_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to set column as NOT NULL")?;
|
||||||
|
|
||||||
// Drop the temporary constraint
|
// Drop the temporary constraint
|
||||||
let query = format!(
|
let query = format!(
|
||||||
@ -209,7 +213,8 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
constraint_name = self.not_null_constraint_name(ctx),
|
constraint_name = self.not_null_constraint_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to drop NOT NULL constraint")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename the temporary column to its real name
|
// Rename the temporary column to its real name
|
||||||
@ -221,7 +226,8 @@ impl Action for AddColumn {
|
|||||||
table = table.real_name,
|
table = table.real_name,
|
||||||
temp_column_name = self.temp_column_name(ctx),
|
temp_column_name = self.temp_column_name(ctx),
|
||||||
column_name = self.column.name,
|
column_name = self.column.name,
|
||||||
))?;
|
))
|
||||||
|
.context("failed to rename column to final name")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -244,7 +250,7 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
trigger_name = self.trigger_name(ctx),
|
trigger_name = self.trigger_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to drop up trigger")?;
|
||||||
|
|
||||||
// Remove column
|
// Remove column
|
||||||
let query = format!(
|
let query = format!(
|
||||||
@ -255,7 +261,7 @@ impl Action for AddColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
column = self.temp_column_name(ctx),
|
column = self.temp_column_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to drop column")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{Action, MigrationContext};
|
use super::{Action, MigrationContext};
|
||||||
use crate::{db::Conn, schema::Schema};
|
use crate::{db::Conn, schema::Schema};
|
||||||
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -37,7 +38,8 @@ impl Action for AddIndex {
|
|||||||
name = self.name,
|
name = self.name,
|
||||||
table = self.table,
|
table = self.table,
|
||||||
columns = column_real_names.join(", "),
|
columns = column_real_names.join(", "),
|
||||||
))?;
|
))
|
||||||
|
.context("failed to create index")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +61,8 @@ impl Action for AddIndex {
|
|||||||
",
|
",
|
||||||
name = self.name,
|
name = self.name,
|
||||||
table = self.table,
|
table = self.table,
|
||||||
))?;
|
))
|
||||||
|
.context("failed to drop index")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{Action, MigrationContext};
|
use super::{Action, MigrationContext};
|
||||||
use crate::{db::Conn, migrations::common, schema::Schema};
|
use crate::{db::Conn, migrations::common, schema::Schema};
|
||||||
use anyhow::anyhow;
|
use anyhow::{anyhow, Context};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -90,7 +90,7 @@ impl Action for AlterColumn {
|
|||||||
.columns
|
.columns
|
||||||
.iter()
|
.iter()
|
||||||
.find(|column| column.name == self.column)
|
.find(|column| column.name == self.column)
|
||||||
.ok_or_else(|| anyhow!("no such column exists"))?;
|
.ok_or_else(|| anyhow!("no such column {} exists", self.column))?;
|
||||||
|
|
||||||
let temporary_column_type = self
|
let temporary_column_type = self
|
||||||
.changes
|
.changes
|
||||||
@ -108,7 +108,7 @@ impl Action for AlterColumn {
|
|||||||
temp_column = self.temporary_column_name(ctx),
|
temp_column = self.temporary_column_name(ctx),
|
||||||
temp_column_type = temporary_column_type,
|
temp_column_type = temporary_column_type,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to add temporary column")?;
|
||||||
|
|
||||||
let declarations: Vec<String> = table
|
let declarations: Vec<String> = table
|
||||||
.columns
|
.columns
|
||||||
@ -173,10 +173,12 @@ impl Action for AlterColumn {
|
|||||||
down_trigger = self.down_trigger_name(ctx),
|
down_trigger = self.down_trigger_name(ctx),
|
||||||
declarations = declarations.join("\n"),
|
declarations = declarations.join("\n"),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to create up and down triggers")?;
|
||||||
|
|
||||||
// Backfill values in batches by touching the previous column
|
// Backfill values in batches by touching the previous column
|
||||||
common::batch_touch_rows(db, &table.real_name, &column.real_name)?;
|
common::batch_touch_rows(db, &table.real_name, &column.real_name)
|
||||||
|
.context("failed to batch update existing rows")?;
|
||||||
|
|
||||||
// Add a temporary NOT NULL constraint if the column shouldn't be nullable.
|
// Add a temporary NOT NULL constraint if the column shouldn't be nullable.
|
||||||
// This constraint is set as NOT VALID so it doesn't apply to existing rows and
|
// This constraint is set as NOT VALID so it doesn't apply to existing rows and
|
||||||
@ -193,7 +195,8 @@ impl Action for AlterColumn {
|
|||||||
constraint_name = self.not_null_constraint_name(ctx),
|
constraint_name = self.not_null_constraint_name(ctx),
|
||||||
column = self.temporary_column_name(ctx),
|
column = self.temporary_column_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to add NOT NULL constraint")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -216,7 +219,7 @@ impl Action for AlterColumn {
|
|||||||
existing_name = self.column,
|
existing_name = self.column,
|
||||||
new_name = new_name,
|
new_name = new_name,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to rename column")?;
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -237,7 +240,7 @@ impl Action for AlterColumn {
|
|||||||
",
|
",
|
||||||
self.table, column.real_name
|
self.table, column.real_name
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to drop old column")?;
|
||||||
|
|
||||||
// Rename temporary column
|
// Rename temporary column
|
||||||
let query = format!(
|
let query = format!(
|
||||||
@ -248,7 +251,8 @@ impl Action for AlterColumn {
|
|||||||
temp_column = self.temporary_column_name(ctx),
|
temp_column = self.temporary_column_name(ctx),
|
||||||
name = column_name,
|
name = column_name,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to rename temporary column")?;
|
||||||
|
|
||||||
// Remove triggers and procedures
|
// Remove triggers and procedures
|
||||||
let query = format!(
|
let query = format!(
|
||||||
@ -263,7 +267,8 @@ impl Action for AlterColumn {
|
|||||||
up_trigger = self.up_trigger_name(ctx),
|
up_trigger = self.up_trigger_name(ctx),
|
||||||
down_trigger = self.down_trigger_name(ctx),
|
down_trigger = self.down_trigger_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to drop up and down triggers")?;
|
||||||
|
|
||||||
// Update column to be NOT NULL if necessary
|
// Update column to be NOT NULL if necessary
|
||||||
if !column.nullable {
|
if !column.nullable {
|
||||||
@ -277,7 +282,8 @@ impl Action for AlterColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
constraint_name = self.not_null_constraint_name(ctx),
|
constraint_name = self.not_null_constraint_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to validate NOT NULL constraint")?;
|
||||||
|
|
||||||
// Update the column to be NOT NULL.
|
// Update the column to be NOT NULL.
|
||||||
// This requires an exclusive lock but since PG 12 it can check
|
// This requires an exclusive lock but since PG 12 it can check
|
||||||
@ -291,7 +297,7 @@ impl Action for AlterColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
column = column_name,
|
column = column_name,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to set column as NOT NULL")?;
|
||||||
|
|
||||||
// Drop the temporary constraint
|
// Drop the temporary constraint
|
||||||
let query = format!(
|
let query = format!(
|
||||||
@ -302,7 +308,8 @@ impl Action for AlterColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
constraint_name = self.not_null_constraint_name(ctx),
|
constraint_name = self.not_null_constraint_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to drop NOT NULL constraint")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -344,7 +351,8 @@ impl Action for AlterColumn {
|
|||||||
up_trigger = self.up_trigger_name(ctx),
|
up_trigger = self.up_trigger_name(ctx),
|
||||||
down_trigger = self.down_trigger_name(ctx),
|
down_trigger = self.down_trigger_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to drop up and down triggers")?;
|
||||||
|
|
||||||
// Drop temporary column
|
// Drop temporary column
|
||||||
let query = format!(
|
let query = format!(
|
||||||
@ -355,7 +363,7 @@ impl Action for AlterColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
temp_column = self.temporary_column_name(ctx),
|
temp_column = self.temporary_column_name(ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to drop temporary column")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{Action, Column, MigrationContext};
|
use super::{Action, Column, MigrationContext};
|
||||||
use crate::{db::Conn, schema::Schema};
|
use crate::{db::Conn, schema::Schema};
|
||||||
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -71,7 +72,8 @@ impl Action for CreateTable {
|
|||||||
)",
|
)",
|
||||||
self.name,
|
self.name,
|
||||||
definition_rows.join(",\n"),
|
definition_rows.join(",\n"),
|
||||||
))?;
|
))
|
||||||
|
.context("failed to create table")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +90,8 @@ impl Action for CreateTable {
|
|||||||
fn update_schema(&self, _ctx: &MigrationContext, _schema: &mut Schema) {}
|
fn update_schema(&self, _ctx: &MigrationContext, _schema: &mut Schema) {}
|
||||||
|
|
||||||
fn abort(&self, _ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
fn abort(&self, _ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||||
let query = format!("DROP TABLE IF EXISTS {table}", table = self.name,);
|
db.run(&format!("DROP TABLE IF EXISTS {}", self.name,))
|
||||||
db.run(&query)?;
|
.context("failed to drop table")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{Action, MigrationContext};
|
use super::{Action, MigrationContext};
|
||||||
use crate::{db::Conn, schema::Schema};
|
use crate::{db::Conn, schema::Schema};
|
||||||
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -77,7 +78,7 @@ impl Action for RemoveColumn {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
declarations = declarations.join("\n"),
|
declarations = declarations.join("\n"),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to create down trigger")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -102,7 +103,8 @@ impl Action for RemoveColumn {
|
|||||||
column = self.column,
|
column = self.column,
|
||||||
trigger_name = self.trigger_name(&ctx),
|
trigger_name = self.trigger_name(&ctx),
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query)
|
||||||
|
.context("failed to drop column and down trigger")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -124,7 +126,8 @@ impl Action for RemoveColumn {
|
|||||||
",
|
",
|
||||||
table = self.table,
|
table = self.table,
|
||||||
trigger_name = self.trigger_name(&ctx),
|
trigger_name = self.trigger_name(&ctx),
|
||||||
))?;
|
))
|
||||||
|
.context("failed to drop down trigger")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{Action, MigrationContext};
|
use super::{Action, MigrationContext};
|
||||||
use crate::{db::Conn, schema::Schema};
|
use crate::{db::Conn, schema::Schema};
|
||||||
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -35,7 +36,7 @@ impl Action for RemoveTable {
|
|||||||
",
|
",
|
||||||
table = self.table,
|
table = self.table,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to drop table")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{Action, MigrationContext};
|
use super::{Action, MigrationContext};
|
||||||
use crate::{db::Conn, schema::Schema};
|
use crate::{db::Conn, schema::Schema};
|
||||||
|
use anyhow::Context;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -38,7 +39,7 @@ impl Action for RenameTable {
|
|||||||
table = self.table,
|
table = self.table,
|
||||||
new_name = self.new_name,
|
new_name = self.new_name,
|
||||||
);
|
);
|
||||||
db.run(&query)?;
|
db.run(&query).context("failed to rename table")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user