feat(export): add SQL INSERT batch or single-row mode

This commit is contained in:
jearhe authored and GitHub committed 2026-09-06 10:27:34 +08:00
1 parent 5d65be03a3
commit ab35a5b1da
29 files changed
+563 -23

No files matched your search

@@ -92,6 +92,7 @@ import { buildRenameObjectSql, supportsObjectRename } from "@/lib/table/objectRe
import { isTauriRuntime } from "@/lib/backend/tauriRuntime";
import { generateDatabaseExportId } from "@/lib/export/databaseExport";
import { buildXlsxHeaderOverrides, hasXlsxHeaderComments, type XlsxExportOptions, type XlsxHeaderMode } from "@/lib/export/xlsxHeader";
import { showSqlInsertModeDialog, type SqlInsertMode } from "@/lib/export/sqlInsertMode";
import { copyToClipboard, eventTargetAllowsAppClipboardShortcut } from "@/lib/common/clipboard";
import {
defaultPasteTableMode,
@@ -2097,8 +2098,13 @@ async function exportDataLegacy(row: ObjectBrowserRow, format: "json") {
}
async function exportData(row: ObjectBrowserRow, format: "csv" | "json" | "sql") {
if (format === "json") await exportDataLegacy(row, format);
else await exportTableData(row, format);
if (format === "json") {
await exportDataLegacy(row, format);
return;
}
const insertMode = format === "sql" ? await showSqlInsertModeDialog() : undefined;
if (format === "sql" && insertMode === null) return;
await exportTableData(row, format, undefined, "name", true, insertMode ?? "batch");
}
function showObjectBrowserXlsxHeaderDialog(hasComments: boolean): Promise<XlsxExportOptions | null> {
@@ -2141,7 +2147,7 @@ async function exportDataXlsx(row: ObjectBrowserRow) {
await exportTableData(row, "xlsx", columnInfos, exportOptions.headerMode, exportOptions.autoFilter);
}
async function exportTableData(row: ObjectBrowserRow, format: "csv" | "xlsx" | "sql", columnInfos?: ColumnInfo[], headerMode: XlsxHeaderMode = "name", autoFilter = true) {
async function exportTableData(row: ObjectBrowserRow, format: "csv" | "xlsx" | "sql", columnInfos?: ColumnInfo[], headerMode: XlsxHeaderMode = "name", autoFilter = true, insertMode: SqlInsertMode = "batch") {
const schema = row.schema || selectedSchema.value;
// Save dialog first
@@ -2215,6 +2221,7 @@ async function exportTableData(row: ObjectBrowserRow, format: "csv" | "xlsx" | "
tableName: row.name,
filePath,
format,
...(format === "sql" ? { insertMode } : {}),
csvQuoteMode: settingsStore.editorSettings.csvQuoteMode,
columns,
columnComments: format === "xlsx" ? columnComments : undefined,
@@ -26,6 +26,15 @@ describe("ObjectBrowser XLSX export", () => {
expect(exportDataXlsx.indexOf("await showObjectBrowserXlsxHeaderDialog(")).toBeLessThan(exportDataXlsx.indexOf('await exportTableData(row, "xlsx", columnInfos, exportOptions.headerMode, exportOptions.autoFilter)'));
});
it("asks for the SQL INSERT mode before opening the save dialog", () => {
const exportData = functionBody("exportData");
const exportTableData = functionBody("exportTableData");
expect(exportData).toContain("await showSqlInsertModeDialog()");
expect(exportData.indexOf("await showSqlInsertModeDialog()")).toBeLessThan(exportData.indexOf("await exportTableData("));
expect(exportTableData).toContain('...(format === "sql" ? { insertMode } : {})');
});
it("falls back to field-name headers when column metadata is unavailable", () => {
const exportDataXlsx = functionBody("exportDataXlsx");