fix(sqlserver): complete schema diff DDL support - #7168
Conversation
t8y2
left a comment
There was a problem hiding this comment.
request changes: SQL Server column dependency handling is still incomplete, and PostgreSQL defaults with parameterized casts are currently corrupted.
-
crates/dbx-core/src/schema_diff.rs:2236discards unchanged indexes and foreign keys, while the SQL generation around line 4615 only drops indexes reported as removed or modified. A type or nullability change on a column with an unchanged dependent index therefore emitsALTER COLUMNwithout dropping the dependency. Primary keys, CHECK constraints, and inbound foreign keys are also not fully represented.SQL Server documents that
ALTER COLUMNfails when indexes, statistics, or constraints depend on the column: https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sqlPlease make column changes dependency-aware: drop every affected index/key/CHECK/FK, including inbound FKs, then recreate the exact original object types. Add live regressions for an unchanged nonclustered index, primary key, CHECK constraint, and inbound foreign key.
-
crates/dbx-core/src/schema_diff.rs:3566stops consuming a PostgreSQL cast type at(. For example,'0.00'::numeric(10,2)becomes'0.00'(10,2), producing invalid T-SQL.Please consume balanced type modifiers, array suffixes, and schema-qualified type names, with regressions for
numeric(10,2)andcharacter varying(20).
Snapshot and restore live SQL Server indexes, keys, checks, statistics, and foreign keys around ALTER COLUMN. Parse complete PostgreSQL cast types when translating defaults and add unit plus live regressions.
|
@t8y2 感谢 review。关于 SQL Server 为什么需要这样处理现有 schema diff 主要描述“发生变化”的索引和外键。目标库中未发生变化、但依赖被修改列的对象不会出现在 diff 中;CHECK、入站外键和独立统计信息也无法仅靠当前 diff 数据完整获取。 因此,如果生成 SQL 时直接执行
当前提交 之所以不能只处理 diff 中的对象,是因为这些阻塞对象可能完全没有变化,只有运行时查询目标库目录才能发现。 本地 SQL Server 负向测试环境:SQL Server LocalDB 跳过“保存定义 → 删除依赖 → 修改列 → 恢复依赖”,直接执行裸
同时复刻了回归测试中的组合依赖:
使用当前依赖感知流程后,LocalDB 回归可以成功修改列,并验证普通索引、PK、UQ、CHECK、出站 FK 和入站 FK 均已按原属性恢复。 实现取舍,希望听取您的意见本地测试也确认并非每种操作都必须删除依赖,例如:
所以当前实现是偏保守的统一方案:只要发生类型或可空性变化,就保存并重建相关依赖,以优先保证所有阻塞场景正确;代价是代码和生成 SQL 的复杂度较高,少数 SQL Server 原本允许直接修改的场景也会发生依赖重建。 这部分改动确实比较大,想请您确认一下设计方向:您更倾向于保留当前这种统一兜底、以正确性为先的实现,还是希望进一步缩小范围,只针对确认会阻塞的修改类型和依赖组合进行处理?我可以根据您的意见继续调整。 |
t8y2
left a comment
There was a problem hiding this comment.
Pushed a small follow-up patch on top at 409903c.
The narrowed conditional-table prefix check in wrap_conditional_check dropped SQLite CREATE TEMP TABLE from IF NOT EXISTS wrapping, and PostgreSQL GLOBAL/LOCAL TEMPORARY/UNLOGGED forms lost the DO-block idempotent wrapper. The patch restores coverage for all CREATE TABLE variants via a shared create_table_variant_prefix helper (fail-open when the keyword cannot be located), with regression tests for both dialects.
One known follow-up stays open and does not block this PR: a diff-"modified" UNIQUE-constraint backing index is still recreated as a plain CREATE UNIQUE INDEX. The drop side correctly resolves ALTER TABLE ... DROP CONSTRAINT at runtime, but the create side cannot know constraint-ness at generation time. Impact is metadata fidelity only — uniqueness and FK referenceability are preserved (CREATE TABLE (Transact-SQL)). A proper fix needs constraint-ness threaded into the index metadata snapshot; tracked for a separate change.
Checks run: cargo test -p dbx-core --no-default-features --lib script_generator (63 passed, including the two new regressions).
t8y2
left a comment
There was a problem hiding this comment.
Resolved the conflict with main at bb9f74d (old head 409903c, base c8c9870).
Cause: both this branch and the freshly landed schema-sync change edited crates/dbx-core/src/schema_diff.rs; the only textual conflict was the ddl_profile import list — resolved to the union (main's expanded import). Everything else auto-merged.
Behavior preservation: the main-side column_def auto-increment gating (MySQL-family only) and this branch's dedicated sqlserver_column_definition coexist — the SQL Server path emits IDENTITY(1,1) directly after the type with correct T-SQL clause order. The regression test from main was updated to assert that order ([seq] INT IDENTITY(1,1) NOT NULL) instead of absence, which matches both sides' intent.
Checks run: cargo test -p dbx-core --no-default-features --lib schema_diff:: (228 passed) and script_generator (63 passed) on the resolved head; git diff --check clean, no conflict markers.
bb9f74d to
1e2caf1
Compare
|
Thanks for the contribution! Merged in a4bf844, will be released in the next version. |
目前此功能在sqlserver上已基本可用,我会持续跟进sqlserver diff DDL |
变更说明
ALTER COLUMN前正确处理默认约束,保留已有约束名称和表达式,并生成可逆的回滚 SQL;同时包含invert_change_string的回滚修复UPDATE、不存在时执行ADD,删除注释时按存在性执行DROPDATETIME2/DATETIMEOFFSET当前时间精度、UnicodeN'...'字面量和方括号标识符转义本 PR 基于
6cf8d8e,补全在验证 #7051 修复过程中发现的其余 SQL Server 架构比较场景。Refs #7051
修复前后
此前 SQL Server 目标库仍可能收到不支持的语法,例如
ADD COLUMN、ALTER COLUMN ... SET DEFAULT、COMMENT ON或CREATE INDEX IF NOT EXISTS;部分列变更还会被已有默认约束阻止。现在生成的 SQL 全部使用 SQL Server 原生语法和系统目录检查,包括:
ALTER TABLE ... ADD,以及包含完整类型和NULL|NOT NULL的ALTER COLUMNsys.default_constraints查找默认约束,并按删除、保留、重建的正确顺序执行sys.extended_properties以及sp_updateextendedproperty、sp_addextendedproperty、sp_dropextendedproperty管理注释OBJECT_ID和sys.indexes条件检查,避免生成 SQL Server 不支持的CREATE INDEX IF NOT EXISTSsp_rename、NEXT VALUE FOR以及 SQL Server 专用的函数、序列、触发器和外键语法本次改动仅涉及
dbx-core,没有 UI 或前端变更,因此不需要截图。验证结果
cargo +1.97.1 test -p dbx-core --locked --no-default-features --lib:5,267 passed,55 ignoredcargo +1.97.1 test -p dbx-core --locked --no-default-features --lib sqlserver:304 passed,4 ignored;已在 rebase 到最终main后重新执行cargo +1.97.1 clippy -p dbx-core --locked --no-default-features --all-targets -- -D warningscargo +1.97.1 fmt -p dbx-core --checkgit diff --check真实 SQL Server 执行验证
使用
sqlcmd连接 SQL Server LocalDB17.0.4025.3(Express Edition 64-bit)完成验证。测试对象创建在tempdb的事务内,执行结束后全部回滚。真实执行覆盖:
SYSDATETIME()和SYSDATETIMEOFFSET()默认值]、空格和单引号的标识符执行结果为
PASS,并确认事务回滚后测试 schema 不存在。4 个被忽略的 SQL Server 驱动测试要求配置
DBX_LIVE_SQLSERVER_HOST/PORT/USER/PASSWORD;LocalDB 提供的是本地命名管道,而不是该测试要求的 TCP 连接。这些测试针对空间类型和驱动集成,本 PR 涉及的 DDL 已由真实 SQL Server 引擎直接执行验证。Microsoft 文档依据