fix: sort tables by FK dependency in transfer and export

This commit is contained in:
t8y2 committed 2026-06-18 00:00:37 +08:00
1 parent 71db24813e
commit c4c427fb67
11 files changed
+292 -6

No files matched your search

+28 -1
View File
@@ -119,6 +119,15 @@ pub struct BuildDatabaseSqlExportOptions {
pub row_limit_per_table: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub insert_batch_size: Option<usize>,
/// Optional connection info for FK-aware table ordering.
/// When set, the caller should sort tables by dependency before passing them
/// to `build_database_sql_export`.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub connection_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub database: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub schema: Option<String>,
}
pub fn format_export_sql_literal(value: &Value) -> String {
@@ -404,9 +413,27 @@ pub async fn export_database_sql_core(
}
// 7. Separate tables and views
let tables: Vec<_> = all_tables.iter().filter(|t| t.table_type != "VIEW").collect();
let mut tables: Vec<_> = all_tables.iter().filter(|t| t.table_type != "VIEW").collect();
let views: Vec<_> = all_tables.iter().filter(|t| t.table_type == "VIEW").collect();
// Sort tables by foreign key dependency so referenced (parent) tables are
// exported before referencing (child) tables.
if tables.len() > 1 {
let table_names: Vec<String> = tables.iter().map(|t| t.name.clone()).collect();
if let Ok(sorted_names) = crate::transfer::sort_tables_by_fk_dependency(
state,
&request.connection_id,
&request.database,
&request.schema,
&table_names,
true,
)
.await
{
tables.sort_by_key(|t| sorted_names.iter().position(|n| n == &t.name).unwrap_or(usize::MAX));
}
}
// 8. Calculate total objects
let mut total_objects = tables.len() + views.len();