on main help sign in
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.

commit8888557c3848f037a86822b5a2778e9879324d84 authorfabianlindfors <fabian@flapplabs.se> dateMon 31 Jan 2022, 19:53 (5 years ago) parent4e93a39
6 files changed+13−26
src/helpers.rs+7−16 src/lib.rs+2−2 src/migrations/add_column.rs+1−1 src/migrations/alter_column.rs+2−2 src/migrations/common.rs−4 src/migrations/remove_column.rs+1−1
src/helpers.rs+7−16
@@ -2,37 +2,28 @@ use anyhow::Context;
22
33use crate::db::Conn;
44
5−pub fn set_up_helpers(db: &mut dyn Conn, current_migration: &Option<String>) -> anyhow::Result<()> {
6− let predicate = if let Some(current_migration) = current_migration {
7− format!(
8− "current_setting('search_path') = 'migration_{}' OR setting_bool",
9− current_migration
10− )
11− } else {
12− "setting_bool".to_string()
13− };
14−
5+pub fn set_up_helpers(db: &mut dyn Conn, target_migration: &str) -> anyhow::Result<()> {
156 let query = format!(
167 "
17− CREATE OR REPLACE FUNCTION reshape.is_old_schema()
8+ CREATE OR REPLACE FUNCTION reshape.is_new_schema()
189 RETURNS BOOLEAN AS $$
1910 DECLARE
20− setting TEXT := current_setting('reshape.is_old_schema', TRUE);
11+ setting TEXT := current_setting('reshape.is_new_schema', TRUE);
2112 setting_bool BOOLEAN := setting IS NOT NULL AND setting = 'YES';
2213 BEGIN
23− RETURN {};
14+ RETURN current_setting('search_path') = 'migration_{}' OR setting_bool;
2415 END
2516 $$ language 'plpgsql';
2617 ",
27− predicate
18+ target_migration,
2819 );
2920 db.query(&query)
30− .context("failed creating helper function reshape.is_old_schema()")?;
21+ .context("failed creating helper function reshape.is_new_schema()")?;
3122
3223 Ok(())
3324}
3425
3526pub fn tear_down_helpers(db: &mut dyn Conn) -> anyhow::Result<()> {
36− db.query("DROP FUNCTION IF EXISTS reshape.is_old_schema;")?;
27+ db.query("DROP FUNCTION IF EXISTS reshape.is_new_schema;")?;
3728 Ok(())
3829}
src/lib.rs+2−2
@@ -189,7 +189,8 @@ fn migrate(
189189
190190 println!("Applying {} migrations\n", remaining_migrations.len());
191191
192− helpers::set_up_helpers(db, &current_migration).context("failed to set up helpers")?;
192+ let target_migration = remaining_migrations.last().unwrap().name.to_string();
193+ helpers::set_up_helpers(db, &target_migration).context("failed to set up helpers")?;
193194
194195 let mut new_schema = Schema::new();
195196 let mut last_migration_index = usize::MAX;
@@ -244,7 +245,6 @@ fn migrate(
244245 }
245246
246247 // Create schema and views for migration
247− let target_migration = remaining_migrations.last().unwrap().name.to_string();
248248 create_schema_for_migration(db, &target_migration, &new_schema)
249249 .with_context(|| format!("failed to create schema for migration {}", target_migration))?;
250250
src/migrations/add_column.rs+1−1
@@ -106,7 +106,7 @@ impl Action for AddColumn {
106106 CREATE OR REPLACE FUNCTION {trigger_name}()
107107 RETURNS TRIGGER AS $$
108108 BEGIN
109− IF reshape.is_old_schema() THEN
109+ IF NOT reshape.is_new_schema() THEN
110110 DECLARE
111111 {declarations}
112112 BEGIN
src/migrations/alter_column.rs+2−2
@@ -103,7 +103,7 @@ impl Action for AlterColumn {
103103 CREATE OR REPLACE FUNCTION {up_trigger}()
104104 RETURNS TRIGGER AS $$
105105 BEGIN
106− IF reshape.is_old_schema() THEN
106+ IF NOT reshape.is_new_schema() THEN
107107 DECLARE
108108 {declarations}
109109 {existing_column} public.{table}.{existing_column_real}%TYPE := NEW.{existing_column_real};
@@ -121,7 +121,7 @@ impl Action for AlterColumn {
121121 CREATE OR REPLACE FUNCTION {down_trigger}()
122122 RETURNS TRIGGER AS $$
123123 BEGIN
124− IF NOT reshape.is_old_schema() THEN
124+ IF reshape.is_new_schema() THEN
125125 DECLARE
126126 {declarations}
127127 {existing_column} public.{table}.{temp_column}%TYPE := NEW.{temp_column};
src/migrations/common.rs−4
@@ -72,8 +72,6 @@ impl ToSql for PostgresRawValue {
7272pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow::Result<()> {
7373 const BATCH_SIZE: u16 = 1000;
7474
75− db.query("SET reshape.is_old_schema = 'YES'")?;
76−
7775 let mut cursor: Option<PostgresRawValue> = None;
7876
7977 loop {
@@ -152,8 +150,6 @@ pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow:
152150 cursor = last_value
153151 }
154152
155− db.query("SET reshape.is_old_schema = ''")?;
156−
157153 Ok(())
158154}
159155
src/migrations/remove_column.rs+1−1
@@ -61,7 +61,7 @@ impl Action for RemoveColumn {
6161 CREATE OR REPLACE FUNCTION {trigger_name}()
6262 RETURNS TRIGGER AS $$
6363 BEGIN
64− IF NOT reshape.is_old_schema() IS NULL THEN
64+ IF reshape.is_new_schema() THEN
6565 DECLARE
6666 {declarations}
6767 BEGIN