From b0a4061484bdb1272d96315a23cecf851d38534b Mon Sep 17 00:00:00 2001
From: t8y2 <1156263951@qq.com>
Date: Fri, 22 May 2026 16:43:14 +0800
Subject: [PATCH] feat(structure): support column reordering
---
.../structure/TableStructureEditorDialog.vue | 72 +++++++---
apps/desktop/src/i18n/locales/en.ts | 2 +
apps/desktop/src/i18n/locales/es.ts | 2 +
apps/desktop/src/i18n/locales/zh-CN.ts | 2 +
.../src/lib/tableStructureCapabilities.ts | 4 +
.../src/lib/tableStructureEditorSql.ts | 91 +++++++++++--
.../src/lib/tableStructureEditorState.ts | 3 +-
.../tableStructureCapabilities.test.ts | 2 +
.../tableStructureEditorPresentation.test.ts | 8 ++
.../app-tests/tableStructureEditorSql.test.ts | 107 +++++++++++++++
.../tableStructureEditorState.test.ts | 127 ++++++++++--------
11 files changed, 332 insertions(+), 88 deletions(-)
diff --git a/apps/desktop/src/components/structure/TableStructureEditorDialog.vue b/apps/desktop/src/components/structure/TableStructureEditorDialog.vue
index 8e8665f155..0c42bf8889 100644
--- a/apps/desktop/src/components/structure/TableStructureEditorDialog.vue
+++ b/apps/desktop/src/components/structure/TableStructureEditorDialog.vue
@@ -11,6 +11,7 @@ import {
AlertTriangle,
Check,
ChevronDown,
+ ChevronUp,
Database,
KeyRound,
Loader2,
@@ -224,6 +225,21 @@ function removeNewColumn(column: EditableStructureColumn) {
columns.value = columns.value.filter((item) => item.id !== column.id);
}
+function canMoveColumn(index: number, direction: -1 | 1): boolean {
+ const targetIndex = index + direction;
+ if (targetIndex < 0 || targetIndex >= columns.value.length) return false;
+ if (columns.value[index]?.markedForDrop || columns.value[targetIndex]?.markedForDrop) return false;
+ return isCreateMode.value || structureCapabilities.value.reorderColumn;
+}
+
+function moveColumn(index: number, direction: -1 | 1) {
+ if (!canMoveColumn(index, direction)) return;
+ const targetIndex = index + direction;
+ const [column] = columns.value.splice(index, 1);
+ if (!column) return;
+ columns.value.splice(targetIndex, 0, column);
+}
+
function toggleDropColumn(column: EditableStructureColumn) {
if (!canDropColumn(column)) return;
column.markedForDrop = !column.markedForDrop;
@@ -455,7 +471,7 @@ watch(
{{ t("structureEditor.comment") }}
|
-
+ |
{{ t("structureEditor.actions") }}
|
@@ -544,21 +560,45 @@ watch(
-
-
+
+
+
+
+
+
|
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts
index ac59ccab1e..ba56f4ab30 100644
--- a/apps/desktop/src/i18n/locales/en.ts
+++ b/apps/desktop/src/i18n/locales/en.ts
@@ -846,6 +846,8 @@ export default {
drop: "Drop",
restore: "Restore",
remove: "Remove",
+ moveColumnUp: "Move column up",
+ moveColumnDown: "Move column down",
yes: "Yes",
no: "No",
emptyReadonly: "No records",
diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts
index 8ebcf6b2f4..b27dbcc6b7 100644
--- a/apps/desktop/src/i18n/locales/es.ts
+++ b/apps/desktop/src/i18n/locales/es.ts
@@ -743,6 +743,8 @@ export default {
drop: "Eliminar",
restore: "Restaurar",
remove: "Quitar",
+ moveColumnUp: "Mover columna arriba",
+ moveColumnDown: "Mover columna abajo",
yes: "Sí",
no: "No",
emptyReadonly: "Sin registros",
diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts
index cdf2b01e0b..87cae4dfa1 100644
--- a/apps/desktop/src/i18n/locales/zh-CN.ts
+++ b/apps/desktop/src/i18n/locales/zh-CN.ts
@@ -827,6 +827,8 @@ export default {
drop: "删除",
restore: "恢复",
remove: "移除",
+ moveColumnUp: "上移字段",
+ moveColumnDown: "下移字段",
yes: "是",
no: "否",
emptyReadonly: "暂无记录",
diff --git a/apps/desktop/src/lib/tableStructureCapabilities.ts b/apps/desktop/src/lib/tableStructureCapabilities.ts
index c29423c0bd..c6b974f9ce 100644
--- a/apps/desktop/src/lib/tableStructureCapabilities.ts
+++ b/apps/desktop/src/lib/tableStructureCapabilities.ts
@@ -21,6 +21,7 @@ export interface TableStructureCapabilities {
alterType: boolean;
alterNullability: boolean;
alterDefault: boolean;
+ reorderColumn: boolean;
comment: boolean;
createIndex: boolean;
dropIndex: boolean;
@@ -41,6 +42,7 @@ const unsupportedCapabilities: TableStructureCapabilities = {
alterType: false,
alterNullability: false,
alterDefault: false,
+ reorderColumn: false,
comment: false,
createIndex: false,
dropIndex: false,
@@ -65,6 +67,7 @@ const mysqlCapabilities = capabilities({
alterType: true,
alterNullability: true,
alterDefault: true,
+ reorderColumn: true,
comment: true,
createIndex: true,
dropIndex: true,
@@ -182,6 +185,7 @@ const clickhouseCapabilities = capabilities({
alterType: true,
alterNullability: true,
alterDefault: true,
+ reorderColumn: true,
comment: true,
});
diff --git a/apps/desktop/src/lib/tableStructureEditorSql.ts b/apps/desktop/src/lib/tableStructureEditorSql.ts
index 1ca0be0133..71115d84e4 100644
--- a/apps/desktop/src/lib/tableStructureEditorSql.ts
+++ b/apps/desktop/src/lib/tableStructureEditorSql.ts
@@ -10,6 +10,7 @@ export interface EditableStructureColumn {
comment: string;
isPrimaryKey: boolean;
original?: ColumnInfo;
+ originalPosition?: number;
markedForDrop: boolean;
}
@@ -130,12 +131,17 @@ function hasExistingColumnAttributeChange(column: EditableStructureColumn): bool
);
}
-function buildAddColumnSql(databaseType: StructureSqlFlavor, table: string, column: EditableStructureColumn): string[] {
+function buildAddColumnSql(
+ databaseType: StructureSqlFlavor,
+ table: string,
+ column: EditableStructureColumn,
+ positionClause = "",
+): string[] {
const addKeyword = databaseType === "sqlserver" ? "ADD" : "ADD COLUMN";
const definition = columnDefinition(databaseType, column);
const statements = isOracleLike(databaseType)
? [`ALTER TABLE ${table} ADD (${definition});`]
- : [`ALTER TABLE ${table} ${addKeyword} ${definition};`];
+ : [`ALTER TABLE ${table} ${addKeyword} ${definition}${positionClause};`];
if ((databaseType === "postgres" || isOracleLike(databaseType)) && clean(column.comment)) {
statements.push(
`COMMENT ON COLUMN ${table}.${quoteIdent(databaseType, column.name)} IS ${quoteString(clean(column.comment))};`,
@@ -185,13 +191,13 @@ function buildOracleLikeExistingColumnSql(
return statements;
}
-function buildMysqlExistingColumnSql(table: string, column: EditableStructureColumn): string[] {
+function buildMysqlExistingColumnSql(table: string, column: EditableStructureColumn, positionClause = ""): string[] {
const originalName = column.original?.name ?? column.name;
const operation =
column.name === originalName
? `MODIFY COLUMN ${columnDefinition("mysql", column)}`
: `CHANGE COLUMN ${quoteIdent("mysql", originalName)} ${columnDefinition("mysql", column)}`;
- return [`ALTER TABLE ${table} ${operation};`];
+ return [`ALTER TABLE ${table} ${operation}${positionClause};`];
}
function buildPostgresExistingColumnSql(table: string, column: EditableStructureColumn): string[] {
@@ -259,7 +265,11 @@ function buildH2ExistingColumnSql(table: string, column: EditableStructureColumn
return statements;
}
-function buildClickHouseExistingColumnSql(table: string, column: EditableStructureColumn): string[] {
+function buildClickHouseExistingColumnSql(
+ table: string,
+ column: EditableStructureColumn,
+ positionClause = "",
+): string[] {
const original = column.original;
if (!original) return [];
@@ -278,20 +288,28 @@ function buildClickHouseExistingColumnSql(table: string, column: EditableStructu
const defaultValue = normalizeDefault(column.defaultValue);
if (defaultValue) {
statements.push(
- `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)} DEFAULT ${defaultValue};`,
+ `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)} DEFAULT ${defaultValue}${positionClause};`,
);
} else if (originalDefault(column)) {
statements.push(`ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} REMOVE DEFAULT;`);
if (clickHouseColumnType(column) !== original.data_type.trim()) {
statements.push(
- `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)};`,
+ `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)}${positionClause};`,
+ );
+ } else if (positionClause) {
+ statements.push(
+ `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)}${positionClause};`,
);
}
} else {
statements.push(
- `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)};`,
+ `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)}${positionClause};`,
);
}
+ } else if (positionClause) {
+ statements.push(
+ `ALTER TABLE ${table} MODIFY COLUMN ${quoteIdent("clickhouse", currentName)} ${clickHouseColumnType(column)}${positionClause};`,
+ );
}
if (clean(column.comment) !== originalComment(column)) {
statements.push(
@@ -322,6 +340,41 @@ function buildSqliteExistingColumnSql(table: string, column: EditableStructureCo
return statements;
}
+function columnPositionClause(
+ dialect: TableStructureDialect,
+ columns: EditableStructureColumn[],
+ index: number,
+): string {
+ if (dialect !== "mysql" && dialect !== "clickhouse") return "";
+ if (index <= 0) return " FIRST";
+ return ` AFTER ${quoteIdent(dialect, columns[index - 1]?.name ?? "")}`;
+}
+
+function originalPreviousColumnName(
+ columns: EditableStructureColumn[],
+ column: EditableStructureColumn,
+): string | null {
+ if (!column.original || typeof column.originalPosition !== "number") return null;
+ const originalColumns = columns
+ .filter((item) => item.original && typeof item.originalPosition === "number")
+ .sort((a, b) => (a.originalPosition ?? 0) - (b.originalPosition ?? 0));
+ const index = originalColumns.findIndex((item) => item.id === column.id);
+ if (index < 0) return null;
+ return index === 0 ? null : (originalColumns[index - 1]?.original?.name ?? null);
+}
+
+function currentPreviousOriginalColumnName(columns: EditableStructureColumn[], index: number): string | null {
+ if (index <= 0) return null;
+ const previous = columns[index - 1];
+ return previous?.original?.name ?? previous?.name ?? null;
+}
+
+function mysqlColumnPositionChanged(columns: EditableStructureColumn[], index: number): boolean {
+ const column = columns[index];
+ if (!column?.original || typeof column.originalPosition !== "number") return false;
+ return currentPreviousOriginalColumnName(columns, index) !== originalPreviousColumnName(columns, column);
+}
+
function buildColumnSql(options: BuildTableStructureChangeSqlOptions, warnings: string[]): string[] {
const databaseType = options.databaseType;
const capabilities = getTableStructureCapabilities(databaseType);
@@ -329,6 +382,8 @@ function buildColumnSql(options: BuildTableStructureChangeSqlOptions, warnings:
const table = qualifiedTable(dialect, options.schema, options.tableName);
const statements: string[] = [];
const databaseLabel = databaseType ?? "this database";
+ const activeColumns = options.columns.filter((column) => !column.markedForDrop);
+ const hasOriginalColumnPositions = activeColumns.some((column) => typeof column.originalPosition === "number");
for (const column of options.columns) {
if (column.markedForDrop) {
@@ -345,16 +400,24 @@ function buildColumnSql(options: BuildTableStructureChangeSqlOptions, warnings:
continue;
}
+ const activeIndex = activeColumns.indexOf(column);
+ const positionClause = hasOriginalColumnPositions ? columnPositionClause(dialect, activeColumns, activeIndex) : "";
+ const hasPositionChange =
+ hasOriginalColumnPositions &&
+ (dialect === "mysql" || dialect === "clickhouse") &&
+ !!column.original &&
+ mysqlColumnPositionChanged(activeColumns, activeIndex);
+
if (!column.original) {
if (!capabilities.addColumn) {
warnings.push(`Adding columns is not supported for ${databaseLabel} from this editor.`);
continue;
}
- statements.push(...buildAddColumnSql(dialect, table, column));
+ statements.push(...buildAddColumnSql(dialect, table, column, positionClause));
continue;
}
- if (!hasExistingColumnAttributeChange(column)) continue;
+ if (!hasExistingColumnAttributeChange(column) && !hasPositionChange) continue;
const original = column.original;
const hasRename = column.name !== original.name;
const hasAttributeChange =
@@ -362,6 +425,9 @@ function buildColumnSql(options: BuildTableStructureChangeSqlOptions, warnings:
column.isNullable !== original.is_nullable ||
normalizeDefault(column.defaultValue) !== originalDefault(column) ||
clean(column.comment) !== originalComment(column);
+ if (hasPositionChange && !capabilities.reorderColumn) {
+ warnings.push(`Reordering columns is not supported for ${databaseLabel} from this editor.`);
+ }
if (hasRename && !capabilities.renameColumn) {
warnings.push(`Renaming columns is not supported for ${databaseLabel} from this editor.`);
}
@@ -369,13 +435,14 @@ function buildColumnSql(options: BuildTableStructureChangeSqlOptions, warnings:
warnings.push(`Editing existing columns is not supported for ${databaseLabel} yet.`);
}
if (
+ (hasPositionChange && !capabilities.reorderColumn) ||
(hasRename && !capabilities.renameColumn) ||
(hasAttributeChange && !capabilities.alterExistingColumn && dialect !== "sqlite")
) {
continue;
}
if (dialect === "mysql") {
- statements.push(...buildMysqlExistingColumnSql(table, column));
+ statements.push(...buildMysqlExistingColumnSql(table, column, hasPositionChange ? positionClause : ""));
} else if (dialect === "postgres") {
statements.push(...buildPostgresExistingColumnSql(table, column));
} else if (dialect === "oracle") {
@@ -383,7 +450,7 @@ function buildColumnSql(options: BuildTableStructureChangeSqlOptions, warnings:
} else if (dialect === "h2") {
statements.push(...buildH2ExistingColumnSql(table, column));
} else if (dialect === "clickhouse") {
- statements.push(...buildClickHouseExistingColumnSql(table, column));
+ statements.push(...buildClickHouseExistingColumnSql(table, column, hasPositionChange ? positionClause : ""));
} else if (dialect === "sqlite") {
statements.push(...buildSqliteExistingColumnSql(table, column, warnings));
} else {
diff --git a/apps/desktop/src/lib/tableStructureEditorState.ts b/apps/desktop/src/lib/tableStructureEditorState.ts
index 717e63c8ce..011b9707dc 100644
--- a/apps/desktop/src/lib/tableStructureEditorState.ts
+++ b/apps/desktop/src/lib/tableStructureEditorState.ts
@@ -2,7 +2,7 @@ import type { ColumnInfo, IndexInfo } from "../types/database.ts";
import type { EditableStructureColumn, EditableStructureIndex } from "./tableStructureEditorSql.ts";
export function createColumnDrafts(columns: ColumnInfo[]): EditableStructureColumn[] {
- return columns.map((column) => ({
+ return columns.map((column, index) => ({
id: `existing:${column.name}`,
name: column.name,
dataType: column.data_type,
@@ -11,6 +11,7 @@ export function createColumnDrafts(columns: ColumnInfo[]): EditableStructureColu
comment: column.comment ?? "",
isPrimaryKey: column.is_primary_key,
original: column,
+ originalPosition: index,
markedForDrop: false,
}));
}
diff --git a/packages/app-tests/tableStructureCapabilities.test.ts b/packages/app-tests/tableStructureCapabilities.test.ts
index 93c20797dd..560c2caf14 100644
--- a/packages/app-tests/tableStructureCapabilities.test.ts
+++ b/packages/app-tests/tableStructureCapabilities.test.ts
@@ -31,6 +31,7 @@ test("mysql-like databases expose index rebuild and type capabilities", () => {
assert.equal(caps.dropIndex, true);
assert.equal(caps.rebuildIndex, true);
assert.equal(caps.indexType, true);
+ assert.equal(caps.reorderColumn, true);
assert.equal(canEditTableStructure(dbType), true);
}
});
@@ -79,6 +80,7 @@ test("limited analytic engines can open the editor for supported operations only
assert.equal(clickhouse.alterType, true);
assert.equal(clickhouse.alterNullability, true);
assert.equal(clickhouse.alterDefault, true);
+ assert.equal(clickhouse.reorderColumn, true);
assert.equal(clickhouse.comment, true);
assert.equal(clickhouse.createIndex, false);
assert.equal(clickhouse.rebuildIndex, false);
diff --git a/packages/app-tests/tableStructureEditorPresentation.test.ts b/packages/app-tests/tableStructureEditorPresentation.test.ts
index 419c83a615..3af2505a03 100644
--- a/packages/app-tests/tableStructureEditorPresentation.test.ts
+++ b/packages/app-tests/tableStructureEditorPresentation.test.ts
@@ -42,3 +42,11 @@ test("structure editor gates controls through table structure capabilities", ()
assert.match(source, /structureCapabilities\.value\.indexInclude/);
assert.match(source, /structureCapabilities\.value\.indexFilter/);
});
+
+test("structure editor exposes column order controls", () => {
+ assert.match(source, /function moveColumn/);
+ assert.match(source, /@click="moveColumn\(index, -1\)"/);
+ assert.match(source, /@click="moveColumn\(index, 1\)"/);
+ assert.match(source, /t\(['"]structureEditor\.moveColumnUp['"]\)/);
+ assert.match(source, /t\(['"]structureEditor\.moveColumnDown['"]\)/);
+});
diff --git a/packages/app-tests/tableStructureEditorSql.test.ts b/packages/app-tests/tableStructureEditorSql.test.ts
index 628b17655c..a70ba41594 100644
--- a/packages/app-tests/tableStructureEditorSql.test.ts
+++ b/packages/app-tests/tableStructureEditorSql.test.ts
@@ -17,6 +17,7 @@ function column(overrides: Partial): EditableStructureC
comment: overrides.comment ?? "",
isPrimaryKey: overrides.isPrimaryKey ?? false,
original: overrides.original,
+ originalPosition: overrides.originalPosition,
markedForDrop: overrides.markedForDrop ?? false,
};
}
@@ -95,6 +96,66 @@ test("builds MySQL column and index change statements", () => {
]);
});
+test("builds MySQL column reorder statements", () => {
+ const result = buildTableStructureChangeSql({
+ databaseType: "mysql",
+ tableName: "users",
+ columns: [
+ column({
+ id: "id",
+ name: "id",
+ dataType: "int",
+ isNullable: false,
+ isPrimaryKey: true,
+ originalPosition: 0,
+ original: {
+ name: "id",
+ data_type: "int",
+ is_nullable: false,
+ column_default: null,
+ is_primary_key: true,
+ extra: null,
+ },
+ }),
+ column({
+ id: "email",
+ name: "email",
+ dataType: "varchar(255)",
+ originalPosition: 2,
+ original: {
+ name: "email",
+ data_type: "varchar(255)",
+ is_nullable: true,
+ column_default: null,
+ is_primary_key: false,
+ extra: null,
+ },
+ }),
+ column({
+ id: "name",
+ name: "display_name",
+ dataType: "varchar(120)",
+ originalPosition: 1,
+ original: {
+ name: "name",
+ data_type: "varchar(80)",
+ is_nullable: true,
+ column_default: null,
+ is_primary_key: false,
+ extra: null,
+ },
+ }),
+ ],
+ indexes: [],
+ });
+
+ assert.deepEqual(result.warnings, []);
+ assert.deepEqual(result.statements, [
+ "ALTER TABLE `users` MODIFY COLUMN `email` varchar(255) AFTER `id`;",
+ "ALTER TABLE `users` CHANGE COLUMN `name` `display_name` varchar(120) AFTER `email`;",
+ ]);
+});
+
test("builds PostgreSQL rename, type, default, comment, and index statements", () => {
const result = buildTableStructureChangeSql({
databaseType: "postgres",
@@ -823,6 +884,52 @@ test("builds ClickHouse nullable and comment column changes", () => {
]);
});
+test("builds ClickHouse column reorder statements", () => {
+ const result = buildTableStructureChangeSql({
+ databaseType: "clickhouse",
+ tableName: "events",
+ columns: [
+ column({
+ id: "event_type",
+ name: "event_type",
+ dataType: "String",
+ isNullable: false,
+ originalPosition: 1,
+ original: {
+ name: "event_type",
+ data_type: "String",
+ is_nullable: false,
+ column_default: null,
+ is_primary_key: false,
+ extra: null,
+ },
+ }),
+ column({
+ id: "ts",
+ name: "ts",
+ dataType: "DateTime",
+ isNullable: false,
+ originalPosition: 0,
+ original: {
+ name: "ts",
+ data_type: "DateTime",
+ is_nullable: false,
+ column_default: null,
+ is_primary_key: false,
+ extra: null,
+ },
+ }),
+ ],
+ indexes: [],
+ });
+
+ assert.deepEqual(result.warnings, []);
+ assert.deepEqual(result.statements, [
+ 'ALTER TABLE "events" MODIFY COLUMN "event_type" String FIRST;',
+ 'ALTER TABLE "events" MODIFY COLUMN "ts" DateTime AFTER "event_type";',
+ ]);
+});
+
test("builds H2 schema-qualified existing column statements", () => {
const result = buildTableStructureChangeSql({
databaseType: "h2",
diff --git a/packages/app-tests/tableStructureEditorState.test.ts b/packages/app-tests/tableStructureEditorState.test.ts
index 5cac0133d9..c7e4da084c 100644
--- a/packages/app-tests/tableStructureEditorState.test.ts
+++ b/packages/app-tests/tableStructureEditorState.test.ts
@@ -37,70 +37,79 @@ const indexes: IndexInfo[] = [
test("creates editable column drafts from column metadata", () => {
const drafts = createColumnDrafts(columns);
- assert.deepEqual(drafts.map((draft) => ({
- id: draft.id,
- name: draft.name,
- dataType: draft.dataType,
- isNullable: draft.isNullable,
- defaultValue: draft.defaultValue,
- comment: draft.comment,
- isPrimaryKey: draft.isPrimaryKey,
- markedForDrop: draft.markedForDrop,
- originalName: draft.original?.name,
- })), [
- {
- id: "existing:id",
- name: "id",
- dataType: "bigint",
- isNullable: false,
- defaultValue: "",
- comment: "identifier",
- isPrimaryKey: true,
- markedForDrop: false,
- originalName: "id",
- },
- {
- id: "existing:name",
- name: "name",
- dataType: "varchar(120)",
- isNullable: true,
- defaultValue: "'guest'",
- comment: "",
- isPrimaryKey: false,
- markedForDrop: false,
- originalName: "name",
- },
- ]);
+ assert.deepEqual(
+ drafts.map((draft) => ({
+ id: draft.id,
+ name: draft.name,
+ dataType: draft.dataType,
+ isNullable: draft.isNullable,
+ defaultValue: draft.defaultValue,
+ comment: draft.comment,
+ isPrimaryKey: draft.isPrimaryKey,
+ originalPosition: draft.originalPosition,
+ markedForDrop: draft.markedForDrop,
+ originalName: draft.original?.name,
+ })),
+ [
+ {
+ id: "existing:id",
+ name: "id",
+ dataType: "bigint",
+ isNullable: false,
+ defaultValue: "",
+ comment: "identifier",
+ isPrimaryKey: true,
+ originalPosition: 0,
+ markedForDrop: false,
+ originalName: "id",
+ },
+ {
+ id: "existing:name",
+ name: "name",
+ dataType: "varchar(120)",
+ isNullable: true,
+ defaultValue: "'guest'",
+ comment: "",
+ isPrimaryKey: false,
+ originalPosition: 1,
+ markedForDrop: false,
+ originalName: "name",
+ },
+ ],
+ );
});
test("creates editable index drafts and splits pasted column lists", () => {
const drafts = createIndexDrafts(indexes);
- assert.deepEqual(drafts.map((draft) => ({
- id: draft.id,
- name: draft.name,
- columns: draft.columns,
- isUnique: draft.isUnique,
- isPrimary: draft.isPrimary,
- originalName: draft.original?.name,
- })), [
- {
- id: "existing:PRIMARY",
- name: "PRIMARY",
- columns: ["id"],
- isUnique: true,
- isPrimary: true,
- originalName: "PRIMARY",
- },
- {
- id: "existing:idx_name",
- name: "idx_name",
- columns: ["name"],
- isUnique: false,
- isPrimary: false,
- originalName: "idx_name",
- },
- ]);
+ assert.deepEqual(
+ drafts.map((draft) => ({
+ id: draft.id,
+ name: draft.name,
+ columns: draft.columns,
+ isUnique: draft.isUnique,
+ isPrimary: draft.isPrimary,
+ originalName: draft.original?.name,
+ })),
+ [
+ {
+ id: "existing:PRIMARY",
+ name: "PRIMARY",
+ columns: ["id"],
+ isUnique: true,
+ isPrimary: true,
+ originalName: "PRIMARY",
+ },
+ {
+ id: "existing:idx_name",
+ name: "idx_name",
+ columns: ["name"],
+ isUnique: false,
+ isPrimary: false,
+ originalName: "idx_name",
+ },
+ ],
+ );
assert.equal(toColumnNames(["id", "name"]), "id, name");
});