Check for new schema rather than old in helper

We want it to be possible for Reshape to be adopted for existing
databases with an existing schema. To make this possible, we can't check
if the schema path matches the current migration as there won't be a
current migration at first. Instead we'll compare against the target
migration.

The next step in making Reshape work with existing databases is to not
automatically complete the first migration. This will not be safe for an
existing application adopting Reshape.
This commit is contained in:
fabianlindfors 2022-01-31 19:53:49 +01:00
parent 4e93a39be0
commit 8888557c38
6 changed files with 13 additions and 26 deletions

View File

@ -2,37 +2,28 @@ use anyhow::Context;
use crate::db::Conn;
pub fn set_up_helpers(db: &mut dyn Conn, current_migration: &Option<String>) -> anyhow::Result<()> {
let predicate = if let Some(current_migration) = current_migration {
format!(
"current_setting('search_path') = 'migration_{}' OR setting_bool",
current_migration
)
} else {
"setting_bool".to_string()
};
pub fn set_up_helpers(db: &mut dyn Conn, target_migration: &str) -> anyhow::Result<()> {
let query = format!(
"
CREATE OR REPLACE FUNCTION reshape.is_old_schema()
CREATE OR REPLACE FUNCTION reshape.is_new_schema()
RETURNS BOOLEAN AS $$
DECLARE
setting TEXT := current_setting('reshape.is_old_schema', TRUE);
setting TEXT := current_setting('reshape.is_new_schema', TRUE);
setting_bool BOOLEAN := setting IS NOT NULL AND setting = 'YES';
BEGIN
RETURN {};
RETURN current_setting('search_path') = 'migration_{}' OR setting_bool;
END
$$ language 'plpgsql';
",
predicate
target_migration,
);
db.query(&query)
.context("failed creating helper function reshape.is_old_schema()")?;
.context("failed creating helper function reshape.is_new_schema()")?;
Ok(())
}
pub fn tear_down_helpers(db: &mut dyn Conn) -> anyhow::Result<()> {
db.query("DROP FUNCTION IF EXISTS reshape.is_old_schema;")?;
db.query("DROP FUNCTION IF EXISTS reshape.is_new_schema;")?;
Ok(())
}

View File

@ -189,7 +189,8 @@ fn migrate(
println!("Applying {} migrations\n", remaining_migrations.len());
helpers::set_up_helpers(db, &current_migration).context("failed to set up helpers")?;
let target_migration = remaining_migrations.last().unwrap().name.to_string();
helpers::set_up_helpers(db, &target_migration).context("failed to set up helpers")?;
let mut new_schema = Schema::new();
let mut last_migration_index = usize::MAX;
@ -244,7 +245,6 @@ fn migrate(
}
// Create schema and views for migration
let target_migration = remaining_migrations.last().unwrap().name.to_string();
create_schema_for_migration(db, &target_migration, &new_schema)
.with_context(|| format!("failed to create schema for migration {}", target_migration))?;

View File

@ -106,7 +106,7 @@ impl Action for AddColumn {
CREATE OR REPLACE FUNCTION {trigger_name}()
RETURNS TRIGGER AS $$
BEGIN
IF reshape.is_old_schema() THEN
IF NOT reshape.is_new_schema() THEN
DECLARE
{declarations}
BEGIN

View File

@ -103,7 +103,7 @@ impl Action for AlterColumn {
CREATE OR REPLACE FUNCTION {up_trigger}()
RETURNS TRIGGER AS $$
BEGIN
IF reshape.is_old_schema() THEN
IF NOT reshape.is_new_schema() THEN
DECLARE
{declarations}
{existing_column} public.{table}.{existing_column_real}%TYPE := NEW.{existing_column_real};
@ -121,7 +121,7 @@ impl Action for AlterColumn {
CREATE OR REPLACE FUNCTION {down_trigger}()
RETURNS TRIGGER AS $$
BEGIN
IF NOT reshape.is_old_schema() THEN
IF reshape.is_new_schema() THEN
DECLARE
{declarations}
{existing_column} public.{table}.{temp_column}%TYPE := NEW.{temp_column};

View File

@ -72,8 +72,6 @@ impl ToSql for PostgresRawValue {
pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow::Result<()> {
const BATCH_SIZE: u16 = 1000;
db.query("SET reshape.is_old_schema = 'YES'")?;
let mut cursor: Option<PostgresRawValue> = None;
loop {
@ -152,8 +150,6 @@ pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow:
cursor = last_value
}
db.query("SET reshape.is_old_schema = ''")?;
Ok(())
}

View File

@ -61,7 +61,7 @@ impl Action for RemoveColumn {
CREATE OR REPLACE FUNCTION {trigger_name}()
RETURNS TRIGGER AS $$
BEGIN
IF NOT reshape.is_old_schema() IS NULL THEN
IF reshape.is_new_schema() THEN
DECLARE
{declarations}
BEGIN