diff --git a/docs/issues/2026-04-11-issue-backlog-tracking.md b/docs/issues/2026-04-11-issue-backlog-tracking.md index b299b23..50a2be9 100644 --- a/docs/issues/2026-04-11-issue-backlog-tracking.md +++ b/docs/issues/2026-04-11-issue-backlog-tracking.md @@ -41,6 +41,7 @@ | #363 | [Bug] 日期字段无法设置值 | Fixed | Pending | | #368 | [Bug] 窗口状态问题 | Fixed | Pending | | #369 | [Bug] AI回复Sql语句时 md 没有正常渲染 | Fixed | Pending | +| #373 | [Bug] 修改表列名时报错 | Fixed | Pending | | #351 | 为什么没有截断和清空表的功能呀? | Fixed | Pending | ## Notes @@ -165,6 +166,12 @@ - 处理:新增 `aiMarkdown` 预处理 helper,在渲染前补齐 opening fence 后缺失的换行,并为 closing fence 缺少前置换行的场景补齐收尾;`AIMessageBubble` 统一使用规范化后的内容喂给 `react-markdown`,恢复 SQL/代码块的正常渲染。 - 验证:新增 `frontend/src/utils/aiMarkdown.test.ts`,覆盖 ` ```sqlSELECT ...` 自动归一化为 ` ```sql\\nSELECT ...` 的坏样例,并执行 `frontend` 下 `npm exec vitest run src/utils/aiMarkdown.test.ts` 与 `npm run build`。 +### #373 + +- 根因:表设计器的 MySQL alter preview 逻辑把“列名变化”和“列定义变化”混在同一个 `MODIFY COLUMN` 分支里处理。MySQL/MariaDB 在重命名列时必须使用 `CHANGE COLUMN old_name new_name definition`,直接生成 `MODIFY COLUMN new_name ...` 会在实际执行时报错。 +- 处理:将 MySQL 分支拆分为 rename 与 redefine 两条路径。列名发生变化时使用 `CHANGE COLUMN 原列名 新列定义`,其余类型/默认值/注释/自增等普通变更继续走 `MODIFY COLUMN`,保留原有位置子句(`FIRST` / `AFTER`)。 +- 验证:补充 `frontend/src/components/tableDesignerSchemaSql.test.ts` 回归测试,覆盖 MySQL 重命名列时必须生成 `CHANGE COLUMN` 而不是 `MODIFY COLUMN`,并执行 `frontend` 下 `npm exec vitest run src/components/tableDesignerSchemaSql.test.ts` 与 `npm run build`。 + ### #330 - 根因:查询结果表格已经支持拖拽调整列宽,但 resize handle 没有提供双击自适应逻辑,导致用户只能靠手工拖拽慢慢试宽度。 diff --git a/frontend/src/components/tableDesignerSchemaSql.test.ts b/frontend/src/components/tableDesignerSchemaSql.test.ts index c991f1f..e45c380 100644 --- a/frontend/src/components/tableDesignerSchemaSql.test.ts +++ b/frontend/src/components/tableDesignerSchemaSql.test.ts @@ -51,4 +51,16 @@ describe('tableDesignerSchemaSql', () => { expect(sql).not.toContain('AFTER'); expect(sql).not.toContain(' FIRST'); }); + + it('uses mysql change column syntax when renaming a column', () => { + const sql = buildAlterTablePreviewSql(buildInput({ + dbType: 'mysql', + originalColumns: [baseColumn({ _key: 'name', name: 'name', type: 'varchar(64)', nullable: 'YES' })], + columns: [baseColumn({ _key: 'name', name: 'display_name', type: 'varchar(64)', nullable: 'YES' })], + })); + + expect(sql).toContain('CHANGE COLUMN `name` `display_name` varchar(64) NULL'); + expect(sql).toContain('FIRST'); + expect(sql).not.toContain('MODIFY COLUMN `display_name`'); + }); }); diff --git a/frontend/src/components/tableDesignerSchemaSql.ts b/frontend/src/components/tableDesignerSchemaSql.ts index c807e6c..82ff9f5 100644 --- a/frontend/src/components/tableDesignerSchemaSql.ts +++ b/frontend/src/components/tableDesignerSchemaSql.ts @@ -140,14 +140,21 @@ const buildMySqlAlterPreviewSql = (input: BuildAlterTablePreviewInput): string = return; } - if ( - curr.name !== orig.name || + const definitionChanged = curr.type !== orig.type || curr.nullable !== orig.nullable || curr.default !== orig.default || (curr.comment || '') !== (orig.comment || '') || - Boolean(curr.isAutoIncrement) !== Boolean(orig.isAutoIncrement) - ) { + Boolean(curr.isAutoIncrement) !== Boolean(orig.isAutoIncrement); + + if (curr.name !== orig.name) { + alters.push( + `CHANGE COLUMN ${quoteIdentifierPart(orig.name, 'mysql')} ${colDef} ${positionSql}`.trim(), + ); + return; + } + + if (definitionChanged) { alters.push(`MODIFY COLUMN ${colDef} ${positionSql}`.trim()); } });