fix: Remove duplicate code in table_migration.rs
All checks were successful
BotServer CI/CD / build (push) Successful in 4m27s
All checks were successful
BotServer CI/CD / build (push) Successful in 4m27s
- Removed duplicate DbColumn struct, PROTECTED_COLUMNS const, and sync_table_schema fn - File now has single clean implementation with column drop protection
This commit is contained in:
parent
d785d255c6
commit
62e9a64340
1 changed files with 0 additions and 145 deletions
|
|
@ -172,151 +172,6 @@ pub fn sync_table_schema(
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
/// Column metadata from database
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DbColumn {
|
||||
pub name: String,
|
||||
pub data_type: String,
|
||||
pub is_nullable: bool,
|
||||
}
|
||||
|
||||
/// Columns that should never be dropped automatically
|
||||
const PROTECTED_COLUMNS: &[&str] = &[
|
||||
"id",
|
||||
"bot_id",
|
||||
"org_id",
|
||||
"user_id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"is_deleted",
|
||||
"version",
|
||||
"tenant_id",
|
||||
];
|
||||
|
||||
/// Compare and sync table schema with definition
|
||||
pub fn sync_table_schema(
|
||||
table: &TableDefinition,
|
||||
existing_columns: &[DbColumn],
|
||||
create_sql: &str,
|
||||
conn: &mut diesel::PgConnection,
|
||||
) -> Result<MigrationResult, Box<dyn Error + Send + Sync>> {
|
||||
let mut result = MigrationResult::default();
|
||||
|
||||
// If no columns exist, create the table
|
||||
if existing_columns.is_empty() {
|
||||
info!("Creating new table: {}", table.name);
|
||||
sql_query(create_sql)
|
||||
.execute(conn)
|
||||
.map_err(|e| format!("Failed to create table {}: {}", table.name, e))?;
|
||||
result.tables_created += 1;
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
let table_name = sanitize_identifier(&table.name);
|
||||
let defined_col_names: std::collections::HashSet<String> =
|
||||
table.fields.iter().map(|f| f.name.clone()).collect();
|
||||
let existing_col_names: std::collections::HashSet<String> =
|
||||
existing_columns.iter().map(|c| c.name.clone()).collect();
|
||||
|
||||
// Add missing columns
|
||||
let mut missing_columns: Vec<&FieldDefinition> = Vec::new();
|
||||
for field in &table.fields {
|
||||
if !existing_col_names.contains(&field.name) {
|
||||
missing_columns.push(field);
|
||||
}
|
||||
}
|
||||
|
||||
if !missing_columns.is_empty() {
|
||||
info!(
|
||||
"Table {} is missing {} columns, adding them",
|
||||
table.name,
|
||||
missing_columns.len()
|
||||
);
|
||||
|
||||
for field in &missing_columns {
|
||||
let sql_type = map_type_to_sql(field, "postgres");
|
||||
let column_sql = format!(
|
||||
"ALTER TABLE {} ADD COLUMN IF NOT EXISTS {} {}",
|
||||
&table_name,
|
||||
sanitize_identifier(&field.name),
|
||||
sql_type
|
||||
);
|
||||
|
||||
info!(
|
||||
"Adding column: {}.{} ({})",
|
||||
table.name, field.name, sql_type
|
||||
);
|
||||
match sql_query(&column_sql).execute(conn) {
|
||||
Ok(_) => {
|
||||
result.columns_added += 1;
|
||||
info!("Successfully added column {}.{}", table.name, field.name);
|
||||
}
|
||||
Err(e) => {
|
||||
let err_str = e.to_string();
|
||||
if !err_str.contains("already exists") && !err_str.contains("duplicate column")
|
||||
{
|
||||
let error_msg =
|
||||
format!("Failed to add column {}.{}: {}", table.name, field.name, e);
|
||||
error!("{}", error_msg);
|
||||
result.errors.push(error_msg);
|
||||
} else {
|
||||
info!(
|
||||
"Column {}.{} already exists, skipping",
|
||||
table.name, field.name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.tables_altered += 1;
|
||||
}
|
||||
|
||||
// Drop columns that were removed from definition (with protection)
|
||||
let mut orphaned_columns: Vec<&DbColumn> = Vec::new();
|
||||
for col in existing_columns {
|
||||
if !defined_col_names.contains(&col.name) && !PROTECTED_COLUMNS.contains(&col.name.as_str())
|
||||
{
|
||||
orphaned_columns.push(col);
|
||||
}
|
||||
}
|
||||
|
||||
if !orphaned_columns.is_empty() {
|
||||
warn!(
|
||||
"Table {} has {} orphaned columns not in definition:",
|
||||
table.name,
|
||||
orphaned_columns.len()
|
||||
);
|
||||
|
||||
for col in &orphaned_columns {
|
||||
info!("Dropping orphaned column: {}.{}", table.name, col.name);
|
||||
let drop_sql = format!(
|
||||
"ALTER TABLE {} DROP COLUMN IF EXISTS {}",
|
||||
&table_name,
|
||||
sanitize_identifier(&col.name)
|
||||
);
|
||||
|
||||
match sql_query(&drop_sql).execute(conn) {
|
||||
Ok(_) => {
|
||||
result.columns_dropped += 1;
|
||||
info!("Successfully dropped column {}.{}", table.name, col.name);
|
||||
}
|
||||
Err(e) => {
|
||||
let error_msg =
|
||||
format!("Failed to drop column {}.{}: {}", table.name, col.name, e);
|
||||
error!("{}", error_msg);
|
||||
result.errors.push(error_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if result.columns_dropped > 0 {
|
||||
result.tables_altered += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Get existing columns from a table
|
||||
pub fn get_table_columns(
|
||||
table_name: &str,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue