mirror of
https://github.com/ilyakooo0/reshape.git
synced 2024-11-29 12:03:35 +03:00
Add quotes for all identifiers in queries
This commit is contained in:
parent
0dd8272e9f
commit
9cd9bd395b
24
src/lib.rs
24
src/lib.rs
@ -363,13 +363,23 @@ impl Reshape {
|
||||
let select_columns: Vec<String> = table
|
||||
.columns
|
||||
.iter()
|
||||
.map(|column| format!("{} AS {}", column.real_name, column.name))
|
||||
.map(|column| {
|
||||
format!(
|
||||
r#"
|
||||
"{real_name}" AS "{alias}"
|
||||
"#,
|
||||
real_name = column.real_name,
|
||||
alias = column.name,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
db.run(&format!(
|
||||
"CREATE OR REPLACE VIEW {schema}.{view_name} AS
|
||||
r#"
|
||||
CREATE OR REPLACE VIEW {schema}."{view_name}" AS
|
||||
SELECT {columns}
|
||||
FROM {table_name}",
|
||||
FROM "{table_name}"
|
||||
"#,
|
||||
schema = schema,
|
||||
table_name = table.real_name,
|
||||
view_name = table.name,
|
||||
@ -400,8 +410,12 @@ impl Reshape {
|
||||
// Remove all tables
|
||||
let schema = Schema::new();
|
||||
for table in schema.get_tables(&mut self.db)? {
|
||||
self.db
|
||||
.run(&format!("DROP TABLE IF EXISTS {} CASCADE", table.real_name))?;
|
||||
self.db.run(&format!(
|
||||
r#"
|
||||
DROP TABLE IF EXISTS "{}" CASCADE
|
||||
"#,
|
||||
table.real_name
|
||||
))?;
|
||||
}
|
||||
|
||||
// Reset state
|
||||
|
@ -77,10 +77,10 @@ impl Action for AddColumn {
|
||||
|
||||
// Add column as NOT NULL
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
ADD COLUMN IF NOT EXISTS {definition};
|
||||
",
|
||||
"#,
|
||||
table = self.table,
|
||||
definition = definition_parts.join(" "),
|
||||
);
|
||||
@ -104,7 +104,7 @@ impl Action for AddColumn {
|
||||
|
||||
// Add triggers to fill in values as they are inserted/updated
|
||||
let query = format!(
|
||||
"
|
||||
r#"
|
||||
CREATE OR REPLACE FUNCTION {trigger_name}()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
@ -119,9 +119,9 @@ impl Action for AddColumn {
|
||||
END
|
||||
$$ language 'plpgsql';
|
||||
|
||||
DROP TRIGGER IF EXISTS {trigger_name} ON {table};
|
||||
CREATE TRIGGER {trigger_name} BEFORE UPDATE OR INSERT ON {table} FOR EACH ROW EXECUTE PROCEDURE {trigger_name}();
|
||||
",
|
||||
DROP TRIGGER IF EXISTS "{trigger_name}" ON "{table}";
|
||||
CREATE TRIGGER "{trigger_name}" BEFORE UPDATE OR INSERT ON "{table}" FOR EACH ROW EXECUTE PROCEDURE {trigger_name}();
|
||||
"#,
|
||||
temp_column_name = temp_column_name,
|
||||
trigger_name = self.trigger_name(ctx),
|
||||
up = up,
|
||||
@ -143,11 +143,11 @@ impl Action for AddColumn {
|
||||
// Thanks to this, we can set the full column as NOT NULL later with minimal locking.
|
||||
if !self.column.nullable {
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
ADD CONSTRAINT {constraint_name}
|
||||
CHECK ({column} IS NOT NULL) NOT VALID
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
ADD CONSTRAINT "{constraint_name}"
|
||||
CHECK ("{column}" IS NOT NULL) NOT VALID
|
||||
"#,
|
||||
table = self.table,
|
||||
constraint_name = self.not_null_constraint_name(ctx),
|
||||
column = temp_column_name,
|
||||
@ -168,10 +168,10 @@ impl Action for AddColumn {
|
||||
|
||||
// Remove triggers and procedures
|
||||
let query = format!(
|
||||
"
|
||||
DROP TRIGGER IF EXISTS {trigger_name} ON {table};
|
||||
DROP FUNCTION IF EXISTS {trigger_name};
|
||||
",
|
||||
r#"
|
||||
DROP TRIGGER IF EXISTS "{trigger_name}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{trigger_name}";
|
||||
"#,
|
||||
table = self.table,
|
||||
trigger_name = self.trigger_name(ctx),
|
||||
);
|
||||
@ -184,10 +184,10 @@ impl Action for AddColumn {
|
||||
// Validate the temporary constraint (should always be valid).
|
||||
// This performs a sequential scan but does not take an exclusive lock.
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
VALIDATE CONSTRAINT {constraint_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
VALIDATE CONSTRAINT "{constraint_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
constraint_name = self.not_null_constraint_name(ctx),
|
||||
);
|
||||
@ -200,10 +200,10 @@ impl Action for AddColumn {
|
||||
// the existing constraint for correctness which makes the lock short-lived.
|
||||
// Source: https://dba.stackexchange.com/a/268128
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
ALTER COLUMN {column} SET NOT NULL
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
ALTER COLUMN "{column}" SET NOT NULL
|
||||
"#,
|
||||
table = self.table,
|
||||
column = self.temp_column_name(ctx),
|
||||
);
|
||||
@ -213,10 +213,10 @@ impl Action for AddColumn {
|
||||
|
||||
// Drop the temporary constraint
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
DROP CONSTRAINT {constraint_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
DROP CONSTRAINT "{constraint_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
constraint_name = self.not_null_constraint_name(ctx),
|
||||
);
|
||||
@ -228,10 +228,10 @@ impl Action for AddColumn {
|
||||
// Rename the temporary column to its real name
|
||||
transaction
|
||||
.run(&format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
RENAME COLUMN {temp_column_name} TO {column_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
RENAME COLUMN "{temp_column_name}" TO "{column_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
temp_column_name = self.temp_column_name(ctx),
|
||||
column_name = self.column.name,
|
||||
@ -252,10 +252,10 @@ impl Action for AddColumn {
|
||||
fn abort(&self, ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||
// Remove column
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
DROP COLUMN IF EXISTS {column}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
DROP COLUMN IF EXISTS "{column}"
|
||||
"#,
|
||||
table = self.table,
|
||||
column = self.temp_column_name(ctx),
|
||||
);
|
||||
@ -263,10 +263,10 @@ impl Action for AddColumn {
|
||||
|
||||
// Remove triggers and procedures
|
||||
let query = format!(
|
||||
"
|
||||
DROP TRIGGER IF EXISTS {trigger_name} ON {table};
|
||||
DROP FUNCTION IF EXISTS {trigger_name};
|
||||
",
|
||||
r#"
|
||||
DROP TRIGGER IF EXISTS "{trigger_name}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{trigger_name}";
|
||||
"#,
|
||||
table = self.table,
|
||||
trigger_name = self.trigger_name(ctx),
|
||||
);
|
||||
|
@ -31,13 +31,13 @@ impl Action for AddIndex {
|
||||
.columns
|
||||
.iter()
|
||||
.filter(|column| self.columns.contains(&column.name))
|
||||
.map(|column| column.real_name.to_string())
|
||||
.map(|column| format!("\"{}\"", column.real_name))
|
||||
.collect();
|
||||
|
||||
db.run(&format!(
|
||||
"
|
||||
CREATE INDEX CONCURRENTLY {name} ON {table} ({columns})
|
||||
",
|
||||
r#"
|
||||
CREATE INDEX CONCURRENTLY "{name}" ON "{table}" ({columns})
|
||||
"#,
|
||||
name = self.name,
|
||||
table = self.table,
|
||||
columns = column_real_names.join(", "),
|
||||
@ -58,9 +58,9 @@ impl Action for AddIndex {
|
||||
|
||||
fn abort(&self, _ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||
db.run(&format!(
|
||||
"
|
||||
DROP INDEX CONCURRENTLY IF EXISTS {name}
|
||||
",
|
||||
r#"
|
||||
DROP INDEX CONCURRENTLY IF EXISTS "{name}"
|
||||
"#,
|
||||
name = self.name,
|
||||
))
|
||||
.context("failed to drop index")?;
|
||||
|
@ -67,14 +67,13 @@ impl Action for AlterColumn {
|
||||
}
|
||||
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
ADD COLUMN IF NOT EXISTS {temp_column_definition}
|
||||
",
|
||||
"#,
|
||||
table = self.table,
|
||||
temp_column_definition = temp_column_definition_parts.join(" "),
|
||||
);
|
||||
println!("Query {}", query);
|
||||
db.run(&query).context("failed to add temporary column")?;
|
||||
|
||||
// If up or down wasn't provided, we default to simply moving the value over.
|
||||
@ -97,7 +96,7 @@ impl Action for AlterColumn {
|
||||
.collect();
|
||||
|
||||
let query = format!(
|
||||
"
|
||||
r#"
|
||||
CREATE OR REPLACE FUNCTION {up_trigger}()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
@ -113,8 +112,8 @@ impl Action for AlterColumn {
|
||||
END
|
||||
$$ language 'plpgsql';
|
||||
|
||||
DROP TRIGGER IF EXISTS {up_trigger} ON {table};
|
||||
CREATE TRIGGER {up_trigger} BEFORE INSERT OR UPDATE ON {table} FOR EACH ROW EXECUTE PROCEDURE {up_trigger}();
|
||||
DROP TRIGGER IF EXISTS "{up_trigger}" ON "{table}";
|
||||
CREATE TRIGGER "{up_trigger}" BEFORE INSERT OR UPDATE ON "{table}" FOR EACH ROW EXECUTE PROCEDURE {up_trigger}();
|
||||
|
||||
CREATE OR REPLACE FUNCTION {down_trigger}()
|
||||
RETURNS TRIGGER AS $$
|
||||
@ -131,19 +130,19 @@ impl Action for AlterColumn {
|
||||
END
|
||||
$$ language 'plpgsql';
|
||||
|
||||
DROP TRIGGER IF EXISTS {down_trigger} ON {table};
|
||||
CREATE TRIGGER {down_trigger} BEFORE INSERT OR UPDATE ON {table} FOR EACH ROW EXECUTE PROCEDURE {down_trigger}();
|
||||
",
|
||||
existing_column = &self.column,
|
||||
existing_column_real = column.real_name,
|
||||
temp_column = self.temporary_column_name(ctx),
|
||||
up = up,
|
||||
down = down,
|
||||
table = self.table,
|
||||
up_trigger = self.up_trigger_name(ctx),
|
||||
down_trigger = self.down_trigger_name(ctx),
|
||||
declarations = declarations.join("\n"),
|
||||
);
|
||||
DROP TRIGGER IF EXISTS "{down_trigger}" ON "{table}";
|
||||
CREATE TRIGGER "{down_trigger}" BEFORE INSERT OR UPDATE ON "{table}" FOR EACH ROW EXECUTE PROCEDURE {down_trigger}();
|
||||
"#,
|
||||
existing_column = &self.column,
|
||||
existing_column_real = column.real_name,
|
||||
temp_column = self.temporary_column_name(ctx),
|
||||
up = up,
|
||||
down = down,
|
||||
table = self.table,
|
||||
up_trigger = self.up_trigger_name(ctx),
|
||||
down_trigger = self.down_trigger_name(ctx),
|
||||
declarations = declarations.join("\n"),
|
||||
);
|
||||
db.run(&query)
|
||||
.context("failed to create up and down triggers")?;
|
||||
|
||||
@ -157,11 +156,11 @@ impl Action for AlterColumn {
|
||||
// Thanks to this, we can set the full column as NOT NULL later with minimal locking.
|
||||
if !column.nullable {
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
ADD CONSTRAINT {constraint_name}
|
||||
CHECK ({column} IS NOT NULL) NOT VALID
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
ADD CONSTRAINT "{constraint_name}"
|
||||
CHECK ("{column}" IS NOT NULL) NOT VALID
|
||||
"#,
|
||||
table = self.table,
|
||||
constraint_name = self.not_null_constraint_name(ctx),
|
||||
column = self.temporary_column_name(ctx),
|
||||
@ -181,10 +180,10 @@ impl Action for AlterColumn {
|
||||
if self.can_short_circuit() {
|
||||
if let Some(new_name) = &self.changes.name {
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
RENAME COLUMN {existing_name} TO {new_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
RENAME COLUMN "{existing_name}" TO "{new_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
existing_name = self.column,
|
||||
new_name = new_name,
|
||||
@ -210,10 +209,10 @@ impl Action for AlterColumn {
|
||||
// Validate the temporary constraint (should always be valid).
|
||||
// This performs a sequential scan but does not take an exclusive lock.
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
VALIDATE CONSTRAINT {constraint_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
VALIDATE CONSTRAINT "{constraint_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
constraint_name = self.not_null_constraint_name(ctx),
|
||||
);
|
||||
@ -225,10 +224,10 @@ impl Action for AlterColumn {
|
||||
// the existing constraint for correctness which makes the lock short-lived.
|
||||
// Source: https://dba.stackexchange.com/a/268128
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
ALTER COLUMN {column} SET NOT NULL
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
ALTER COLUMN "{column}" SET NOT NULL
|
||||
"#,
|
||||
table = self.table,
|
||||
column = self.temporary_column_name(ctx),
|
||||
);
|
||||
@ -236,10 +235,10 @@ impl Action for AlterColumn {
|
||||
|
||||
// Drop the temporary constraint
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
DROP CONSTRAINT {constraint_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
DROP CONSTRAINT "{constraint_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
constraint_name = self.not_null_constraint_name(ctx),
|
||||
);
|
||||
@ -249,19 +248,20 @@ impl Action for AlterColumn {
|
||||
|
||||
// Remove old column
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {} DROP COLUMN {} CASCADE
|
||||
",
|
||||
self.table, self.column
|
||||
r#"
|
||||
ALTER TABLE "{table}" DROP COLUMN "{column}" CASCADE
|
||||
"#,
|
||||
table = self.table,
|
||||
column = self.column,
|
||||
);
|
||||
db.run(&query).context("failed to drop old column")?;
|
||||
|
||||
// Rename temporary column
|
||||
let column_name = self.changes.name.as_deref().unwrap_or(&self.column);
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table} RENAME COLUMN {temp_column} TO {name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}" RENAME COLUMN "{temp_column}" TO "{name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
temp_column = self.temporary_column_name(ctx),
|
||||
name = column_name,
|
||||
@ -271,13 +271,13 @@ impl Action for AlterColumn {
|
||||
|
||||
// Remove triggers and procedures
|
||||
let query = format!(
|
||||
"
|
||||
DROP TRIGGER IF EXISTS {up_trigger} ON {table};
|
||||
DROP FUNCTION IF EXISTS {up_trigger};
|
||||
r#"
|
||||
DROP TRIGGER IF EXISTS "{up_trigger}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{up_trigger}";
|
||||
|
||||
DROP TRIGGER IF EXISTS {down_trigger} ON {table};
|
||||
DROP FUNCTION IF EXISTS {down_trigger};
|
||||
",
|
||||
DROP TRIGGER IF EXISTS "{down_trigger}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{down_trigger}";
|
||||
"#,
|
||||
table = self.table,
|
||||
up_trigger = self.up_trigger_name(ctx),
|
||||
down_trigger = self.down_trigger_name(ctx),
|
||||
@ -313,10 +313,10 @@ impl Action for AlterColumn {
|
||||
fn abort(&self, ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||
// Drop temporary column
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
DROP COLUMN IF EXISTS {temp_column};
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
DROP COLUMN IF EXISTS "{temp_column}";
|
||||
"#,
|
||||
table = self.table,
|
||||
temp_column = self.temporary_column_name(ctx),
|
||||
);
|
||||
@ -324,13 +324,13 @@ impl Action for AlterColumn {
|
||||
|
||||
// Remove triggers and procedures
|
||||
let query = format!(
|
||||
"
|
||||
DROP TRIGGER IF EXISTS {up_trigger} ON {table};
|
||||
DROP FUNCTION IF EXISTS {up_trigger};
|
||||
r#"
|
||||
DROP TRIGGER IF EXISTS "{up_trigger}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{up_trigger}";
|
||||
|
||||
DROP TRIGGER IF EXISTS {down_trigger} ON {table};
|
||||
DROP FUNCTION IF EXISTS {down_trigger};
|
||||
",
|
||||
DROP TRIGGER IF EXISTS "{down_trigger}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{down_trigger}";
|
||||
"#,
|
||||
table = self.table,
|
||||
up_trigger = self.up_trigger_name(ctx),
|
||||
down_trigger = self.down_trigger_name(ctx),
|
||||
|
@ -87,7 +87,9 @@ pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow:
|
||||
.iter()
|
||||
.map(|column| {
|
||||
format!(
|
||||
"{table}.{column} = rows.{column}",
|
||||
r#"
|
||||
"{table}"."{column}" = rows."{column}"
|
||||
"#,
|
||||
table = table,
|
||||
column = column,
|
||||
)
|
||||
@ -97,7 +99,7 @@ pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow:
|
||||
|
||||
let returning_columns = primary_key
|
||||
.iter()
|
||||
.map(|column| format!("rows.{}", column))
|
||||
.map(|column| format!("rows.\"{}\"", column))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
|
||||
@ -113,24 +115,24 @@ pub fn batch_touch_rows(db: &mut dyn Conn, table: &str, column: &str) -> anyhow:
|
||||
};
|
||||
|
||||
let query = format!(
|
||||
"
|
||||
WITH rows AS (
|
||||
SELECT {primary_key_columns}
|
||||
FROM public.{table}
|
||||
{cursor_where}
|
||||
ORDER BY {primary_key_columns}
|
||||
LIMIT {batch_size}
|
||||
), update AS (
|
||||
UPDATE public.{table}
|
||||
SET {column} = {column}
|
||||
FROM rows
|
||||
WHERE {primary_key_where}
|
||||
RETURNING {returning_columns}
|
||||
)
|
||||
SELECT LAST_VALUE(({primary_key_columns})) OVER () AS last_value
|
||||
FROM update
|
||||
LIMIT 1
|
||||
",
|
||||
r#"
|
||||
WITH rows AS (
|
||||
SELECT {primary_key_columns}
|
||||
FROM public."{table}"
|
||||
{cursor_where}
|
||||
ORDER BY {primary_key_columns}
|
||||
LIMIT {batch_size}
|
||||
), update AS (
|
||||
UPDATE public."{table}"
|
||||
SET "{column}" = "{column}"
|
||||
FROM rows
|
||||
WHERE {primary_key_where}
|
||||
RETURNING {returning_columns}
|
||||
)
|
||||
SELECT LAST_VALUE(({primary_key_columns})) OVER () AS last_value
|
||||
FROM update
|
||||
LIMIT 1
|
||||
"#,
|
||||
table = table,
|
||||
primary_key_columns = primary_key_columns,
|
||||
cursor_where = cursor_where,
|
||||
|
@ -42,7 +42,7 @@ impl Action for CreateTable {
|
||||
.columns
|
||||
.iter()
|
||||
.map(|column| {
|
||||
let mut parts = vec![column.name.to_string(), column.data_type.to_string()];
|
||||
let mut parts = vec![format!("\"{}\"", column.name), column.data_type.to_string()];
|
||||
|
||||
if let Some(default) = &column.default {
|
||||
parts.push("DEFAULT".to_string());
|
||||
@ -62,24 +62,46 @@ impl Action for CreateTable {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let primary_key_columns = self.primary_key.join(", ");
|
||||
let primary_key_columns = self
|
||||
.primary_key
|
||||
.iter()
|
||||
// Add quotes around all column names
|
||||
.map(|col| format!("\"{}\"", col))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
definition_rows.push(format!("PRIMARY KEY ({})", primary_key_columns));
|
||||
|
||||
for foreign_key in &self.foreign_keys {
|
||||
// Add quotes around all column names
|
||||
let columns: Vec<String> = foreign_key
|
||||
.columns
|
||||
.iter()
|
||||
.map(|col| format!("\"{}\"", col))
|
||||
.collect();
|
||||
let referenced_columns: Vec<String> = foreign_key
|
||||
.referenced_columns
|
||||
.iter()
|
||||
.map(|col| format!("\"{}\"", col))
|
||||
.collect();
|
||||
|
||||
definition_rows.push(format!(
|
||||
"FOREIGN KEY ({columns}) REFERENCES {table} ({referenced_columns})",
|
||||
columns = foreign_key.columns.join(", "),
|
||||
r#"
|
||||
FOREIGN KEY ({columns}) REFERENCES "{table}" ({referenced_columns})
|
||||
"#,
|
||||
columns = columns.join(", "),
|
||||
table = foreign_key.referenced_table,
|
||||
referenced_columns = foreign_key.referenced_columns.join(", "),
|
||||
referenced_columns = referenced_columns.join(", "),
|
||||
));
|
||||
}
|
||||
|
||||
db.run(&format!(
|
||||
"CREATE TABLE {} (
|
||||
{}
|
||||
)",
|
||||
self.name,
|
||||
definition_rows.join(",\n"),
|
||||
r#"
|
||||
CREATE TABLE "{name}" (
|
||||
{definition}
|
||||
)
|
||||
"#,
|
||||
name = self.name,
|
||||
definition = definition_rows.join(",\n"),
|
||||
))
|
||||
.context("failed to create table")?;
|
||||
Ok(())
|
||||
@ -97,8 +119,13 @@ impl Action for CreateTable {
|
||||
fn update_schema(&self, _ctx: &MigrationContext, _schema: &mut Schema) {}
|
||||
|
||||
fn abort(&self, _ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||
db.run(&format!("DROP TABLE IF EXISTS {}", self.name,))
|
||||
.context("failed to drop table")?;
|
||||
db.run(&format!(
|
||||
r#"
|
||||
DROP TABLE IF EXISTS {name}
|
||||
"#,
|
||||
name = self.name,
|
||||
))
|
||||
.context("failed to drop table")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ impl Action for RemoveColumn {
|
||||
.collect();
|
||||
|
||||
let query = format!(
|
||||
"
|
||||
r#"
|
||||
CREATE OR REPLACE FUNCTION {trigger_name}()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
@ -72,9 +72,9 @@ impl Action for RemoveColumn {
|
||||
END
|
||||
$$ language 'plpgsql';
|
||||
|
||||
DROP TRIGGER IF EXISTS {trigger_name} ON {table};
|
||||
CREATE TRIGGER {trigger_name} BEFORE UPDATE OR INSERT ON {table} FOR EACH ROW EXECUTE PROCEDURE {trigger_name}();
|
||||
",
|
||||
DROP TRIGGER IF EXISTS "{trigger_name}" ON "{table}";
|
||||
CREATE TRIGGER "{trigger_name}" BEFORE UPDATE OR INSERT ON "{table}" FOR EACH ROW EXECUTE PROCEDURE {trigger_name}();
|
||||
"#,
|
||||
column_name = self.column,
|
||||
trigger_name = self.trigger_name(ctx),
|
||||
down = down,
|
||||
@ -94,13 +94,13 @@ impl Action for RemoveColumn {
|
||||
) -> anyhow::Result<Option<Transaction<'a>>> {
|
||||
// Remove column, function and trigger
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE {table}
|
||||
DROP COLUMN IF EXISTS {column};
|
||||
r#"
|
||||
ALTER TABLE "{table}"
|
||||
DROP COLUMN IF EXISTS "{column}";
|
||||
|
||||
DROP TRIGGER IF EXISTS {trigger_name} ON {table};
|
||||
DROP FUNCTION IF EXISTS {trigger_name};
|
||||
",
|
||||
DROP TRIGGER IF EXISTS "{trigger_name}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{trigger_name}";
|
||||
"#,
|
||||
table = self.table,
|
||||
column = self.column,
|
||||
trigger_name = self.trigger_name(ctx),
|
||||
@ -122,10 +122,10 @@ impl Action for RemoveColumn {
|
||||
fn abort(&self, ctx: &MigrationContext, db: &mut dyn Conn) -> anyhow::Result<()> {
|
||||
// Remove function and trigger
|
||||
db.run(&format!(
|
||||
"
|
||||
DROP TRIGGER IF EXISTS {trigger_name} ON {table};
|
||||
DROP FUNCTION IF EXISTS {trigger_name};
|
||||
",
|
||||
r#"
|
||||
DROP TRIGGER IF EXISTS "{trigger_name}" ON "{table}";
|
||||
DROP FUNCTION IF EXISTS "{trigger_name}";
|
||||
"#,
|
||||
table = self.table,
|
||||
trigger_name = self.trigger_name(ctx),
|
||||
))
|
||||
|
@ -33,10 +33,10 @@ impl Action for RemoveIndex {
|
||||
db: &'a mut dyn Conn,
|
||||
) -> anyhow::Result<Option<Transaction<'a>>> {
|
||||
db.run(&format!(
|
||||
"
|
||||
DROP INDEX CONCURRENTLY IF EXISTS {}
|
||||
",
|
||||
self.index
|
||||
r#"
|
||||
DROP INDEX CONCURRENTLY IF EXISTS "{name}"
|
||||
"#,
|
||||
name = self.index
|
||||
))
|
||||
.context("failed to drop index")?;
|
||||
|
||||
|
@ -33,9 +33,9 @@ impl Action for RemoveTable {
|
||||
) -> anyhow::Result<Option<Transaction<'a>>> {
|
||||
// Remove table
|
||||
let query = format!(
|
||||
"
|
||||
DROP TABLE IF EXISTS {table};
|
||||
",
|
||||
r#"
|
||||
DROP TABLE IF EXISTS "{table}";
|
||||
"#,
|
||||
table = self.table,
|
||||
);
|
||||
db.run(&query).context("failed to drop table")?;
|
||||
|
@ -34,10 +34,10 @@ impl Action for RenameTable {
|
||||
) -> anyhow::Result<Option<Transaction<'a>>> {
|
||||
// Rename table
|
||||
let query = format!(
|
||||
"
|
||||
ALTER TABLE IF EXISTS {table}
|
||||
RENAME TO {new_name}
|
||||
",
|
||||
r#"
|
||||
ALTER TABLE IF EXISTS "{table}"
|
||||
RENAME TO "{new_name}"
|
||||
"#,
|
||||
table = self.table,
|
||||
new_name = self.new_name,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user