fix(vastbase): preserve comments when copying tables

Closes #10045
This commit is contained in:
t8y2 committed 2026-09-23 01:54:11 +08:00
1 parent fc6833af60
commit 6acbcb0d2b
3 files changed
+204 -7

No files matched your search

+137 -2
View File
@@ -817,13 +817,16 @@ pub fn build_duplicate_table_structure_sql(options: DuplicateTableStructureSqlOp
));
}
}
if options.database_type == Some(DatabaseType::Dameng) {
if let Some(database_type @ (DatabaseType::Dameng | DatabaseType::Vastbase)) = options.database_type {
comment_sql.extend(options.column_comments.iter().filter_map(|column| {
if column.comment.trim().is_empty() {
return None;
}
let column_name = quote_table_identifier(options.database_type, &column.name);
Some(format!("COMMENT ON COLUMN {target}.{column_name} IS {}", quote_sql_string(&column.comment)))
Some(format!(
"COMMENT ON COLUMN {target}.{column_name} IS {}",
quote_duplicate_table_comment(database_type, &column.comment)
))
}));
}
@@ -1109,6 +1112,7 @@ fn supports_duplicate_table_comment(database_type: DatabaseType) -> bool {
| DatabaseType::Kwdb
| DatabaseType::OpenGauss
| DatabaseType::Dameng
| DatabaseType::Vastbase
)
}
@@ -2273,6 +2277,137 @@ mod tests {
);
}
#[test]
fn duplicate_table_structure_vastbase_preserves_table_and_column_comments() {
let sql = build_duplicate_table_structure_sql(DuplicateTableStructureSqlOptions {
database_type: Some(DatabaseType::Vastbase),
schema: Some("业\"务".to_string()),
source_name: "订\"单".to_string(),
target_name: "订\"单_副本".to_string(),
table_comment: Some(" 客户's;订单 ".to_string()),
column_comments: vec![
DuplicateTableColumnComment { name: "备\"注".to_string(), comment: "用户's;备注".to_string() },
DuplicateTableColumnComment {
name: "路径".to_string(), comment: "C:\\订单\n明细\t'".to_string()
},
DuplicateTableColumnComment { name: "空".to_string(), comment: String::new() },
DuplicateTableColumnComment { name: "空白".to_string(), comment: " \t\n ".to_string() },
],
primary_key_columns: vec!["编号".to_string()],
primary_key_constraint_name: Some("PK_副本".to_string()),
identifier_quote: Some("\"".to_string()),
});
let expected_statements = vec![
"CREATE TABLE \"业\"\"务\".\"订\"\"单_副本\" AS SELECT * FROM \"业\"\"务\".\"订\"\"单\" WHERE 1=0",
"COMMENT ON TABLE \"业\"\"务\".\"订\"\"单_副本\" IS ' 客户''s;订单 '",
"COMMENT ON COLUMN \"业\"\"务\".\"订\"\"单_副本\".\"备\"\"注\" IS '用户''s;备注'",
"COMMENT ON COLUMN \"业\"\"务\".\"订\"\"单_副本\".\"路径\" IS E'C:\\\\订单\\n明细\\t\\''",
];
assert_eq!(sql, format!("{};", expected_statements.join(";\n")));
assert_eq!(crate::sql::split_sql_statements_for_database(&sql, DatabaseType::Vastbase), expected_statements);
}
#[test]
fn duplicate_table_structure_vastbase_comments_are_independent_and_optional() {
for table_comment in [None, Some(""), Some(" \t\n "), Some("表注释"), Some("路径\\'\n归档")] {
for column_comment in [None, Some(""), Some(" \t\n "), Some("字段注释")] {
for schema in [None, Some("")] {
let sql = build_duplicate_table_structure_sql(DuplicateTableStructureSqlOptions {
database_type: Some(DatabaseType::Vastbase),
schema: schema.map(str::to_string),
source_name: "source".to_string(),
target_name: "copy".to_string(),
table_comment: table_comment.map(str::to_string),
column_comments: column_comment
.map(|comment| DuplicateTableColumnComment {
name: "note".to_string(),
comment: comment.to_string(),
})
.into_iter()
.collect(),
primary_key_columns: vec![],
primary_key_constraint_name: None,
identifier_quote: None,
});
let mut expected = "CREATE TABLE \"copy\" AS SELECT * FROM \"source\" WHERE 1=0;".to_string();
match table_comment {
Some("表注释") => expected.push_str("\nCOMMENT ON TABLE \"copy\" IS '表注释';"),
Some("路径\\'\n归档") => {
expected.push_str("\nCOMMENT ON TABLE \"copy\" IS E'路径\\\\\\'\\n归档';")
}
_ => {}
}
if column_comment == Some("字段注释") {
expected.push_str("\nCOMMENT ON COLUMN \"copy\".\"note\" IS '字段注释';");
}
assert_eq!(sql, expected);
}
}
}
}
#[test]
fn duplicate_table_structure_comments_keep_other_dialects_unchanged() {
for (database_type, expected) in [
(
Some(DatabaseType::Postgres),
"CREATE TABLE \"copy\" (LIKE \"source\" INCLUDING ALL);\nCOMMENT ON TABLE \"copy\" IS '表注释';",
),
(Some(DatabaseType::Mysql), "CREATE TABLE `copy` LIKE `source`;"),
(Some(DatabaseType::Highgo), "CREATE TABLE \"copy\" AS SELECT * FROM \"source\" WHERE 1=0;"),
(Some(DatabaseType::Kingbase), "CREATE TABLE \"copy\" AS SELECT * FROM \"source\" WHERE 1=0;"),
(Some(DatabaseType::DuckDb), "CREATE TABLE \"copy\" AS SELECT * FROM \"source\" WHERE 1=0;"),
(None, "CREATE TABLE \"copy\" AS SELECT * FROM \"source\" WHERE 1=0;"),
] {
assert_eq!(
build_duplicate_table_structure_sql(DuplicateTableStructureSqlOptions {
database_type,
schema: None,
source_name: "source".to_string(),
target_name: "copy".to_string(),
table_comment: Some("表注释".to_string()),
column_comments: vec![DuplicateTableColumnComment {
name: "note".to_string(),
comment: "字段注释".to_string(),
}],
primary_key_columns: vec![],
primary_key_constraint_name: None,
identifier_quote: None,
}),
expected,
"{database_type:?}"
);
}
}
#[test]
fn copy_table_data_vastbase_keeps_insert_and_target_quoting() {
for normalize_new_target_name in [false, true] {
for columns in [None, Some(vec![]), Some(vec!["编\"号".to_string(), "备注".to_string()])] {
let expected = if columns.as_ref().is_some_and(|columns| !columns.is_empty()) {
"INSERT INTO \"业\"\"务\".\"订\"\"单_副本\" (\"编\"\"号\", \"备注\") SELECT \"编\"\"号\", \"备注\" FROM \"业\"\"务\".\"订\"\"单\";"
} else {
"INSERT INTO \"业\"\"务\".\"订\"\"单_副本\" SELECT * FROM \"业\"\"务\".\"订\"\"单\";"
};
assert_eq!(
build_copy_table_data_sql(CopyTableDataSqlOptions {
database_type: Some(DatabaseType::Vastbase),
schema: Some("业\"务".to_string()),
source_name: "订\"单".to_string(),
target_name: "订\"单_副本".to_string(),
columns,
postgres_overriding_system_value: false,
sqlserver_identity_insert: false,
dameng_identity_insert: false,
normalize_new_target_name,
identifier_quote: Some("\"".to_string()),
}),
expected
);
}
}
}
#[test]
fn duplicate_table_structure_uses_boolean_false_predicate_for_pg_family_fallbacks() {
// Regression for #9950: the generic fallback used `WHERE 0`. PostgreSQL-family