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