mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-02 02:34:42 +08:00
fix(xugu): exclude synthetic scopes from schema export
This commit is contained in:
@@ -12,7 +12,7 @@ import * as api from "@/lib/backend/api";
|
||||
import type { ExportProgress } from "@/lib/backend/api";
|
||||
import { isSchemaAware, isSingleDatabase } from "@/lib/database/databaseFeatureSupport";
|
||||
import { databaseOptionsForConnection, fetchNamespaceOptionsForConnection } from "@/composables/useDatabaseOptions";
|
||||
import { buildAllDatabaseExportPlan, generateDatabaseExportId, runDatabaseExportUntilTerminal, runWithDatabaseBackupSnapshot, shouldUseDatabaseBackupSnapshot, type AllDatabaseExportPlanItem } from "@/lib/export/databaseExport";
|
||||
import { buildAllDatabaseExportPlan, filterExportableSchemas, generateDatabaseExportId, runDatabaseExportUntilTerminal, runWithDatabaseBackupSnapshot, shouldUseDatabaseBackupSnapshot, type AllDatabaseExportPlanItem } from "@/lib/export/databaseExport";
|
||||
import { buildSelectedTablesPayload, isDatabaseExportTableSelectionValid } from "@/lib/export/databaseExportSelection";
|
||||
import { isTauriRuntime } from "@/lib/backend/tauriRuntime";
|
||||
import { useToast } from "@/composables/useToast";
|
||||
@@ -215,7 +215,7 @@ async function loadSchemas(preferredSchema = "") {
|
||||
return;
|
||||
}
|
||||
|
||||
const schemaList = await api.listSchemas(connectionId.value, database.value);
|
||||
const schemaList = filterExportableSchemas(await api.listSchemas(connectionId.value, database.value), config?.db_type);
|
||||
const selected = preferredSchema && schemaList.includes(preferredSchema) ? preferredSchema : schemaList.includes("public") ? "public" : (schemaList[0] ?? "");
|
||||
schemas.value = schemaList;
|
||||
schema.value = selected;
|
||||
@@ -289,7 +289,7 @@ async function buildExportPlanForDatabases(dbs: string[]): Promise<AllDatabaseEx
|
||||
const schemasByDatabase: Record<string, string[]> = {};
|
||||
if (schemaAware) {
|
||||
for (const db of dbs) {
|
||||
schemasByDatabase[db] = await api.listSchemas(connectionId.value, db);
|
||||
schemasByDatabase[db] = filterExportableSchemas(await api.listSchemas(connectionId.value, db), dbType);
|
||||
}
|
||||
}
|
||||
return buildAllDatabaseExportPlan({ databases: dbs, schemaAware, schemasByDatabase, dbType });
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildAllDatabaseExportPlan, filterExportableSchemas } from "@/lib/export/databaseExport";
|
||||
import { XUGU_PUBLIC_SYNONYM_SCOPE, XUGU_SCHEDULER_JOB_SCOPE } from "@/lib/sidebar/xuguPublicSynonyms";
|
||||
|
||||
describe("database export schema selection", () => {
|
||||
it("hides Xugu synthetic tree scopes while preserving real schemas", () => {
|
||||
const schemas = ["APP_TEST", "GUEST", XUGU_PUBLIC_SYNONYM_SCOPE, XUGU_SCHEDULER_JOB_SCOPE];
|
||||
|
||||
expect(filterExportableSchemas(schemas, "xugu")).toEqual(["APP_TEST", "GUEST"]);
|
||||
});
|
||||
|
||||
it("does not apply Xugu filtering to other database types", () => {
|
||||
const schemas = ["APP_TEST", XUGU_PUBLIC_SYNONYM_SCOPE, XUGU_SCHEDULER_JOB_SCOPE];
|
||||
|
||||
expect(filterExportableSchemas(schemas, "postgres")).toEqual(schemas);
|
||||
});
|
||||
|
||||
it("excludes synthetic scopes from an all-database Xugu export plan", () => {
|
||||
expect(
|
||||
buildAllDatabaseExportPlan({
|
||||
databases: ["SHOP_DEMO"],
|
||||
schemaAware: true,
|
||||
dbType: "xugu",
|
||||
schemasByDatabase: {
|
||||
SHOP_DEMO: ["APP_TEST", XUGU_PUBLIC_SYNONYM_SCOPE, XUGU_SCHEDULER_JOB_SCOPE],
|
||||
},
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
database: "SHOP_DEMO",
|
||||
schema: "APP_TEST",
|
||||
fileStem: "SHOP_DEMO",
|
||||
displayName: "SHOP_DEMO",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import * as api from "@/lib/backend/api.ts";
|
||||
import { buildTableSelectSql } from "@/lib/table/tableSelectSql.ts";
|
||||
import { uuid } from "@/lib/common/utils.ts";
|
||||
import { SINGLE_DATABASE_TYPES } from "@/lib/database/databaseCapabilitySets";
|
||||
import { isXuguSyntheticScope } from "@/lib/sidebar/xuguPublicSynonyms";
|
||||
|
||||
export const DATABASE_EXPORT_ROW_LIMIT = 10_000;
|
||||
export const DATABASE_EXPORT_PAGE_SIZE = 500;
|
||||
@@ -76,6 +77,19 @@ export interface AllDatabaseExportPlanItem {
|
||||
displayName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return schemas that can be exported as ordinary schema-owned objects.
|
||||
*
|
||||
* Xugu exposes database-global namespaces (public synonyms and scheduler jobs)
|
||||
* through reserved synthetic schema names so the sidebar can reuse its normal
|
||||
* tree loading path. They are not real schemas and must not be offered by the
|
||||
* schema export selector.
|
||||
*/
|
||||
export function filterExportableSchemas(schemas: readonly string[], databaseType?: DatabaseType): string[] {
|
||||
if (databaseType !== "xugu") return [...schemas];
|
||||
return schemas.filter((schema) => !isXuguSyntheticScope(schema));
|
||||
}
|
||||
|
||||
export interface DatabaseBackupSnapshotOptions {
|
||||
connectionId: string;
|
||||
database: string;
|
||||
@@ -153,7 +167,7 @@ export function buildAllDatabaseExportPlan(options: AllDatabaseExportPlanInput):
|
||||
}));
|
||||
}
|
||||
return options.databases.flatMap((database) => {
|
||||
const schemas = options.schemaAware ? (options.schemasByDatabase?.[database] ?? []).filter((schema) => schema.trim()) : [database];
|
||||
const schemas = options.schemaAware ? filterExportableSchemas(options.schemasByDatabase?.[database] ?? [], options.dbType).filter((schema) => schema.trim()) : [database];
|
||||
const exportSchemas = schemas.length > 0 ? schemas : [database];
|
||||
const includeSchemaInFileName = options.schemaAware && exportSchemas.length > 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user