mirror of
https://github.com/ilyakooo0/reshape.git
synced 2024-11-25 14:12:22 +03:00
Add support for generated constraints on columns
This commit is contained in:
parent
101a414e00
commit
fda6dc8f40
22
README.md
22
README.md
@ -63,14 +63,15 @@ table = "users"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "id"
|
||||
type = "SERIAL"
|
||||
type = "INTEGER"
|
||||
generated = "ALWAYS AS IDENTITY"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "name"
|
||||
type = "TEXT"
|
||||
```
|
||||
|
||||
This is the equivalent of running `CREATE TABLE users (id SERIAL, name TEXT)`.
|
||||
This is the equivalent of running `CREATE TABLE users (id INTEGER GENERATED ALWAYS AS IDENTITY, name TEXT)`.
|
||||
|
||||
### Preparing your application
|
||||
|
||||
@ -109,7 +110,8 @@ table = "customers"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "id"
|
||||
type = "SERIAL"
|
||||
type = "INTEGER"
|
||||
generated = "ALWAYS AS IDENTITY"
|
||||
|
||||
[[actions]]
|
||||
type = "create_table"
|
||||
@ -138,11 +140,12 @@ primary_key = "id"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "id"
|
||||
type = "SERIAL"
|
||||
type = "INTEGER"
|
||||
generated = "ALWAYS AS IDENTITY"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "name"
|
||||
type = "SERIAL"
|
||||
type = "TEXT"
|
||||
|
||||
# Columns default to nullable
|
||||
nullable = false
|
||||
@ -161,7 +164,8 @@ primary_key = "id"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "id"
|
||||
type = "SERIAL"
|
||||
type = "INTEGER"
|
||||
generated = "ALWAYS AS IDENTITY"
|
||||
|
||||
[[actions]]
|
||||
type = "create_table"
|
||||
@ -170,7 +174,8 @@ primary_key = "id"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "id"
|
||||
type = "SERIAL"
|
||||
type = "INTEGER"
|
||||
generated = "ALWAYS AS IDENTITY"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "user_id"
|
||||
@ -343,7 +348,8 @@ primary_key = "id"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "id"
|
||||
type = "SERIAL"
|
||||
type = "INTEGER"
|
||||
generated = "ALWAYS AS IDENTITY"
|
||||
|
||||
[[actions.columns]]
|
||||
name = "name"
|
||||
|
@ -45,11 +45,17 @@ impl Action for AddColumn {
|
||||
self.column.name.to_string(),
|
||||
self.column.data_type.to_string(),
|
||||
];
|
||||
|
||||
if let Some(default) = &self.column.default {
|
||||
definition_parts.push("DEFAULT".to_string());
|
||||
definition_parts.push(default.to_string());
|
||||
}
|
||||
|
||||
if let Some(generated) = &self.column.generated {
|
||||
definition_parts.push("GENERATED".to_string());
|
||||
definition_parts.push(generated.to_string());
|
||||
}
|
||||
|
||||
// Add column as NOT NULL
|
||||
let query = format!(
|
||||
"
|
||||
|
@ -14,6 +14,8 @@ pub struct Column {
|
||||
pub nullable: bool,
|
||||
|
||||
pub default: Option<String>,
|
||||
|
||||
pub generated: Option<String>,
|
||||
}
|
||||
|
||||
fn nullable_default() -> bool {
|
||||
|
@ -39,6 +39,11 @@ impl Action for CreateTable {
|
||||
parts.push("NOT NULL".to_string());
|
||||
}
|
||||
|
||||
if let Some(generated) = &column.generated {
|
||||
parts.push("GENERATED".to_string());
|
||||
parts.push(generated.to_string());
|
||||
}
|
||||
|
||||
parts.join(" ")
|
||||
})
|
||||
.collect();
|
||||
|
@ -17,12 +17,14 @@ fn add_column() {
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -34,6 +36,7 @@ fn add_column() {
|
||||
data_type: "TEXT".to_string(),
|
||||
nullable: false,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
up: Some("(STRING_TO_ARRAY(name, ' '))[1]".to_string()),
|
||||
})
|
||||
@ -44,6 +47,7 @@ fn add_column() {
|
||||
data_type: "TEXT".to_string(),
|
||||
nullable: false,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
up: Some("(STRING_TO_ARRAY(name, ' '))[2]".to_string()),
|
||||
});
|
||||
@ -128,9 +132,10 @@ fn add_column_nullable() {
|
||||
foreign_keys: vec![],
|
||||
columns: vec![Column {
|
||||
name: "id".to_string(),
|
||||
data_type: "SERIAL".to_string(),
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
}],
|
||||
});
|
||||
let add_name_column = Migration::new("add_nullable_name_column", None).with_action(AddColumn {
|
||||
@ -140,6 +145,7 @@ fn add_column_nullable() {
|
||||
data_type: "TEXT".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
up: None,
|
||||
});
|
||||
@ -223,9 +229,10 @@ fn add_column_with_default() {
|
||||
foreign_keys: vec![],
|
||||
columns: vec![Column {
|
||||
name: "id".to_string(),
|
||||
data_type: "SERIAL".to_string(),
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
}],
|
||||
});
|
||||
let add_name_column =
|
||||
@ -236,6 +243,7 @@ fn add_column_with_default() {
|
||||
data_type: "TEXT".to_string(),
|
||||
nullable: false,
|
||||
default: Some("'DEFAULT'".to_string()),
|
||||
generated: None,
|
||||
},
|
||||
up: None,
|
||||
});
|
||||
|
@ -14,15 +14,17 @@ fn add_index() {
|
||||
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
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -14,15 +14,17 @@ fn alter_column_data() {
|
||||
columns: vec![
|
||||
Column {
|
||||
name: "id".to_string(),
|
||||
data_type: "SERIAL".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,
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -116,15 +118,17 @@ fn alter_column_set_not_null() {
|
||||
columns: vec![
|
||||
Column {
|
||||
name: "id".to_string(),
|
||||
data_type: "SERIAL".to_string(),
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
Column {
|
||||
name: "name".to_string(),
|
||||
data_type: "TEXT".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -218,15 +222,17 @@ fn alter_column_rename() {
|
||||
columns: vec![
|
||||
Column {
|
||||
name: "id".to_string(),
|
||||
data_type: "SERIAL".to_string(),
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
Column {
|
||||
name: "name".to_string(),
|
||||
data_type: "TEXT".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -303,15 +309,17 @@ fn alter_column_multiple() {
|
||||
columns: vec![
|
||||
Column {
|
||||
name: "id".to_string(),
|
||||
data_type: "SERIAL".to_string(),
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: true,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
Column {
|
||||
name: "counter".to_string(),
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: false,
|
||||
default: None,
|
||||
generated: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -17,21 +17,24 @@ fn create_table() {
|
||||
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
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -72,7 +75,7 @@ fn create_table() {
|
||||
// id column
|
||||
let id_row = &result[0];
|
||||
assert_eq!("id", id_row.get::<_, String>("column_name"));
|
||||
assert!(id_row.get::<_, Option<String>>("column_default").is_some());
|
||||
assert!(id_row.get::<_, Option<String>>("column_default").is_none());
|
||||
assert_eq!("NO", id_row.get::<_, String>("is_nullable"));
|
||||
assert_eq!("integer", id_row.get::<_, String>("data_type"));
|
||||
|
||||
@ -133,6 +136,7 @@ fn create_table_with_foreign_keys() {
|
||||
data_type: "SERIAL".to_string(),
|
||||
nullable: true, // Will be ignored by Postgres as the column is a SERIAL
|
||||
default: None,
|
||||
generated: None,
|
||||
}],
|
||||
});
|
||||
|
||||
@ -151,12 +155,14 @@ fn create_table_with_foreign_keys() {
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -14,15 +14,17 @@ fn remove_column() {
|
||||
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
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -53,7 +55,7 @@ fn remove_column() {
|
||||
|
||||
// Insert using old schema and ensure it can be retrieved through new schema
|
||||
old_db
|
||||
.simple_query("INSERT INTO users(name) VALUES ('John Doe')")
|
||||
.simple_query("INSERT INTO users(id, name) VALUES (1, 'John Doe')")
|
||||
.unwrap();
|
||||
let results = new_db
|
||||
.query("SELECT id FROM users WHERE id = 1", &[])
|
||||
@ -66,7 +68,7 @@ fn remove_column() {
|
||||
|
||||
// Insert using new schema and ensure the down function is correctly applied
|
||||
new_db
|
||||
.simple_query("INSERT INTO users DEFAULT VALUES")
|
||||
.simple_query("INSERT INTO users(id) VALUES (2)")
|
||||
.unwrap();
|
||||
let result = old_db
|
||||
.query_opt("SELECT name FROM users WHERE id = 2", &[])
|
||||
|
@ -16,6 +16,7 @@ fn remove_table() {
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: false,
|
||||
default: None,
|
||||
generated: None,
|
||||
}],
|
||||
});
|
||||
let remove_table_migration =
|
||||
|
@ -16,6 +16,7 @@ fn rename_table() {
|
||||
data_type: "INTEGER".to_string(),
|
||||
nullable: false,
|
||||
default: None,
|
||||
generated: None,
|
||||
}],
|
||||
});
|
||||
let rename_table_migration = Migration::new("rename_users_table_to_customers", None)
|
||||
|
Loading…
Reference in New Issue
Block a user