diff --git a/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts b/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts
index 2a235cf1d4..515e0d01e8 100644
--- a/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts
+++ b/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts
@@ -37,6 +37,7 @@ vi.mock("@lucide/vue", async () => {
Check: Icon,
ChevronDown: Icon,
ChevronUp: Icon,
+ ClipboardList: Icon,
Copy: Icon,
Database: Icon,
Info: Icon,
diff --git a/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts b/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts
index 4ee08eabac..9e67d77c2e 100644
--- a/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts
+++ b/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts
@@ -44,6 +44,7 @@ vi.mock("@lucide/vue", async () => {
Check: Icon,
ChevronDown: Icon,
ChevronUp: Icon,
+ ClipboardList: Icon,
Copy: Icon,
Database: Icon,
Info: Icon,
diff --git a/apps/desktop/src/components/structure/TableStructureEditor.vue b/apps/desktop/src/components/structure/TableStructureEditor.vue
index 902e602040..7ac344cb3d 100644
--- a/apps/desktop/src/components/structure/TableStructureEditor.vue
+++ b/apps/desktop/src/components/structure/TableStructureEditor.vue
@@ -10,7 +10,7 @@ import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
-import { AlertTriangle, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Copy, Database, Info, KeyRound, ListChevronsUpDown, Loader2, Maximize2, Pencil, Plus, RefreshCw, RotateCcw, Save, Search, Settings, SlidersHorizontal, Trash2, UserRound, X } from "@lucide/vue";
+import { AlertTriangle, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ClipboardList, Copy, Database, Info, KeyRound, ListChevronsUpDown, Loader2, Maximize2, Pencil, Plus, RefreshCw, RotateCcw, Save, Search, Settings, SlidersHorizontal, Trash2, UserRound, X } from "@lucide/vue";
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
@@ -34,6 +34,7 @@ import { joinSqlStatementsForScript } from "@/lib/sql/sqlBatchScript";
import { formatGeneratedDdlIdentifierQuotes, omitDdlDatabaseQualifier, omitDdlIdentifierQuotes } from "@/lib/sql/ddlDisplay";
import { splitSqlStatementRanges } from "@/lib/sql/sqlStatementRanges";
import { copyToClipboard } from "@/lib/common/clipboard";
+import DataGridCopyColumnNamesDialog from "@/components/grid/DataGridCopyColumnNamesDialog.vue";
import { formatSqlForDisplay, sqlFormatDialectForDbType, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
import { queryTimeoutSecsForConcurrentIndex, queryTimeoutSecsForConnection } from "@/lib/sql/queryTimeout";
import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/backend/safeStorage";
@@ -104,6 +105,8 @@ import {
structureColumnSelectionRange,
isSyntheticContextMenuClick,
resolveColumnSelectionActiveId,
+ structureColumnCommentsForCopy,
+ structureColumnNamesForCopy,
tableStructureIdentifierComparisonKey,
toColumnNames,
} from "@/lib/table/tableStructureEditorState";
@@ -3706,6 +3709,20 @@ async function recordStructureHistory(sql: string, start: number, success: boole
}
}
+const copyColumnNamesDialogOpen = ref(false);
+// Fields marked for drop no longer exist after saving, so they are excluded.
+const copyableStructureColumnNames = computed(() => structureColumnNamesForCopy(columns.value));
+const copyableStructureColumnComments = computed(() => structureColumnCommentsForCopy(columns.value));
+
+async function copyColumnNamesText(text: string) {
+ try {
+ await copyToClipboard(text);
+ toast(t("grid.copied"));
+ } catch (e: any) {
+ toast(t("grid.copyFailed", { message: e?.message || String(e) }), 5000);
+ }
+}
+
async function copyPreviewSql() {
if (sqlPreviewPending.value || sqlPreviewLoading.value || !previewSqlText.value.trim()) return;
try {
@@ -4438,6 +4455,10 @@ watch(
{{ t("structureEditor.copyColumns") }}
+
+