feat(postgres): support safe database renaming
This commit is contained in:
20 files changed
+410
-7
No files matched your search
@@ -30,6 +30,7 @@ const {
|
||||
confirmDeleteGroup,
|
||||
showRenameObjectDialog,
|
||||
renameObjectName,
|
||||
renameObjectDialogTitle,
|
||||
renameObjectPreviewSql,
|
||||
renameObjectError,
|
||||
confirmRenameObject,
|
||||
@@ -274,7 +275,7 @@ watch(
|
||||
<Dialog v-model:open="showRenameObjectDialog">
|
||||
<DialogContent class="sm:max-w-[420px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t("contextMenu.renameObjectTitle") }}</DialogTitle>
|
||||
<DialogTitle>{{ renameObjectDialogTitle }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div class="grid gap-3">
|
||||
<Input v-model="renameObjectName" :placeholder="t('contextMenu.renameObjectNamePlaceholder')" @keydown.enter.prevent="confirmRenameObject" />
|
||||
|
||||
@@ -139,7 +139,7 @@ import {
|
||||
type DropObjectSqlOptions,
|
||||
type TableChildObjectType,
|
||||
} from "@/lib/database/dbAdminSql";
|
||||
import { buildRenameObjectSql, supportsObjectRename, type RenameableObjectType } from "@/lib/table/objectRenameSql";
|
||||
import { buildRenameObjectSql, buildRenameDatabaseSql, buildRenameDatabasePreflightSql, databaseRenameMaintenanceDatabase, supportsDatabaseRename, supportsObjectRename, type RenameableObjectType } from "@/lib/table/objectRenameSql";
|
||||
import { buildEditableObjectSource, buildRoutineRenameObjectSourceStatements, supportsSourceBackedRoutineRename } from "@/lib/table/objectSourceEditor";
|
||||
import { loadEditableObjectSourceForEditor } from "@/lib/table/objectSourceLoad";
|
||||
import { buildViewDdl } from "@/lib/table/viewDdl";
|
||||
@@ -1218,6 +1218,10 @@ function requestRenameSelectedNode(): boolean {
|
||||
openRenameMongoCollectionDialog();
|
||||
return true;
|
||||
}
|
||||
if (canRenameDatabase.value) {
|
||||
openRenameDatabaseDialog();
|
||||
return true;
|
||||
}
|
||||
if (canRenameObject.value) {
|
||||
openRenameObjectDialog();
|
||||
return true;
|
||||
@@ -2535,6 +2539,15 @@ function openRenameObjectDialog() {
|
||||
showRenameObjectDialog.value = true;
|
||||
}
|
||||
|
||||
function openRenameDatabaseDialog() {
|
||||
claimTreeItemDialogOwnership();
|
||||
routeTreeItemDialogController();
|
||||
renameObjectName.value = activeNode.value.label;
|
||||
renameObjectError.value = "";
|
||||
renameObjectPreviewSql.value = "";
|
||||
showRenameObjectDialog.value = true;
|
||||
}
|
||||
|
||||
async function executeTreeNodeSqlWithProductionGuard(
|
||||
node: Pick<TreeNode, "connectionId" | "database" | "schema">,
|
||||
sql: string,
|
||||
@@ -2544,6 +2557,7 @@ async function executeTreeNodeSqlWithProductionGuard(
|
||||
executeAsScript?: boolean;
|
||||
executionId?: string;
|
||||
isCancelledBeforeDispatch?: () => boolean;
|
||||
beforeExecute?: () => Promise<void>;
|
||||
markDispatched?: () => void;
|
||||
} = {},
|
||||
) {
|
||||
@@ -2562,11 +2576,13 @@ async function executeTreeNodeSqlWithProductionGuard(
|
||||
database,
|
||||
sql,
|
||||
source: t("production.sourceSidebar"),
|
||||
execute: () => {
|
||||
execute: async () => {
|
||||
// The caller may have observed a cancel click while we were still
|
||||
// waiting on connection setup or the production-safety confirmation
|
||||
// above — if so, never actually dispatch the SQL to the backend.
|
||||
if (options.isCancelledBeforeDispatch?.()) throw new Error("Operation cancelled before it was sent to the database.");
|
||||
await options.beforeExecute?.();
|
||||
if (options.isCancelledBeforeDispatch?.()) throw new Error("Operation cancelled before it was sent to the database.");
|
||||
options.markDispatched?.();
|
||||
return options.executeAsScript ? api.executeScript(node.connectionId!, database, sql, options.schema ?? node.schema) : api.executeQuery(node.connectionId!, database, sql, options.schema ?? node.schema, executionId, { timeoutSecs });
|
||||
},
|
||||
@@ -2578,9 +2594,27 @@ let renameObjectPreviewRequestId = 0;
|
||||
async function refreshRenameObjectPreviewSql() {
|
||||
const node = activeNode.value;
|
||||
const requestId = ++renameObjectPreviewRequestId;
|
||||
const objectType = nodeRenameObjectType();
|
||||
const newName = renameObjectName.value.trim();
|
||||
if (!showRenameObjectDialog.value || !objectType || !newName || newName === node.label) {
|
||||
if (!showRenameObjectDialog.value || !newName || newName === node.label) {
|
||||
renameObjectPreviewSql.value = "";
|
||||
return;
|
||||
}
|
||||
// Database rename path
|
||||
if (node.type === "database") {
|
||||
try {
|
||||
const sql = await buildRenameDatabaseSql({
|
||||
databaseType: currentDatabaseType(),
|
||||
oldName: node.label,
|
||||
newName,
|
||||
});
|
||||
if (requestId === renameObjectPreviewRequestId) renameObjectPreviewSql.value = sql;
|
||||
} catch {
|
||||
if (requestId === renameObjectPreviewRequestId) renameObjectPreviewSql.value = "";
|
||||
}
|
||||
return;
|
||||
}
|
||||
const objectType = nodeRenameObjectType();
|
||||
if (!objectType) {
|
||||
renameObjectPreviewSql.value = "";
|
||||
return;
|
||||
}
|
||||
@@ -2608,14 +2642,68 @@ watch([showRenameObjectDialog, renameObjectName, () => activeNode.value.label, (
|
||||
|
||||
async function confirmRenameObject() {
|
||||
const node = sidebarFormTarget.value ?? activeNode.value;
|
||||
const objectType = node.type === "table" ? "TABLE" : node.type === "view" ? "VIEW" : node.type === "materialized_view" ? "MATERIALIZED_VIEW" : node.type === "procedure" ? "PROCEDURE" : node.type === "function" ? "FUNCTION" : null;
|
||||
const newName = renameObjectName.value.trim();
|
||||
if (!objectType || !newName || newName === node.label || !node.connectionId || !node.database) return;
|
||||
if (!newName || newName === node.label || !node.connectionId || !node.database) return;
|
||||
renameObjectError.value = "";
|
||||
let renameApplied = false;
|
||||
try {
|
||||
const dbType = databaseTypeForNode(node);
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
|
||||
// Database rename path
|
||||
if (node.type === "database") {
|
||||
const maintenanceDatabase = databaseRenameMaintenanceDatabase(connectionStore.getConfig(node.connectionId)?.database, node.label);
|
||||
// Preflight: check permissions, prepared transactions, and active connections
|
||||
const preflightSql = await buildRenameDatabasePreflightSql({
|
||||
databaseType: dbType,
|
||||
databaseName: node.label,
|
||||
});
|
||||
const preflightResult = await api.executeQuery(node.connectionId, maintenanceDatabase, preflightSql);
|
||||
let activeConnections = 0;
|
||||
let preparedTransactions = 0;
|
||||
let isOwner = false;
|
||||
if (preflightResult && preflightResult.rows.length > 0) {
|
||||
const row = preflightResult.rows[0] as any[];
|
||||
activeConnections = Number(row[0]) || 0;
|
||||
preparedTransactions = Number(row[1]) || 0;
|
||||
isOwner = row[2] === true || row[2] === "t" || String(row[2]) === "true";
|
||||
}
|
||||
|
||||
if (!isOwner) {
|
||||
renameObjectError.value = t("contextMenu.renameDatabaseNotOwner", { name: node.label });
|
||||
return;
|
||||
}
|
||||
if (preparedTransactions > 0) {
|
||||
renameObjectError.value = t("contextMenu.renameDatabasePreparedTransactions", { name: node.label, count: preparedTransactions });
|
||||
return;
|
||||
}
|
||||
|
||||
const sql = await buildRenameDatabaseSql({
|
||||
databaseType: dbType,
|
||||
oldName: node.label,
|
||||
newName,
|
||||
terminateConnections: activeConnections > 0,
|
||||
});
|
||||
const executed = await executeTreeNodeSqlWithProductionGuard(node, sql, {
|
||||
database: maintenanceDatabase,
|
||||
executeAsScript: true,
|
||||
beforeExecute: () => connectionStore.closeDatabaseConnection(node.connectionId!, node.label),
|
||||
});
|
||||
if (executed === undefined) return;
|
||||
renameApplied = true;
|
||||
toast(t("contextMenu.renameObjectSuccess", { oldName: node.label, newName }), 3000);
|
||||
showRenameObjectDialog.value = false;
|
||||
const liveNode = findSidebarActionTarget(connectionStore.treeNodes, createSidebarActionTarget(node)) ?? node;
|
||||
liveNode.label = newName;
|
||||
liveNode.database = newName;
|
||||
const renamedNode: TreeNode = { ...liveNode, label: newName, database: newName };
|
||||
connectionStore.replacePinnedTreeNode(liveNode, renamedNode);
|
||||
void connectionStore.refreshTreeNode(liveNode);
|
||||
return;
|
||||
}
|
||||
|
||||
const objectType = node.type === "table" ? "TABLE" : node.type === "view" ? "VIEW" : node.type === "materialized_view" ? "MATERIALIZED_VIEW" : node.type === "procedure" ? "PROCEDURE" : node.type === "function" ? "FUNCTION" : null;
|
||||
if (!objectType) return;
|
||||
if (supportsSourceBackedRoutineRename(dbType, objectType as any)) {
|
||||
const schema = node.schema || node.database;
|
||||
const source = await api.getObjectSource(node.connectionId, node.database, schema, node.objectName || node.label, objectType as any, node.signature);
|
||||
@@ -2954,6 +3042,18 @@ const canEditDatabaseCharsetCollation = computed(() => databasePropertyGroups.va
|
||||
|
||||
const canEditDatabaseComment = computed(() => databasePropertyGroups.value.includes("databaseComment"));
|
||||
|
||||
const canRenameDatabase = computed(() => {
|
||||
const node = activeNode.value;
|
||||
if (node.type !== "database" || !node.database) return false;
|
||||
const config = node.connectionId ? connectionStore.getConfig(node.connectionId) : undefined;
|
||||
return !!config && !config.read_only && supportsDatabaseRename(config.db_type);
|
||||
});
|
||||
|
||||
const renameObjectDialogTitle = computed(() => {
|
||||
if (activeNode.value.type === "database") return t("contextMenu.renameDatabaseTitle");
|
||||
return t("contextMenu.renameObjectTitle");
|
||||
});
|
||||
|
||||
const canCreateSchema = computed(() => {
|
||||
const config = activeNode.value.connectionId ? connectionStore.getConfig(activeNode.value.connectionId) : undefined;
|
||||
return canCreateDatabaseNodeNamespace(config, activeNode.value) && !isSqlServerLinkedNode(activeNode.value) && !connectionUsesDatabaseObjectTreeMode(config);
|
||||
@@ -4388,6 +4488,7 @@ function objectDialogCapabilities() {
|
||||
return {
|
||||
showRenameObjectDialog,
|
||||
renameObjectName,
|
||||
renameObjectDialogTitle,
|
||||
renameObjectPreviewSql,
|
||||
renameObjectError,
|
||||
confirmRenameObject,
|
||||
@@ -4917,6 +5018,14 @@ function buildDatabaseSidebarMenu(context: SidebarMenuFactoryContext): boolean {
|
||||
if (canEditDatabaseProperties.value) {
|
||||
items.push({ label: t("contextMenu.editDatabaseProperties"), action: openEditDatabasePropertiesDialog, icon: SquarePen });
|
||||
}
|
||||
if (canRenameDatabase.value) {
|
||||
items.push({
|
||||
label: t("contextMenu.renameDatabase"),
|
||||
action: openRenameDatabaseDialog,
|
||||
icon: Pencil,
|
||||
shortcut: shortcutRename,
|
||||
});
|
||||
}
|
||||
if (canCreateTable.value) {
|
||||
items.push({ label: t("contextMenu.createTable"), action: createTable, icon: Plus });
|
||||
}
|
||||
|
||||
@@ -2880,6 +2880,10 @@ export default {
|
||||
renameObjectTitle: "Rename Object",
|
||||
renameObjectNamePlaceholder: "New name",
|
||||
renameObjectSuccess: '"{oldName}" renamed to "{newName}"',
|
||||
renameDatabase: "Rename Database",
|
||||
renameDatabaseTitle: "Rename Database",
|
||||
renameDatabaseNotOwner: 'Only the database owner can rename "{name}".',
|
||||
renameDatabasePreparedTransactions: 'Database "{name}" has {count} pending prepared transaction(s). Please COMMIT or ROLLBACK them first.',
|
||||
confirmDropTableTitle: "Drop Table",
|
||||
confirmDropTableMessage: 'Are you sure you want to drop "{name}"? This will permanently delete the table and all its data.',
|
||||
dropTableCascade: "Use CASCADE",
|
||||
|
||||
@@ -2790,6 +2790,10 @@ export default withEnglishFallback({
|
||||
renameObjectTitle: "Renombrar objeto",
|
||||
renameObjectNamePlaceholder: "Nuevo nombre",
|
||||
renameObjectSuccess: '"{oldName}" renombrado a "{newName}"',
|
||||
renameDatabase: "Renombrar base de datos",
|
||||
renameDatabaseTitle: "Renombrar base de datos",
|
||||
renameDatabaseNotOwner: 'Solo el propietario puede renombrar "{name}".',
|
||||
renameDatabasePreparedTransactions: 'La base de datos "{name}" tiene {count} transacciones preparadas pendientes. Ejecute COMMIT o ROLLBACK primero.',
|
||||
confirmDropTableTitle: "Eliminar tabla",
|
||||
confirmDropTableMessage: '¿Estás seguro de que deseas eliminar "{name}"? Esto borrará permanentemente la tabla y todos sus datos.',
|
||||
dropTableCascade: "Usar CASCADE",
|
||||
|
||||
@@ -2788,6 +2788,10 @@ export default withEnglishFallback({
|
||||
renameObjectTitle: "Rinomina Oggetto",
|
||||
renameObjectNamePlaceholder: "Nuovo nome",
|
||||
renameObjectSuccess: '"{oldName}" rinominato in "{newName}"',
|
||||
renameDatabase: "Rinomina Database",
|
||||
renameDatabaseTitle: "Rinomina Database",
|
||||
renameDatabaseNotOwner: 'Solo il proprietario può rinominare "{name}".',
|
||||
renameDatabasePreparedTransactions: 'Il database "{name}" ha {count} transazioni preparate in sospeso. Eseguire COMMIT o ROLLBACK prima.',
|
||||
confirmDropTableTitle: "Elimina Tabella",
|
||||
confirmDropTableMessage: 'Sei sicuro di voler eliminare (DROP) la tabella "{name}"? Questa operazione eliminerà permanentemente la tabella e tutti i suoi dati.',
|
||||
dropTableCascade: "Usa CASCADE",
|
||||
|
||||
@@ -2812,6 +2812,10 @@ export default withEnglishFallback({
|
||||
renameObjectTitle: "オブジェクト名を変更",
|
||||
renameObjectNamePlaceholder: "新しい名前",
|
||||
renameObjectSuccess: "「{oldName}」の名前を「{newName}」に変更しました",
|
||||
renameDatabase: "データベース名を変更",
|
||||
renameDatabaseTitle: "データベース名を変更",
|
||||
renameDatabaseNotOwner: "データベース「{name}」の所有者のみが名前を変更できます。",
|
||||
renameDatabasePreparedTransactions: "データベース「{name}」には {count} 件の保留中のプリペアドトランザクションがあります。先に COMMIT または ROLLBACK してください。",
|
||||
confirmDropTableTitle: "テーブルを削除",
|
||||
confirmDropTableMessage: "本当にテーブル「{name}」をドロップ(削除)しますか?テーブルとすべてのデータが永久に削除されます。",
|
||||
dropTableCascade: "CASCADE を使用",
|
||||
|
||||
@@ -3015,6 +3015,10 @@ export default withEnglishFallback({
|
||||
closeRightTabs: "Fechar abas à direita",
|
||||
compileObject: "Compilar",
|
||||
compileObjectSuccess: '"{name}" compilado com sucesso',
|
||||
renameDatabase: "Renomear banco de dados",
|
||||
renameDatabaseTitle: "Renomear banco de dados",
|
||||
renameDatabaseNotOwner: "Somente o proprietário do banco de dados pode renomear «{name}».",
|
||||
renameDatabasePreparedTransactions: "Há {count} transações preparadas pendentes no banco de dados «{name}». Execute COMMIT ou ROLLBACK antes de renomear.",
|
||||
},
|
||||
visibleDatabases: {
|
||||
title: "Bancos de dados visíveis",
|
||||
|
||||
@@ -2804,6 +2804,10 @@ export default withEnglishFallback({
|
||||
renameObjectTitle: "重命名对象",
|
||||
renameObjectNamePlaceholder: "新名称",
|
||||
renameObjectSuccess: "已将「{oldName}」重命名为「{newName}」",
|
||||
renameDatabase: "重命名数据库",
|
||||
renameDatabaseTitle: "重命名数据库",
|
||||
renameDatabaseNotOwner: "只有数据库所有者才能重命名「{name}」。",
|
||||
renameDatabasePreparedTransactions: "数据库「{name}」中有 {count} 个未完成的预备事务,请先 COMMIT 或 ROLLBACK 后再重命名。",
|
||||
confirmDropTableTitle: "删除表",
|
||||
confirmDropTableMessage: "确定要删除「{name}」吗?这将永久删除表及其所有数据。",
|
||||
dropTableCascade: "使用 CASCADE 强制删除",
|
||||
|
||||
@@ -2788,6 +2788,10 @@ export default withEnglishFallback({
|
||||
renameObjectTitle: "重新命名物件",
|
||||
renameObjectNamePlaceholder: "新名稱",
|
||||
renameObjectSuccess: "已將「{oldName}」重新命名為「{newName}」",
|
||||
renameDatabase: "重新命名資料庫",
|
||||
renameDatabaseTitle: "重新命名資料庫",
|
||||
renameDatabaseNotOwner: "只有資料庫擁有者才能重新命名「{name}」。",
|
||||
renameDatabasePreparedTransactions: "資料庫「{name}」中有 {count} 個未完成的預備事務,請先 COMMIT 或 ROLLBACK 後再重新命名。",
|
||||
confirmDropTableTitle: "刪除資料表",
|
||||
confirmDropTableMessage: "確定要刪除「{name}」嗎?這將永久刪除資料表及其所有資料。",
|
||||
dropTableCascade: "使用 CASCADE 強制刪除",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { databaseRenameMaintenanceDatabase, supportsDatabaseRename } from "@/lib/table/objectRenameSql";
|
||||
|
||||
describe("database rename", () => {
|
||||
it("chooses a maintenance database outside the rename target", () => {
|
||||
expect(databaseRenameMaintenanceDatabase("admin", "application")).toBe("admin");
|
||||
expect(databaseRenameMaintenanceDatabase("application", "application")).toBe("postgres");
|
||||
expect(databaseRenameMaintenanceDatabase(undefined, "application")).toBe("postgres");
|
||||
expect(databaseRenameMaintenanceDatabase("postgres", "postgres")).toBe("template1");
|
||||
expect(databaseRenameMaintenanceDatabase("template1", "postgres")).toBe("template1");
|
||||
});
|
||||
|
||||
it("does not expose database rename for YashanDB", () => {
|
||||
expect(supportsDatabaseRename("postgres")).toBe(true);
|
||||
expect(supportsDatabaseRename("yashandb")).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -227,6 +227,8 @@ export const buildTableSelectSql = forward("buildTableSelectSql");
|
||||
export const buildDatabaseSearchSql = forward("buildDatabaseSearchSql");
|
||||
export const buildSearchResultWhere = forward("buildSearchResultWhere");
|
||||
export const buildRenameObjectSql = forward("buildRenameObjectSql");
|
||||
export const buildRenameDatabaseSql = forward("buildRenameDatabaseSql");
|
||||
export const buildRenameDatabasePreflightSql = forward("buildRenameDatabasePreflightSql");
|
||||
export const buildCreateDatabaseSql = forward("buildCreateDatabaseSql");
|
||||
export const buildDuckDbAttachDatabaseSql = forward("buildDuckDbAttachDatabaseSql");
|
||||
export const buildSqliteAttachDatabaseSql = forward("buildSqliteAttachDatabaseSql");
|
||||
|
||||
@@ -1316,6 +1316,14 @@ export async function buildRenameObjectSql(options: BuildRenameObjectSqlOptions)
|
||||
return post("/api/query/build-rename-object-sql", { options });
|
||||
}
|
||||
|
||||
export async function buildRenameDatabaseSql(options: { databaseType?: DatabaseType; oldName: string; newName: string; terminateConnections: boolean }): Promise<string> {
|
||||
return post("/api/query/build-rename-database-sql", options);
|
||||
}
|
||||
|
||||
export async function buildRenameDatabasePreflightSql(options: { databaseType?: DatabaseType; databaseName: string }): Promise<string> {
|
||||
return post("/api/query/build-rename-database-preflight-sql", options);
|
||||
}
|
||||
|
||||
export async function buildCreateDatabaseSql(options: CreateDatabaseSqlOptions): Promise<string> {
|
||||
return post("/api/query/build-create-database-sql", { options });
|
||||
}
|
||||
|
||||
@@ -1494,6 +1494,22 @@ export async function buildRenameObjectSql(options: BuildRenameObjectSqlOptions)
|
||||
return invoke("build_rename_object_sql", { options });
|
||||
}
|
||||
|
||||
export async function buildRenameDatabaseSql(options: { databaseType?: DatabaseType; oldName: string; newName: string; terminateConnections: boolean }): Promise<string> {
|
||||
return invoke("build_rename_database_sql", {
|
||||
databaseType: options.databaseType,
|
||||
oldName: options.oldName,
|
||||
newName: options.newName,
|
||||
terminateConnections: options.terminateConnections,
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildRenameDatabasePreflightSql(options: { databaseType?: DatabaseType; databaseName: string }): Promise<string> {
|
||||
return invoke("build_rename_database_preflight_sql", {
|
||||
databaseType: options.databaseType,
|
||||
databaseName: options.databaseName,
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildCreateDatabaseSql(options: CreateDatabaseSqlOptions): Promise<string> {
|
||||
return invoke("build_create_database_sql", { options });
|
||||
}
|
||||
|
||||
@@ -32,3 +32,36 @@ export function supportsObjectRename(databaseType: DatabaseType | undefined, obj
|
||||
export function buildRenameObjectSql(options: BuildRenameObjectSqlOptions): Promise<string> {
|
||||
return api.buildRenameObjectSql(options);
|
||||
}
|
||||
|
||||
// ── Database rename (PostgreSQL family) ──
|
||||
|
||||
const DATABASE_RENAME_TYPES = new Set<DatabaseType>(["postgres", "redshift", "gaussdb", "kwdb", "kingbase", "highgo", "uxdb", "vastbase", "opengauss"]);
|
||||
|
||||
export function supportsDatabaseRename(databaseType?: DatabaseType): boolean {
|
||||
return !!databaseType && DATABASE_RENAME_TYPES.has(databaseType);
|
||||
}
|
||||
|
||||
export function databaseRenameMaintenanceDatabase(configuredDatabase: string | undefined, targetDatabase: string): string {
|
||||
if (configuredDatabase && configuredDatabase !== targetDatabase) return configuredDatabase;
|
||||
return targetDatabase === "postgres" ? "template1" : "postgres";
|
||||
}
|
||||
|
||||
export interface BuildRenameDatabaseSqlOptions {
|
||||
databaseType?: DatabaseType;
|
||||
oldName: string;
|
||||
newName: string;
|
||||
terminateConnections?: boolean;
|
||||
}
|
||||
|
||||
export function buildRenameDatabaseSql(options: BuildRenameDatabaseSqlOptions): Promise<string> {
|
||||
return api.buildRenameDatabaseSql({ ...options, terminateConnections: options.terminateConnections ?? false });
|
||||
}
|
||||
|
||||
export interface BuildRenameDatabasePreflightSqlOptions {
|
||||
databaseType?: DatabaseType;
|
||||
databaseName: string;
|
||||
}
|
||||
|
||||
export function buildRenameDatabasePreflightSql(options: BuildRenameDatabasePreflightSqlOptions): Promise<string> {
|
||||
return api.buildRenameDatabasePreflightSql(options);
|
||||
}
|
||||
Reference in new issue
Block a user