From 820b8cd26fbd5d00b4357e123dee0760a8ce87c7 Mon Sep 17 00:00:00 2001 From: amwps290 Date: Wed, 29 Jul 2026 03:23:04 +0800 Subject: [PATCH] feat(metadata): honor system schema visibility --- .../drivers/kingbase-go/kingbase_metadata.go | 28 ++++-- agents/drivers/kingbase-go/main.go | 10 +- agents/drivers/kingbase-go/main_test.go | 18 ++++ .../connection/ConnectionDialog.vue | 10 ++ .../src/components/objects/ObjectBrowser.vue | 16 ++- .../__tests__/useSchemaOptions.spec.ts | 17 +++- .../src/composables/useSchemaOptions.ts | 8 +- apps/desktop/src/i18n/locales/en.ts | 2 + apps/desktop/src/i18n/locales/es.ts | 2 + apps/desktop/src/i18n/locales/it.ts | 2 + apps/desktop/src/i18n/locales/ja.ts | 2 + apps/desktop/src/i18n/locales/pt-BR.ts | 2 + apps/desktop/src/i18n/locales/zh-CN.ts | 2 + apps/desktop/src/i18n/locales/zh-TW.ts | 2 + .../database/visibleDatabases.spec.ts | 52 ++++++++++ .../src/lib/database/visibleDatabases.ts | 97 ++++++++++++++++++- .../connectionStore.metadataLoading.spec.ts | 58 +++++++++++ apps/desktop/src/stores/connectionStore.ts | 18 ++-- apps/desktop/src/types/database.ts | 1 + crates/dbx-core/src/agent_connection.rs | 1 + crates/dbx-core/src/cloud_sync.rs | 3 + crates/dbx-core/src/connection.rs | 1 + crates/dbx-core/src/connection_secrets.rs | 1 + crates/dbx-core/src/db/agent_driver.rs | 6 +- crates/dbx-core/src/db/postgres.rs | 67 +++++++++---- crates/dbx-core/src/db/redis_driver.rs | 1 + crates/dbx-core/src/models/connection.rs | 6 ++ crates/dbx-core/src/mq/config.rs | 1 + crates/dbx-core/src/mq/service.rs | 1 + crates/dbx-core/src/nacos/config.rs | 1 + crates/dbx-core/src/nacos/service.rs | 2 + crates/dbx-core/src/production_safety.rs | 1 + crates/dbx-core/src/query.rs | 2 + crates/dbx-core/src/schema.rs | 17 ++-- crates/dbx-core/src/schema/normalization.rs | 1 + crates/dbx-core/src/storage.rs | 2 + crates/dbx-core/src/transfer.rs | 1 + .../tests/database_export_prefetch.rs | 1 + .../live_postgres_query_result_export.rs | 1 + .../dbx-core/tests/live_postgres_transfer.rs | 1 + .../tests/live_sqlserver_completion.rs | 1 + .../live_sqlserver_query_result_export.rs | 1 + crates/dbx-web/src/routes/connection.rs | 1 + src-tauri/src/commands/connection.rs | 1 + 44 files changed, 422 insertions(+), 47 deletions(-) create mode 100644 apps/desktop/src/lib/__tests__/database/visibleDatabases.spec.ts diff --git a/agents/drivers/kingbase-go/kingbase_metadata.go b/agents/drivers/kingbase-go/kingbase_metadata.go index 51381ee39..c57e976d5 100644 --- a/agents/drivers/kingbase-go/kingbase_metadata.go +++ b/agents/drivers/kingbase-go/kingbase_metadata.go @@ -215,13 +215,27 @@ func (s *server) listDatabases() ([]databaseInfo, error) { return []databaseInfo{{Name: s.params.Database}}, nil } -func (s *server) listSchemas(visible []string) ([]string, error) { - query := "SELECT nspname FROM sys_catalog.sys_namespace WHERE nspname NOT LIKE 'sys_temp_%' AND nspname NOT LIKE 'sys_toast_temp_%' ORDER BY nspname" - if s.mode.postgresCatalog { - query = "SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname NOT LIKE 'pg_temp_%' AND nspname NOT LIKE 'pg_toast_temp_%' ORDER BY nspname" - } else if s.mode.mysqlCompat { - query = kingbaseMySQLCompatListSchemasSQL +func kingbaseListSchemasSQL(mode kingbaseMode, showSystemSchemas bool) string { + if mode.mysqlCompat { + if showSystemSchemas { + return "SELECT schema_name FROM information_schema.schemata ORDER BY schema_name" + } + return kingbaseMySQLCompatListSchemasSQL } + if mode.postgresCatalog { + if showSystemSchemas { + return "SELECT nspname FROM pg_catalog.pg_namespace ORDER BY nspname" + } + return "SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname NOT LIKE 'pg_temp_%' AND nspname NOT LIKE 'pg_toast_temp_%' ORDER BY nspname" + } + if showSystemSchemas { + return "SELECT nspname FROM sys_catalog.sys_namespace ORDER BY nspname" + } + return "SELECT nspname FROM sys_catalog.sys_namespace WHERE nspname NOT LIKE 'sys_temp_%' AND nspname NOT LIKE 'sys_toast_temp_%' ORDER BY nspname" +} + +func (s *server) listSchemas(visible []string, showSystemSchemas bool) ([]string, error) { + query := kingbaseListSchemasSQL(s.mode, showSystemSchemas) rows, err := s.metadataQuery(query) if err != nil { return nil, err @@ -383,7 +397,7 @@ func (s *server) completionAssistantSearch(request completionAssistantRequest) ( } else { schemas := []string{request.Schema} if request.GlobalSearch { - visible, err := s.listSchemas(nil) + visible, err := s.listSchemas(nil, false) if err != nil { return completionAssistantResponse{}, err } diff --git a/agents/drivers/kingbase-go/main.go b/agents/drivers/kingbase-go/main.go index 79cf709af..530b772ac 100644 --- a/agents/drivers/kingbase-go/main.go +++ b/agents/drivers/kingbase-go/main.go @@ -367,7 +367,7 @@ func (s *server) dispatch(method string, params map[string]json.RawMessage) (any result, err := s.listDatabases() return result, false, err case "list_schemas": - result, err := s.listSchemas(stringSliceParam(params, "visible_schemas")) + result, err := s.listSchemas(stringSliceParam(params, "visible_schemas"), boolParam(params, "show_system_schemas")) return result, false, err case "list_tables": result, err := s.listTables(stringParam(params, "schema"), metadataListConstraintsFromParams(params)) @@ -1138,6 +1138,14 @@ func intParam(params map[string]json.RawMessage, key string) int { return value } +func boolParam(params map[string]json.RawMessage, key string) bool { + var value bool + if raw, ok := params[key]; ok { + _ = json.Unmarshal(raw, &value) + } + return value +} + func stringSliceParam(params map[string]json.RawMessage, key string) []string { var values []string if json.Unmarshal(params[key], &values) == nil { diff --git a/agents/drivers/kingbase-go/main_test.go b/agents/drivers/kingbase-go/main_test.go index 3f75cebc6..9ae68430c 100644 --- a/agents/drivers/kingbase-go/main_test.go +++ b/agents/drivers/kingbase-go/main_test.go @@ -706,6 +706,24 @@ func TestMySQLCompatSchemaQueryKeepsUserSchemasWithSystemLikeNames(t *testing.T) } } +func TestListSchemasQueryIncludesSystemSchemasWhenEnabled(t *testing.T) { + for _, mode := range []kingbaseMode{{}, {postgresCatalog: true}, {mysqlCompat: true}} { + query := kingbaseListSchemasSQL(mode, true) + if strings.Contains(query, "NOT LIKE") || strings.Contains(query, "<>") { + t.Fatalf("show-system query must not filter schemas: %s", query) + } + } +} + +func TestListSchemasQueryKeepsDefaultTemporarySchemaFilters(t *testing.T) { + for _, mode := range []kingbaseMode{{}, {postgresCatalog: true}} { + query := kingbaseListSchemasSQL(mode, false) + if !strings.Contains(query, "temp_%") { + t.Fatalf("default query must keep temporary schema filters: %s", query) + } + } +} + func TestMetadataNormalizationHelpers(t *testing.T) { if normalizeTableType("BASE TABLE") != "TABLE" { t.Fatal("BASE TABLE was not normalized") diff --git a/apps/desktop/src/components/connection/ConnectionDialog.vue b/apps/desktop/src/components/connection/ConnectionDialog.vue index 17b72e3da..1e1f9af97 100644 --- a/apps/desktop/src/components/connection/ConnectionDialog.vue +++ b/apps/desktop/src/components/connection/ConnectionDialog.vue @@ -255,6 +255,7 @@ const defaultForm = (): ConnectionForm => ({ external_config: undefined, init_script: undefined, read_only: false, + show_system_schemas: false, is_production: false, production_databases: [], visible_databases: undefined, @@ -1994,6 +1995,7 @@ watch( attached_databases: config.attached_databases || [], init_script: config.init_script, read_only: config.read_only || false, + show_system_schemas: config.show_system_schemas || false, is_production: config.is_production || false, production_databases: config.production_databases || [], visible_databases: config.visible_databases, @@ -3391,6 +3393,7 @@ function connectionConfigForSubmit(id: string, generatedName = ""): ConnectionCo } else { config.visible_databases = Array.isArray(config.visible_databases) && config.visible_databases.length > 0 ? config.visible_databases : undefined; } + if (!config.show_system_schemas) config.show_system_schemas = undefined; if (config.visible_schemas && Object.keys(config.visible_schemas).length === 0) config.visible_schemas = undefined; if (config.agent_java_options && config.agent_java_options.length === 0) config.agent_java_options = undefined; return config as ConnectionConfig; @@ -6557,6 +6560,13 @@ function openExternalUrl(url: string) { {{ t("connection.readOnlyHint") }} +
+ + +