From 2b8a5c88979b270bbe1fcdc17071a2c6007e40ad Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Fri, 14 Aug 2026 13:53:03 +0000 Subject: [PATCH] fix(import): use SQL Server float for decimal inference Refs: #4072 --- .../lib/__tests__/table/tableImport.spec.ts | 15 +++++++ apps/desktop/src/lib/table/tableImport.ts | 1 + crates/dbx-core/src/table_import.rs | 44 +++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/apps/desktop/src/lib/__tests__/table/tableImport.spec.ts b/apps/desktop/src/lib/__tests__/table/tableImport.spec.ts index d2c28f76d1..0ed0ee0052 100644 --- a/apps/desktop/src/lib/__tests__/table/tableImport.spec.ts +++ b/apps/desktop/src/lib/__tests__/table/tableImport.spec.ts @@ -4,6 +4,7 @@ import { buildTableImportParseOptions, defaultTableImportEmptyStringAsNull, formatTableImportElapsed, + importDataTypeForDatabase, nextTableImportWizardStep, previousTableImportWizardStep, requiredImportTargetColumns, @@ -131,4 +132,18 @@ describe("tableImport", () => { created_at: "DATETIME", }); }); + + it("uses SQL Server FLOAT for inferred decimal columns", () => { + expect(suggestImportTargetDataTypes(["id", "active", "amount", "created_at", "notes"], [[1001, true, "12.5", "2026-07-07 08:15:00", "invoice"]], "sqlserver")).toEqual({ + id: "BIGINT", + active: "BIT", + amount: "FLOAT", + created_at: "DATETIME2", + notes: "NVARCHAR(MAX)", + }); + expect(importDataTypeForDatabase("decimal", "mysql")).toBe("DOUBLE"); + expect(importDataTypeForDatabase("decimal", "postgres")).toBe("DOUBLE PRECISION"); + expect(importDataTypeForDatabase("decimal", "sqlite")).toBe("REAL"); + expect(importDataTypeForDatabase("decimal", "oracle")).toBe("BINARY_DOUBLE"); + }); }); diff --git a/apps/desktop/src/lib/table/tableImport.ts b/apps/desktop/src/lib/table/tableImport.ts index f8a0d56e3c..42870cb709 100644 --- a/apps/desktop/src/lib/table/tableImport.ts +++ b/apps/desktop/src/lib/table/tableImport.ts @@ -243,6 +243,7 @@ export function importDataTypeForDatabase(inferredType: ImportInferredType, data return "BIGINT"; case "decimal": if (["postgres", "gaussdb", "opengauss", "redshift", "kingbase", "highgo", "uxdb", "kwdb", "vastbase"].includes(databaseType || "")) return "DOUBLE PRECISION"; + if (databaseType === "sqlserver") return "FLOAT"; if (databaseType === "sqlite" || databaseType === "rqlite" || databaseType === "turso" || databaseType === "cloudflare-d1") return "REAL"; if (databaseType === "oracle" || databaseType === "oceanbase-oracle" || databaseType === "dameng") return "BINARY_DOUBLE"; if (databaseType === "clickhouse") return "Float64"; diff --git a/crates/dbx-core/src/table_import.rs b/crates/dbx-core/src/table_import.rs index ff7eeb034b..367fe79c7a 100644 --- a/crates/dbx-core/src/table_import.rs +++ b/crates/dbx-core/src/table_import.rs @@ -3575,6 +3575,7 @@ fn decimal_data_type(db_type: &DatabaseType) -> &'static str { | DatabaseType::Uxdb | DatabaseType::Kwdb | DatabaseType::Vastbase => "DOUBLE PRECISION", + DatabaseType::SqlServer => "FLOAT", DatabaseType::Sqlite | DatabaseType::Rqlite | DatabaseType::Turso | DatabaseType::CloudflareD1 => "REAL", DatabaseType::Oracle | DatabaseType::OceanbaseOracle | DatabaseType::Dameng => "BINARY_DOUBLE", DatabaseType::ClickHouse => "Float64", @@ -8834,6 +8835,49 @@ mod tests { assert_eq!(plan.sql, "CREATE TABLE [dbo].[events] (\n [notes] NVARCHAR(MAX)\n)"); } + #[test] + fn create_table_plan_uses_sqlserver_float_for_inferred_decimals() { + let data = ParsedImportFile { + columns: vec![ + "id".to_string(), + "active".to_string(), + "amount".to_string(), + "created_at".to_string(), + "notes".to_string(), + ], + rows: vec![vec![ + serde_json::json!(1001), + serde_json::json!(true), + serde_json::json!("12.5"), + serde_json::json!("2026-07-07 08:15:00"), + serde_json::json!("invoice"), + ]], + total_rows: 1, + effective_encoding: None, + }; + let mappings = data + .columns + .iter() + .map(|column| TableImportColumnMapping { + source_column: column.clone(), + target_column: column.clone(), + target_data_type: None, + }) + .collect::>(); + + let plan = + build_import_create_table_plan(&data, &mappings, "invoices", "dbo", &DatabaseType::SqlServer).unwrap(); + + assert_eq!( + plan.sql, + "CREATE TABLE [dbo].[invoices] (\n [id] BIGINT,\n [active] BIT,\n [amount] FLOAT,\n [created_at] DATETIME2,\n [notes] NVARCHAR(MAX)\n)" + ); + assert_eq!(decimal_data_type(&DatabaseType::Mysql), "DOUBLE"); + assert_eq!(decimal_data_type(&DatabaseType::Postgres), "DOUBLE PRECISION"); + assert_eq!(decimal_data_type(&DatabaseType::Sqlite), "REAL"); + assert_eq!(decimal_data_type(&DatabaseType::Oracle), "BINARY_DOUBLE"); + } + #[test] fn create_table_plan_uses_user_defined_column_type() { let data = ParsedImportFile {