feat(xugu): expose tablespaces and datafiles in tree
This commit is contained in:
1 parent
afe3b3f3c2
commit
351a8b699b
32 files changed
+811
-4
No files matched your search
@@ -164,6 +164,7 @@ import { invalidateObjectBrowserRowsCache } from "@/lib/table/objectBrowserRowsC
|
||||
import { MetadataTaskLimiter } from "@/lib/metadata/metadataTaskLimiter";
|
||||
import { buildCustomTypeTreeChildren } from "@/lib/sidebar/customTypeTree";
|
||||
import { TreeNodeLoadRegistry, type TreeNodeLoadHandle } from "@/lib/metadata/treeNodeLoadHandle";
|
||||
import { buildXuguTablespaceChildren } from "@/lib/sidebar/xuguTablespaces";
|
||||
import i18n from "@/i18n";
|
||||
import type { MqAdminConfig } from "@/types/mq";
|
||||
import { RABBITMQ_MQ_TENANT, resolveMqSystemKindFromConnection } from "@/lib/mq/mqConsoleDefaults";
|
||||
@@ -1364,7 +1365,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
// as metadata children, withConnectionUtilityNodes would keep the old copies
|
||||
// AND append fresh ones on every useCachedChildren pass, duplicating the
|
||||
// 用户/角色 menus once per refresh cycle.
|
||||
return node.type === "user-admin" || node.type === "dameng-users" || node.type === "dameng-roles" || node.type === "dameng-job-admin" || node.type === "saved-sql-root";
|
||||
return node.type === "user-admin" || node.type === "dameng-users" || node.type === "dameng-roles" || node.type === "dameng-job-admin" || node.type === "group-tablespaces" || node.type === "saved-sql-root";
|
||||
}
|
||||
|
||||
function connectionMetadataChildren(children: TreeNode[] | undefined): TreeNode[] {
|
||||
@@ -1653,13 +1654,33 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
};
|
||||
}
|
||||
|
||||
function buildXuguTablespacesNode(connectionId: string, existingConnectionNode?: TreeNode): TreeNode | undefined {
|
||||
const config = getConfig(connectionId);
|
||||
if (effectiveDatabaseTypeForConnection(config) !== "xugu") return undefined;
|
||||
const existing = existingConnectionNode?.children?.find((child) => child.type === "group-tablespaces");
|
||||
return {
|
||||
id: `${connectionId}:__xugu_tablespaces`,
|
||||
label: "tree.xuguTablespaces",
|
||||
type: "group-tablespaces",
|
||||
connectionId,
|
||||
// SYS_TABLESPACES/SYS_DATAFILES are scoped to the current database. The
|
||||
// optional value lets the agent switch to the configured database while
|
||||
// retaining compatibility with connections that have no default DB.
|
||||
database: config?.database || "",
|
||||
objectCount: existing?.objectCount,
|
||||
isExpanded: existing?.isExpanded ?? false,
|
||||
children: existing?.children ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
function withConnectionUtilityNodes(connectionId: string, children: TreeNode[], existingConnectionNode?: TreeNode): TreeNode[] {
|
||||
const nonUtilityChildren = connectionMetadataChildren(children);
|
||||
const userAdminNode = buildUserAdminNode(connectionId, existingConnectionNode);
|
||||
const damengUserNode = buildDamengUserNode(connectionId, existingConnectionNode);
|
||||
const damengRoleNode = buildDamengRoleNode(connectionId, existingConnectionNode);
|
||||
const damengJobAdminNode = buildDamengJobAdminNode(connectionId, existingConnectionNode);
|
||||
return [...nonUtilityChildren, userAdminNode, damengUserNode, damengRoleNode, damengJobAdminNode].filter(Boolean) as TreeNode[];
|
||||
const xuguTablespacesNode = buildXuguTablespacesNode(connectionId, existingConnectionNode);
|
||||
return [...nonUtilityChildren, userAdminNode, damengUserNode, damengRoleNode, damengJobAdminNode, xuguTablespacesNode].filter(Boolean) as TreeNode[];
|
||||
}
|
||||
|
||||
function withSavedSqlRoot(connectionId: string, children: TreeNode[], existingConnectionNode?: TreeNode): TreeNode[] {
|
||||
@@ -4137,6 +4158,50 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
{ flush: "post" },
|
||||
);
|
||||
|
||||
async function loadXuguTablespaces(node: TreeNode, options?: LoadTreeOptions) {
|
||||
if (node.type !== "group-tablespaces" || !node.connectionId) return;
|
||||
const connectionId = node.connectionId;
|
||||
const config = getConfig(connectionId);
|
||||
if (effectiveDatabaseTypeForConnection(config) !== "xugu") return;
|
||||
return runTreeMetadataLoad(
|
||||
{
|
||||
kind: "xugu-tablespaces",
|
||||
connectionId,
|
||||
database: node.database || undefined,
|
||||
driverProfile: metadataDriverProfile(config),
|
||||
},
|
||||
async () => {
|
||||
let load = beginTreeNodeLoad(node);
|
||||
try {
|
||||
await ensureConnected(connectionId);
|
||||
load = reclaimTreeNodeLoad(load, node);
|
||||
if (useCachedChildren(node, options, load)) return;
|
||||
const tablespaces = await withMetadataLoadTimeout(connectionId, api.listXuguTablespaces(connectionId, node.database || undefined), "Xugu tablespaces");
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
const children = buildXuguTablespaceChildren(targetNode, tablespaces);
|
||||
setChildren(targetNode, children);
|
||||
targetNode.objectCount = children.length;
|
||||
targetNode.isExpanded = true;
|
||||
} catch (error) {
|
||||
// Storage metadata is an optional, read-only enhancement. A user
|
||||
// without SYS_* view access should see an empty group rather than a
|
||||
// connection-level RPC error that blocks the rest of the tree.
|
||||
console.debug("[DBX][xugu-tablespaces:unavailable]", { connectionId, error });
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (targetNode) {
|
||||
setChildren(targetNode, []);
|
||||
targetNode.objectCount = 0;
|
||||
targetNode.isExpanded = true;
|
||||
}
|
||||
} finally {
|
||||
finishTreeNodeLoad(load);
|
||||
}
|
||||
},
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
async function loadDatabases(connectionId: string, options?: LoadTreeOptions) {
|
||||
const configForScope = getConfig(connectionId);
|
||||
const searchFilter = activeTreeLoadSearchFilter(options);
|
||||
@@ -6549,6 +6614,8 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
node.isExpanded = true;
|
||||
} else if (node.type === "doris-catalog" && node.connectionId) {
|
||||
await loadDorisCatalogDatabases(node, options);
|
||||
} else if (node.type === "group-tablespaces" && node.connectionId) {
|
||||
await loadXuguTablespaces(node, options);
|
||||
} else if (node.type === "database" && node.connectionId && hasTreeNodeDatabaseContext(node)) {
|
||||
if (node.catalog && node.catalog !== "internal") {
|
||||
await loadDorisCatalogTables(node, options);
|
||||
@@ -8863,6 +8930,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
loadObjectGroupChildren,
|
||||
loadCustomTypeChildren,
|
||||
loadPackageMembers,
|
||||
loadXuguTablespaces,
|
||||
loadXuguTypeMembers,
|
||||
loadMoreObjectGroupChildren,
|
||||
loadAllObjectGroupChildren,
|
||||
|
||||
Reference in new issue
Block a user