feat(mysql): support safe grouped result editing

This commit is contained in:
zipg authored and GitHub committed 2026-08-19 11:03:17 +08:00
1 parent 533c7a9633
commit 21af5cf600
10 files changed
+507 -36

No files matched your search

+75 -1
View File
@@ -2835,7 +2835,8 @@ fn is_postgres_tsvector_type(data_type: &str) -> bool {
pub(crate) fn is_non_identity_generated_column(column_info: Option<&DataGridColumnInfo>) -> bool {
let extra = column_info.and_then(|column| column.extra.as_deref()).unwrap_or("").to_ascii_lowercase();
extra.contains("generated always as") && !extra.contains("identity")
(extra.contains("generated always as") || extra.contains("virtual generated") || extra.contains("stored generated"))
&& !extra.contains("identity")
}
fn is_null_write_to_not_null_column(
@@ -4923,6 +4924,79 @@ mod tests {
assert!(result.rollback_statements.is_empty());
}
#[test]
fn mysql_grouped_result_update_uses_physical_columns_and_primary_key() {
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
database_type: Some(DatabaseType::Mysql),
identifier_quote: None,
table_meta: DataGridTableMeta {
catalog: None,
database: None,
schema: Some("app".to_string()),
table_name: "users".to_string(),
primary_keys: vec!["id".to_string()],
columns: Some(vec![column("id", "bigint", false, None), column("department", "varchar", false, None)]),
},
columns: vec!["用户ID".to_string(), "部门".to_string(), "订单数".to_string()],
source_columns: Some(vec![Some("id".to_string()), Some("department".to_string()), None]),
rows: vec![vec![json!(7), json!("sales"), json!(3)]],
dirty_rows: vec![(0, vec![(1, json!("support"))])],
deleted_rows: vec![],
new_rows: vec![],
});
assert_eq!(result.validation_error, None);
assert_eq!(result.statements, vec!["UPDATE `app`.`users` SET `department` = 'support' WHERE `id` = 7;"]);
assert_eq!(
result.rollback_statements,
vec!["UPDATE `app`.`users` SET `department` = 'sales' WHERE `id` = 7 AND BINARY `department` = 'support';"]
);
}
#[test]
fn mysql_update_omits_virtual_and_stored_generated_columns() {
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
database_type: Some(DatabaseType::Mysql),
identifier_quote: None,
table_meta: DataGridTableMeta {
catalog: None,
database: None,
schema: Some("app".to_string()),
table_name: "users".to_string(),
primary_keys: vec!["id".to_string()],
columns: Some(vec![
column("id", "bigint", false, None),
column("virtual_label", "varchar", true, Some("VIRTUAL GENERATED")),
column("stored_label", "varchar", true, Some("STORED GENERATED")),
column("department", "varchar", false, None),
]),
},
columns: vec![
"id".to_string(),
"virtual_label".to_string(),
"stored_label".to_string(),
"department".to_string(),
],
source_columns: Some(vec![
Some("id".to_string()),
Some("virtual_label".to_string()),
Some("stored_label".to_string()),
Some("department".to_string()),
]),
rows: vec![vec![json!(7), json!("sales-7"), json!("SALES"), json!("sales")]],
dirty_rows: vec![(0, vec![(1, json!("support-7")), (2, json!("SUPPORT")), (3, json!("support"))])],
deleted_rows: vec![],
new_rows: vec![],
});
assert_eq!(result.validation_error, None);
assert_eq!(result.statements, vec!["UPDATE `app`.`users` SET `department` = 'support' WHERE `id` = 7;"]);
assert_eq!(
result.rollback_statements,
vec!["UPDATE `app`.`users` SET `department` = 'sales' WHERE `id` = 7 AND BINARY `department` = 'support';"]
);
}
#[test]
fn kingbase_column_index_prefers_exact_case_and_rejects_ambiguous_fallback() {
let columns = vec![Some("ckg023".to_string()), Some("CKG023".to_string())];