fix(schema): include postgres column comments in ddl
This commit is contained in:
1 parent
153daf6c09
commit
c00074dfdf
1 file changed
+73
-18
@@ -829,6 +829,37 @@ mod object_source_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod ddl_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn column(name: &str, data_type: &str) -> db::ColumnInfo {
|
||||||
|
db::ColumnInfo {
|
||||||
|
name: name.to_string(),
|
||||||
|
data_type: data_type.to_string(),
|
||||||
|
is_nullable: true,
|
||||||
|
column_default: None,
|
||||||
|
is_primary_key: false,
|
||||||
|
extra: None,
|
||||||
|
comment: None,
|
||||||
|
numeric_precision: None,
|
||||||
|
numeric_scale: None,
|
||||||
|
character_maximum_length: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn postgres_table_ddl_includes_column_comments() {
|
||||||
|
let mut display_name = column("display_name", "text");
|
||||||
|
display_name.comment = Some("User's display name".to_string());
|
||||||
|
let columns = vec![display_name];
|
||||||
|
|
||||||
|
let ddl = render_postgres_table_ddl("public", "users", &columns, &[], &[]);
|
||||||
|
|
||||||
|
assert!(ddl.contains("COMMENT ON COLUMN \"public\".\"users\".\"display_name\" IS 'User''s display name';"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn mysql_ddl(pool: &sqlx::mysql::MySqlPool, table: &str) -> Result<String, String> {
|
pub async fn mysql_ddl(pool: &sqlx::mysql::MySqlPool, table: &str) -> Result<String, String> {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
let sql = format!("SHOW CREATE TABLE `{}`", table.replace('`', "``"));
|
let sql = format!("SHOW CREATE TABLE `{}`", table.replace('`', "``"));
|
||||||
@@ -855,11 +886,22 @@ pub async fn pg_ddl(pool: &sqlx::postgres::PgPool, schema: &str, table: &str) ->
|
|||||||
db::postgres::list_foreign_keys(pool, schema, table),
|
db::postgres::list_foreign_keys(pool, schema, table),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut ddl = format!("CREATE TABLE \"{schema}\".\"{table}\" (\n");
|
Ok(render_postgres_table_ddl(schema, table, &columns, &indexes, &fkeys))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_postgres_table_ddl(
|
||||||
|
schema: &str,
|
||||||
|
table: &str,
|
||||||
|
columns: &[db::ColumnInfo],
|
||||||
|
indexes: &[db::IndexInfo],
|
||||||
|
fkeys: &[db::ForeignKeyInfo],
|
||||||
|
) -> String {
|
||||||
|
let table_name = format!("{}.{}", pg_ident(schema), pg_ident(table));
|
||||||
|
let mut ddl = format!("CREATE TABLE {table_name} (\n");
|
||||||
let col_lines: Vec<String> = columns
|
let col_lines: Vec<String> = columns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| {
|
.map(|c| {
|
||||||
let mut line = format!(" \"{}\" {}", c.name, c.data_type);
|
let mut line = format!(" {} {}", pg_ident(&c.name), c.data_type);
|
||||||
if !c.is_nullable {
|
if !c.is_nullable {
|
||||||
line.push_str(" NOT NULL");
|
line.push_str(" NOT NULL");
|
||||||
}
|
}
|
||||||
@@ -873,44 +915,57 @@ pub async fn pg_ddl(pool: &sqlx::postgres::PgPool, schema: &str, table: &str) ->
|
|||||||
|
|
||||||
let pks: Vec<&str> = columns.iter().filter(|c| c.is_primary_key).map(|c| c.name.as_str()).collect();
|
let pks: Vec<&str> = columns.iter().filter(|c| c.is_primary_key).map(|c| c.name.as_str()).collect();
|
||||||
if !pks.is_empty() {
|
if !pks.is_empty() {
|
||||||
ddl.push_str(&format!(
|
ddl.push_str(&format!(",\n PRIMARY KEY ({})", pks.iter().map(|k| pg_ident(k)).collect::<Vec<_>>().join(", ")));
|
||||||
",\n PRIMARY KEY ({})",
|
|
||||||
pks.iter().map(|k| format!("\"{k}\"")).collect::<Vec<_>>().join(", ")
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
for fk in &fkeys {
|
for fk in fkeys {
|
||||||
ddl.push_str(&format!(
|
ddl.push_str(&format!(
|
||||||
",\n CONSTRAINT \"{}\" FOREIGN KEY (\"{}\") REFERENCES \"{}\"(\"{}\")",
|
",\n CONSTRAINT {} FOREIGN KEY ({}) REFERENCES {}({})",
|
||||||
fk.name, fk.column, fk.ref_table, fk.ref_column
|
pg_ident(&fk.name),
|
||||||
|
pg_ident(&fk.column),
|
||||||
|
pg_ident(&fk.ref_table),
|
||||||
|
pg_ident(&fk.ref_column)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ddl.push_str("\n);\n");
|
ddl.push_str("\n);\n");
|
||||||
|
|
||||||
for idx in &indexes {
|
for col in columns {
|
||||||
|
if let Some(comment) = col.comment.as_deref().filter(|comment| !comment.is_empty()) {
|
||||||
|
ddl.push_str(&format!(
|
||||||
|
"\nCOMMENT ON COLUMN {table_name}.{} IS {};",
|
||||||
|
pg_ident(&col.name),
|
||||||
|
sql_string(comment)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx in indexes {
|
||||||
if idx.is_primary {
|
if idx.is_primary {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let unique = if idx.is_unique { "UNIQUE " } else { "" };
|
let unique = if idx.is_unique { "UNIQUE " } else { "" };
|
||||||
let cols = idx.columns.iter().map(|c| format!("\"{c}\"")).collect::<Vec<_>>().join(", ");
|
let cols = idx.columns.iter().map(|c| pg_ident(c)).collect::<Vec<_>>().join(", ");
|
||||||
let using = idx.index_type.as_deref().map(|t| format!(" USING {t}")).unwrap_or_default();
|
let using = idx.index_type.as_deref().map(|t| format!(" USING {t}")).unwrap_or_default();
|
||||||
let include = idx
|
let include = idx
|
||||||
.included_columns
|
.included_columns
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.filter(|c| !c.is_empty())
|
.filter(|c| !c.is_empty())
|
||||||
.map(|cols| {
|
.map(|cols| format!(" INCLUDE ({})", cols.iter().map(|c| pg_ident(c)).collect::<Vec<_>>().join(", ")))
|
||||||
format!(" INCLUDE ({})", cols.iter().map(|c| format!("\"{c}\"")).collect::<Vec<_>>().join(", "))
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let filter = idx.filter.as_deref().map(|f| format!(" WHERE {f}")).unwrap_or_default();
|
let filter = idx.filter.as_deref().map(|f| format!(" WHERE {f}")).unwrap_or_default();
|
||||||
ddl.push_str(&format!(
|
ddl.push_str(&format!(
|
||||||
"\nCREATE {unique}INDEX \"{}\" ON \"{schema}\".\"{table}\"{using} ({cols}){include}{filter};",
|
"\nCREATE {unique}INDEX {} ON {table_name}{using} ({cols}){include}{filter};",
|
||||||
idx.name
|
pg_ident(&idx.name)
|
||||||
));
|
));
|
||||||
if let Some(ref c) = idx.comment {
|
if let Some(ref c) = idx.comment {
|
||||||
ddl.push_str(&format!("\nCOMMENT ON INDEX \"{schema}\".\"{}\" IS '{}';", idx.name, c.replace('\'', "''")));
|
ddl.push_str(&format!(
|
||||||
|
"\nCOMMENT ON INDEX {}.{} IS {};",
|
||||||
|
pg_ident(schema),
|
||||||
|
pg_ident(&idx.name),
|
||||||
|
sql_string(c)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ddl)
|
ddl
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn build_sqlserver_ddl(
|
pub async fn build_sqlserver_ddl(
|
||||||
|
|||||||
Reference in new issue
Block a user