fix(export): append semicolons to exported DDL statements
This commit is contained in:
parent
ba71068bc8
commit
aae2cae068
|
|
@ -60,6 +60,7 @@ import { isTauriRuntime } from "@/lib/tauriRuntime";
|
|||
import { generateDatabaseExportId } from "@/lib/databaseExport";
|
||||
import { copyToClipboard } from "@/lib/clipboard";
|
||||
import { formatSqlInsert } from "@/lib/exportFormats";
|
||||
import { buildSingleDdlExportFileContent } from "@/lib/ddlExport";
|
||||
import { fetchTableDataForExport } from "@/lib/tableDataExport";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { useExportTracker, type ExportTask } from "@/composables/useExportTracker";
|
||||
|
|
@ -799,7 +800,7 @@ async function exportStructure(row: ObjectBrowserRow) {
|
|||
try {
|
||||
const schema = row.schema || selectedSchema.value || props.database;
|
||||
const ddl = await api.getTableDdl(props.connection.id, props.database, schema, row.name, tableDdlObjectType(row.type));
|
||||
await saveFileContent(ddl + "\n", `${row.name}.sql`, "SQL", "sql");
|
||||
await saveFileContent(buildSingleDdlExportFileContent(ddl), `${row.name}.sql`, "SQL", "sql");
|
||||
} catch (e: any) {
|
||||
console.error("Export structure failed:", e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ import { editableRowIdentifierColumns, usesSyntheticRowIdKey } from "@/lib/table
|
|||
import { supportsDatabaseCreation, supportsDatabaseSearch, supportsFieldLineage, supportsObjectBrowserTreeNode, supportsSchemaDiagram, supportsSqlFileExecution, supportsTableImport, supportsTableTruncate, supportsTableStructureEditing, usesTreeSchemaMode } from "@/lib/databaseCapabilities";
|
||||
import { copyNameForTreeNode, objectSourceKindForTreeNode, sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick";
|
||||
import { formatSqlInsert } from "@/lib/exportFormats";
|
||||
import { joinExportedDdls } from "@/lib/ddlExport";
|
||||
import { fetchTableDataForExport } from "@/lib/tableDataExport";
|
||||
import { buildCreateDatabaseSql, buildDuckDbAttachDatabaseSql, duckDbAttachedDatabaseNameFromPath, supportsCreateDatabaseCharset, uniqueDuckDbAttachedDatabaseName } from "@/lib/createDatabaseSql";
|
||||
import {
|
||||
|
|
@ -2592,7 +2593,7 @@ async function exportStructure() {
|
|||
const ddl = await api.getTableDdl(target.connectionId, target.database, target.schema || target.database, target.label, tableDdlObjectTypeForNode(target.type));
|
||||
parts.push(ddl.trim());
|
||||
}
|
||||
structurePreviewSql.value = `${parts.filter(Boolean).join("\n\n")}\n`;
|
||||
structurePreviewSql.value = joinExportedDdls(parts);
|
||||
} catch (e: any) {
|
||||
structurePreviewError.value = e?.message || String(e);
|
||||
console.error("Export structure failed:", e);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
export function ensureSqlStatementTerminator(sql: string): string {
|
||||
const trimmed = sql.trim();
|
||||
if (!trimmed) return "";
|
||||
return trimmed.endsWith(";") ? trimmed : `${trimmed};`;
|
||||
}
|
||||
|
||||
export function buildSingleDdlExportFileContent(sql: string): string {
|
||||
const statement = ensureSqlStatementTerminator(sql);
|
||||
return statement ? `${statement}\n` : "";
|
||||
}
|
||||
|
||||
export function joinExportedDdls(ddls: readonly string[]): string {
|
||||
const statements = ddls.map(ensureSqlStatementTerminator).filter(Boolean);
|
||||
return statements.length ? `${statements.join("\n\n")}\n` : "";
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { strict as assert } from "node:assert";
|
||||
import { test } from "vitest";
|
||||
import { buildSingleDdlExportFileContent, ensureSqlStatementTerminator, joinExportedDdls } from "../../apps/desktop/src/lib/ddlExport.ts";
|
||||
|
||||
test("ensureSqlStatementTerminator appends a trailing semicolon when missing", () => {
|
||||
assert.equal(ensureSqlStatementTerminator("CREATE TABLE `users` (\n `id` int\n) ENGINE=InnoDB"), "CREATE TABLE `users` (\n `id` int\n) ENGINE=InnoDB;");
|
||||
});
|
||||
|
||||
test("ensureSqlStatementTerminator does not duplicate an existing trailing semicolon", () => {
|
||||
assert.equal(ensureSqlStatementTerminator("CREATE VIEW v AS SELECT 1;"), "CREATE VIEW v AS SELECT 1;");
|
||||
});
|
||||
|
||||
test("joinExportedDdls separates exported objects with blank lines and terminates each statement", () => {
|
||||
assert.equal(
|
||||
joinExportedDdls([
|
||||
"CREATE TABLE `users` (`id` int)",
|
||||
"CREATE TABLE `posts` (`id` int);",
|
||||
]),
|
||||
"CREATE TABLE `users` (`id` int);\n\nCREATE TABLE `posts` (`id` int);\n",
|
||||
);
|
||||
});
|
||||
|
||||
test("buildSingleDdlExportFileContent emits a single importable statement with one trailing newline", () => {
|
||||
assert.equal(
|
||||
buildSingleDdlExportFileContent(" CREATE TABLE `users` (`id` int) "),
|
||||
"CREATE TABLE `users` (`id` int);\n",
|
||||
);
|
||||
});
|
||||
Loading…
Reference in New Issue