diff --git a/apps/desktop/src/components/structure/TableStructureEditor.vue b/apps/desktop/src/components/structure/TableStructureEditor.vue
index 6822672595..a03dfbc140 100644
--- a/apps/desktop/src/components/structure/TableStructureEditor.vue
+++ b/apps/desktop/src/components/structure/TableStructureEditor.vue
@@ -55,6 +55,7 @@ import {
dataTypeLengthInputValue,
dataTypeLengthUnitValue,
defaultNewColumnDataType,
+ filterStructureIndexColumnOptions,
generateIndexName,
generateUniqueIndexName,
getColumnEditorControls,
@@ -2108,11 +2109,10 @@ const availableColumnNames = computed(() =>
);
const colSearch = ref("");
-const filteredColumnNames = computed(() => {
- const q = colSearch.value.toLowerCase().trim();
- if (!q) return availableColumnNames.value;
- return availableColumnNames.value.filter((c) => c.toLowerCase().includes(q));
-});
+
+function filteredIndexColumnNames(selectedColumns: readonly string[]): string[] {
+ return filterStructureIndexColumnOptions(availableColumnNames.value, selectedColumns, colSearch.value);
+}
function toggleIndexColumn(index: EditableStructureIndex, col: string) {
const previousColumns = [...index.columns];
@@ -3163,7 +3163,7 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
-
+
{{ col }}
@@ -3199,7 +3199,7 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
-
+
{{ col }}
diff --git a/apps/desktop/src/lib/table/tableStructureEditorState.ts b/apps/desktop/src/lib/table/tableStructureEditorState.ts
index 4df6cea0d0..36b348f43c 100644
--- a/apps/desktop/src/lib/table/tableStructureEditorState.ts
+++ b/apps/desktop/src/lib/table/tableStructureEditorState.ts
@@ -777,6 +777,15 @@ export function sameStructureIndexType(left: string | null | undefined, right: s
return normalizeStructureIndexType(left) === normalizeStructureIndexType(right);
}
+/** Keep selected fields removable even after they are no longer available on the table. */
+export function filterStructureIndexColumnOptions(availableColumns: readonly string[], selectedColumns: readonly string[], search = ""): string[] {
+ const availableSet = new Set(availableColumns);
+ const unavailableSelected = selectedColumns.filter((column) => column.trim() && !availableSet.has(column));
+ const options = [...new Set([...unavailableSelected, ...availableColumns])];
+ const query = search.trim().toLowerCase();
+ return query ? options.filter((column) => column.toLowerCase().includes(query)) : options;
+}
+
export function createIndexDrafts(indexes: IndexInfo[]): EditableStructureIndex[] {
return indexes.map((index) => ({
id: `existing:${index.name}`,
diff --git a/packages/app-tests/tableStructureEditorState.test.ts b/packages/app-tests/tableStructureEditorState.test.ts
index c6e2817e32..8e7983d653 100644
--- a/packages/app-tests/tableStructureEditorState.test.ts
+++ b/packages/app-tests/tableStructureEditorState.test.ts
@@ -9,6 +9,7 @@ import {
createColumnDrafts,
createIndexDrafts,
dataTypeLengthInputValue,
+ filterStructureIndexColumnOptions,
generateIndexName,
generateUniqueIndexName,
getColumnEditorControls,
@@ -404,6 +405,12 @@ test("creates editable index drafts and splits pasted column lists", () => {
assert.equal(toColumnNames(["id", "name"]), "id, name");
});
+test("keeps unavailable selected index fields removable", () => {
+ assert.deepEqual(filterStructureIndexColumnOptions(["id", "customer_id", "name"], ["platform_code"]), ["platform_code", "id", "customer_id", "name"]);
+ assert.deepEqual(filterStructureIndexColumnOptions(["id", "customer_id", "name"], ["customer_id", "platform_code"]), ["platform_code", "id", "customer_id", "name"]);
+ assert.deepEqual(filterStructureIndexColumnOptions(["id", "customer_id", "name"], ["platform_code"], "PLAT"), ["platform_code"]);
+});
+
test("normalizes Postgres lowercase index types when creating structure drafts", () => {
const postgresIndexes: IndexInfo[] = [
{