fix: handle MySQL backup SQL import

This commit is contained in:
t8y2
2026-05-16 12:13:40 +08:00
parent e9621ef06a
commit f4c7c1d764
10 changed files with 371 additions and 10 deletions
+38 -1
View File
@@ -88,6 +88,7 @@ import {
} from "@/lib/databaseCapabilities";
import { sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick";
import { formatCsv, formatJson, formatSqlInsert } from "@/lib/exportFormats";
import { buildCreateDatabaseSql, supportsCreateDatabaseCharset } from "@/lib/createDatabaseSql";
import { hexToRgba } from "@/lib/color";
import DangerConfirmDialog from "@/components/editor/DangerConfirmDialog.vue";
import { isTauriRuntime } from "@/lib/tauriRuntime";
@@ -604,6 +605,8 @@ const duplicateTableName = ref("");
const showCreateDatabaseDialog = ref(false);
const createDatabaseName = ref("");
const createDatabaseCharset = ref("utf8mb4");
const createDatabaseCollation = ref("utf8mb4_unicode_ci");
const showDropDatabaseConfirm = ref(false);
const showCreateSchemaDialog = ref(false);
const createSchemaName = ref("");
@@ -682,6 +685,11 @@ const canCreateDatabase = computed(() => {
return props.node.type === "connection" && supportsDatabaseCreation(config?.db_type);
});
const canSetCreateDatabaseCharset = computed(() => {
const config = props.node.connectionId ? connectionStore.getConfig(props.node.connectionId) : undefined;
return supportsCreateDatabaseCharset(config?.db_type, config?.driver_profile);
});
const canDropDatabase = computed(() => {
const config = props.node.connectionId ? connectionStore.getConfig(props.node.connectionId) : undefined;
return props.node.type === "database" && supportsDatabaseCreation(config?.db_type);
@@ -786,6 +794,8 @@ function buildDropSchemaSql(): string {
function openCreateDatabaseDialog() {
createDatabaseName.value = "";
createDatabaseCharset.value = "utf8mb4";
createDatabaseCollation.value = "utf8mb4_unicode_ci";
showCreateDatabaseDialog.value = true;
}
@@ -796,7 +806,14 @@ async function confirmCreateDatabase() {
showCreateDatabaseDialog.value = false;
try {
await connectionStore.ensureConnected(node.connectionId);
const sql = `CREATE DATABASE ${quoteIdent(name)};`;
const config = connectionStore.getConfig(node.connectionId);
const sql = buildCreateDatabaseSql({
databaseType: config?.db_type,
driverProfile: config?.driver_profile,
name,
charset: createDatabaseCharset.value,
collation: createDatabaseCollation.value,
});
await api.executeQuery(node.connectionId, "", sql);
toast(t("contextMenu.createDatabaseSuccess", { name }), 3000);
await connectionStore.loadDatabases(node.connectionId, { force: true });
@@ -2037,6 +2054,26 @@ const isDragging = computed(() => dragState.active && dragState.draggedId === pr
:placeholder="t('contextMenu.createDatabaseNamePlaceholder')"
@keydown.enter.prevent="confirmCreateDatabase"
/>
<div v-if="canSetCreateDatabaseCharset" class="grid gap-2">
<div class="grid gap-1.5">
<label class="text-xs font-medium text-muted-foreground">{{ t("contextMenu.createDatabaseCharset") }}</label>
<Input
v-model="createDatabaseCharset"
:placeholder="t('contextMenu.createDatabaseCharsetPlaceholder')"
@keydown.enter.prevent="confirmCreateDatabase"
/>
</div>
<div class="grid gap-1.5">
<label class="text-xs font-medium text-muted-foreground">{{
t("contextMenu.createDatabaseCollation")
}}</label>
<Input
v-model="createDatabaseCollation"
:placeholder="t('contextMenu.createDatabaseCollationPlaceholder')"
@keydown.enter.prevent="confirmCreateDatabase"
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" @click="showCreateDatabaseDialog = false">{{ t("dangerDialog.cancel") }}</Button>
<Button :disabled="!createDatabaseName.trim()" @click="confirmCreateDatabase">{{
+4
View File
@@ -660,6 +660,10 @@ export default {
createDatabaseSuccess: 'Database "{name}" created',
dropDatabaseSuccess: 'Database "{name}" dropped',
createDatabaseNamePlaceholder: "Database name",
createDatabaseCharset: "Character set",
createDatabaseCharsetPlaceholder: "e.g. utf8mb4",
createDatabaseCollation: "Collation",
createDatabaseCollationPlaceholder: "e.g. utf8mb4_unicode_ci",
createSchema: "Create Schema",
dropSchema: "Drop Schema",
confirmDropSchemaTitle: "Drop Schema",
+4
View File
@@ -643,6 +643,10 @@ export default {
createDatabaseSuccess: "数据库「{name}」已创建",
dropDatabaseSuccess: "数据库「{name}」已删除",
createDatabaseNamePlaceholder: "数据库名称",
createDatabaseCharset: "字符集",
createDatabaseCharsetPlaceholder: "例如 utf8mb4",
createDatabaseCollation: "排序规则",
createDatabaseCollationPlaceholder: "例如 utf8mb4_unicode_ci",
createSchema: "新建 Schema",
dropSchema: "删除 Schema",
confirmDropSchemaTitle: "删除 Schema",
+43
View File
@@ -0,0 +1,43 @@
import type { DatabaseType } from "@/types/database";
import { quoteTableIdentifier } from "./tableSelectSql";
const MYSQL_COMPATIBLE_PROFILES = new Set([
"mysql",
"mariadb",
"tidb",
"oceanbase",
"doris",
"starrocks",
"custom_mysql",
]);
const MYSQL_COMPATIBLE_TYPES = new Set<DatabaseType>(["mysql", "doris", "starrocks", "goldendb"]);
export interface CreateDatabaseSqlOptions {
databaseType?: DatabaseType;
driverProfile?: string | null;
name: string;
charset?: string;
collation?: string;
}
export function supportsCreateDatabaseCharset(databaseType?: DatabaseType, driverProfile?: string | null): boolean {
return (
MYSQL_COMPATIBLE_TYPES.has(databaseType as DatabaseType) ||
(!!driverProfile && MYSQL_COMPATIBLE_PROFILES.has(driverProfile))
);
}
export function buildCreateDatabaseSql(options: CreateDatabaseSqlOptions): string {
const name = quoteTableIdentifier(options.databaseType, options.name);
const charset = cleanSqlOption(options.charset);
const collation = cleanSqlOption(options.collation);
if (!supportsCreateDatabaseCharset(options.databaseType, options.driverProfile) || !charset) {
return `CREATE DATABASE ${name};`;
}
const collateClause = collation ? ` COLLATE ${collation}` : "";
return `CREATE DATABASE ${name} CHARACTER SET ${charset}${collateClause};`;
}
function cleanSqlOption(value: string | undefined): string {
return value?.trim().replace(/[;\s]+/g, "") ?? "";
}