From 73bd133886bf45ea2ab1ae7bb2b08403174dcfe2 Mon Sep 17 00:00:00 2001 From: gggaiitx <62124152+gggaiitx@users.noreply.github.com> Date: Wed, 8 Jul 2026 15:31:49 +0800 Subject: [PATCH] fix(sqlserver): strip display width from float type in DDL generation * fix(sqlserver): strip scale from float type while preserving mantissa bits * fix: add missing agent_java_options field in test ConnectionConfig --- .../src/table_structure_sql/column_format.rs | 13 ++++++ .../dbx-core/src/table_structure_sql/tests.rs | 44 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/crates/dbx-core/src/table_structure_sql/column_format.rs b/crates/dbx-core/src/table_structure_sql/column_format.rs index 13bb78570..5a677548d 100644 --- a/crates/dbx-core/src/table_structure_sql/column_format.rs +++ b/crates/dbx-core/src/table_structure_sql/column_format.rs @@ -148,6 +148,12 @@ pub(super) fn normalize_column_data_type(dialect: StructureDialect, data_type: & return base_type.to_string(); } + if dialect == StructureDialect::SqlServer && is_sqlserver_float_with_scale(base_type, params) { + // SQL Server float only accepts a single integer mantissa bit count (1–53), + // not comma-separated precision/scale like float(10,2). + return base_type.to_string(); + } + if is_temporal_precision_type(dialect, base_type) { return if is_valid_temporal_precision(params, dialect) { format!("{base_type}({params})") @@ -211,6 +217,13 @@ fn is_sqlserver_lengthless_type(base_type: &str) -> bool { ) } +/// SQL Server `float` accepts a single integer mantissa bit count (1–53) +/// but rejects comma-separated precision/scale like `float(10,2)`. +fn is_sqlserver_float_with_scale(base_type: &str, params: &str) -> bool { + let normalized = base_type.split_whitespace().collect::>().join(" ").to_ascii_lowercase(); + normalized == "float" && params.contains(',') +} + fn normalize_mysql_numeric_attribute_type(base_type: &str, params: &str) -> Option { let mut parts: Vec<&str> = base_type.split_whitespace().collect(); let type_name = parts.first().copied()?.to_ascii_lowercase(); diff --git a/crates/dbx-core/src/table_structure_sql/tests.rs b/crates/dbx-core/src/table_structure_sql/tests.rs index ad8c2e113..4b3f6ae2b 100644 --- a/crates/dbx-core/src/table_structure_sql/tests.rs +++ b/crates/dbx-core/src/table_structure_sql/tests.rs @@ -1291,6 +1291,50 @@ fn sqlserver_strips_mysql_display_width_from_fixed_integer_types() { assert_eq!(result.statements, vec!["ALTER TABLE [dbo].[users] ADD [id] int NOT NULL;"]); } +#[test] +fn sqlserver_strips_scale_from_float() { + let mut amount = column("amount"); + amount.data_type = "float(10,2)".to_string(); + amount.is_nullable = true; + + let result = build_table_structure_change_sql(TableStructureSqlOptions { + database_type: Some(DatabaseType::SqlServer), + schema: Some("dbo".to_string()), + table_name: "orders".to_string(), + columns: vec![amount], + indexes: Vec::new(), + foreign_keys: Vec::new(), + triggers: Vec::new(), + table_comment: None, + original_table_comment: None, + }); + + assert_eq!(result.warnings, Vec::::new()); + assert_eq!(result.statements, vec!["ALTER TABLE [dbo].[orders] ADD [amount] float;"]); +} + +#[test] +fn sqlserver_preserves_float_mantissa_bits() { + let mut value = column("value"); + value.data_type = "float(53)".to_string(); + value.is_nullable = false; + + let result = build_table_structure_change_sql(TableStructureSqlOptions { + database_type: Some(DatabaseType::SqlServer), + schema: Some("dbo".to_string()), + table_name: "measurements".to_string(), + columns: vec![value], + indexes: Vec::new(), + foreign_keys: Vec::new(), + triggers: Vec::new(), + table_comment: None, + original_table_comment: None, + }); + + assert_eq!(result.warnings, Vec::::new()); + assert_eq!(result.statements, vec!["ALTER TABLE [dbo].[measurements] ADD [value] float(53) NOT NULL;"]); +} + #[test] fn sqlserver_default_changes_drop_old_constraints_with_isolated_batches() { let mut sku = column("sku");