From 5d89e012476f0256b41684d9bf354c3c3ceb8d05 Mon Sep 17 00:00:00 2001 From: zipg Date: Wed, 5 Aug 2026 15:52:54 +0800 Subject: [PATCH] fix(kingbase): show connectable custom template databases --- .../drivers/kingbase-go/kingbase_metadata.go | 9 ++++- agents/drivers/kingbase-go/main_test.go | 40 ++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/agents/drivers/kingbase-go/kingbase_metadata.go b/agents/drivers/kingbase-go/kingbase_metadata.go index bbe19eae0..d8fa77f6e 100644 --- a/agents/drivers/kingbase-go/kingbase_metadata.go +++ b/agents/drivers/kingbase-go/kingbase_metadata.go @@ -16,6 +16,11 @@ import ( const metadataTimeout = 15 * time.Second +const ( + kingbaseListDatabasesSQL = "SELECT datname FROM sys_catalog.sys_database WHERE datallowconn AND LOWER(datname) NOT IN ('template0', 'template1') ORDER BY datname" + kingbaseListDatabasesPostgresSQL = "SELECT datname FROM pg_catalog.pg_database WHERE datallowconn AND LOWER(datname) NOT IN ('template0', 'template1') ORDER BY datname" +) + // Escape '_' so only Kingbase internal SYS_/XLOG_ prefixes are hidden; names // such as SYSTEMS and SYSLOG may be user-created schemas in MySQL mode. const kingbaseMySQLCompatListSchemasSQL = `SELECT schema_name FROM information_schema.schemata WHERE UPPER(schema_name) <> 'INFORMATION_SCHEMA' AND UPPER(schema_name) NOT LIKE 'SYS\_%' ESCAPE '\' AND UPPER(schema_name) NOT LIKE 'XLOG\_%' ESCAPE '\' ORDER BY schema_name` @@ -191,8 +196,8 @@ func (s *server) connectionInfo() (map[string]any, error) { func (s *server) listDatabases() ([]databaseInfo, error) { queries := []string{ - "SELECT datname FROM sys_catalog.sys_database WHERE NOT datistemplate AND datallowconn ORDER BY datname", - "SELECT datname FROM pg_catalog.pg_database WHERE NOT datistemplate AND datallowconn ORDER BY datname", + kingbaseListDatabasesSQL, + kingbaseListDatabasesPostgresSQL, "SELECT current_database()", } for _, query := range queries { diff --git a/agents/drivers/kingbase-go/main_test.go b/agents/drivers/kingbase-go/main_test.go index ed0f31c25..d1ce5339e 100644 --- a/agents/drivers/kingbase-go/main_test.go +++ b/agents/drivers/kingbase-go/main_test.go @@ -1006,12 +1006,48 @@ func TestMetadataNormalizationHelpers(t *testing.T) { } } +func TestListDatabasesKeepsConnectableCustomTemplates(t *testing.T) { + for _, query := range []string{kingbaseListDatabasesSQL, kingbaseListDatabasesPostgresSQL} { + lowerQuery := strings.ToLower(query) + if !strings.Contains(lowerQuery, "where datallowconn") { + t.Fatalf("database query must keep the connectable filter: %s", query) + } + if strings.Contains(lowerQuery, "not datistemplate") { + t.Fatalf("database query must not hide connectable custom templates: %s", query) + } + if !strings.Contains(lowerQuery, "lower(datname) not in ('template0', 'template1')") { + t.Fatalf("database query must hide only the standard template databases: %s", query) + } + if strings.Contains(lowerQuery, "'template2'") { + t.Fatalf("database query must keep a connectable database named template2: %s", query) + } + } + + state := &metadataDriverState{query: func(query string) (driver.Rows, error) { + if query != kingbaseListDatabasesSQL { + return nil, errors.New("unexpected query: " + query) + } + return &valueRows{columns: []string{"datname"}, rows: [][]driver.Value{{"JA_SICP_GEOSMARTER"}}}, nil + }} + server := newServer() + server.db = openMetadataDB(t, state) + server.params.Database = "configured" + + databases, err := server.listDatabases() + if err != nil { + t.Fatal(err) + } + if len(databases) != 1 || databases[0].Name != "JA_SICP_GEOSMARTER" { + t.Fatalf("unexpected databases: %#v", databases) + } +} + func TestListDatabasesFallsBackToPostgresCatalog(t *testing.T) { state := &metadataDriverState{query: func(query string) (driver.Rows, error) { switch { - case strings.Contains(query, "sys_catalog.sys_database"): + case query == kingbaseListDatabasesSQL: return nil, errors.New("sys catalog unavailable") - case strings.Contains(query, "pg_catalog.pg_database"): + case query == kingbaseListDatabasesPostgresSQL: return &valueRows{columns: []string{"datname"}, rows: [][]driver.Value{{"app"}, {"test"}}}, nil default: return nil, errors.New("unexpected query: " + query)