fix(db): support routine rename editing

This commit is contained in:
t8y2
2026-05-18 21:24:03 +08:00
parent 06b0c60a0e
commit da00405e10
10 changed files with 453 additions and 30 deletions
@@ -34,7 +34,12 @@ import type { ConnectionConfig, ObjectInfo, ObjectSourceKind } from "@/types/dat
import { isSchemaAware } from "@/lib/databaseCapabilities";
import { buildTableSelectSql, qualifiedTableName } from "@/lib/tableSelectSql";
import { useToast } from "@/composables/useToast";
import { buildExecutableObjectSourceStatements, objectSourceSaveExecutionMode } from "@/lib/objectSourceEditor";
import {
buildExecutableObjectSourceStatements,
buildRoutineRenameObjectSourceStatements,
objectSourceSaveExecutionMode,
supportsSourceBackedRoutineRename,
} from "@/lib/objectSourceEditor";
import { buildRenameObjectSql, supportsObjectRename } from "@/lib/objectRenameSql";
import { useConnectionStore } from "@/stores/connectionStore";
import { useQueryStore } from "@/stores/queryStore";
@@ -169,7 +174,10 @@ function canOpenSource(row: ObjectBrowserRow) {
}
function canRename(row: ObjectBrowserRow) {
return supportsObjectRename(props.connection.db_type, row.type);
return (
supportsObjectRename(props.connection.db_type, row.type) ||
supportsSourceBackedRoutineRename(props.connection.db_type, row.type as ObjectSourceKind)
);
}
function sourceTitle(row: ObjectBrowserRow | null) {
@@ -250,6 +258,9 @@ function renamePreviewSql() {
const row = renameTarget.value;
const newName = renameInput.value.trim();
if (!row || !newName || newName === row.name) return "";
if (supportsSourceBackedRoutineRename(props.connection.db_type, row.type as ObjectSourceKind)) {
return `-- Recreate ${row.type} from source, then drop the original object.`;
}
try {
return buildRenameObjectSql({
databaseType: props.connection.db_type,
@@ -270,14 +281,35 @@ async function confirmRename() {
renameError.value = "";
try {
const schema = row.schema || selectedSchema.value || props.database;
const sql = buildRenameObjectSql({
databaseType: props.connection.db_type,
objectType: row.type,
schema,
oldName: row.name,
newName,
});
await api.executeQuery(props.connection.id, props.database, sql, schema);
if (supportsSourceBackedRoutineRename(props.connection.db_type, row.type as ObjectSourceKind)) {
const source = await api.getObjectSource(
props.connection.id,
props.database,
schema,
row.name,
row.type as ObjectSourceKind,
);
const statements = buildRoutineRenameObjectSourceStatements({
databaseType: props.connection.db_type,
objectType: row.type as ObjectSourceKind,
schema,
name: row.name,
newName,
source: source.source,
});
for (const sql of statements) {
await api.executeQuery(props.connection.id, props.database, sql, schema);
}
} else {
const sql = buildRenameObjectSql({
databaseType: props.connection.db_type,
objectType: row.type,
schema,
oldName: row.name,
newName,
});
await api.executeQuery(props.connection.id, props.database, sql, schema);
}
toast(t("contextMenu.renameObjectSuccess", { oldName: row.name, newName }));
showRenameDialog.value = false;
if (sourceRow.value?.id === row.id) closeSource();
@@ -102,6 +102,7 @@ import {
uniqueDuckDbAttachedDatabaseName,
} from "@/lib/createDatabaseSql";
import { buildRenameObjectSql, supportsObjectRename, type RenameableObjectType } from "@/lib/objectRenameSql";
import { buildRoutineRenameObjectSourceStatements, supportsSourceBackedRoutineRename } from "@/lib/objectSourceEditor";
import { hexToRgba } from "@/lib/color";
import { focusSidebarRenameInput, shouldPreventRenameCloseAutoFocus } from "@/lib/sidebarRenameFocus";
import DangerConfirmDialog from "@/components/editor/DangerConfirmDialog.vue";
@@ -687,7 +688,11 @@ function nodeRenameObjectType(): RenameableObjectType | null {
const canRenameObject = computed(() => {
const objectType = nodeRenameObjectType();
return !!objectType && supportsObjectRename(currentDatabaseType(), objectType);
return (
!!objectType &&
(supportsObjectRename(currentDatabaseType(), objectType) ||
supportsSourceBackedRoutineRename(currentDatabaseType(), objectType as any))
);
});
function openRenameObjectDialog() {
@@ -700,6 +705,9 @@ function buildRenameObjectPreviewSql(): string {
const objectType = nodeRenameObjectType();
const newName = renameObjectName.value.trim();
if (!objectType || !newName || newName === props.node.label) return "";
if (supportsSourceBackedRoutineRename(currentDatabaseType(), objectType as any)) {
return `-- Recreate ${objectType} from source, then drop the original object.`;
}
try {
return buildRenameObjectSql({
databaseType: currentDatabaseType(),
@@ -720,15 +728,32 @@ async function confirmRenameObject() {
if (!objectType || !newName || newName === node.label || !node.connectionId || !node.database) return;
renameObjectError.value = "";
try {
const sql = buildRenameObjectSql({
databaseType: currentDatabaseType(),
objectType,
schema: node.schema,
oldName: node.label,
newName,
});
const dbType = currentDatabaseType();
await connectionStore.ensureConnected(node.connectionId);
await api.executeQuery(node.connectionId, node.database, sql, node.schema);
if (supportsSourceBackedRoutineRename(dbType, objectType as any)) {
const schema = node.schema || node.database;
const source = await api.getObjectSource(node.connectionId, node.database, schema, node.label, objectType as any);
const statements = buildRoutineRenameObjectSourceStatements({
databaseType: dbType!,
objectType: objectType as any,
schema,
name: node.label,
newName,
source: source.source,
});
for (const sql of statements) {
await api.executeQuery(node.connectionId, node.database, sql, schema);
}
} else {
const sql = buildRenameObjectSql({
databaseType: dbType,
objectType,
schema: node.schema,
oldName: node.label,
newName,
});
await api.executeQuery(node.connectionId, node.database, sql, node.schema);
}
toast(t("contextMenu.renameObjectSuccess", { oldName: node.label, newName }), 3000);
showRenameObjectDialog.value = false;
await refreshTableList(node);