From eaa76d8f04a1f6aec243cc0cbe8d7bb54144f5d1 Mon Sep 17 00:00:00 2001 From: Syngnat Date: Fri, 20 Mar 2026 11:19:08 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(connection):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=9E=E6=8E=A5=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BF=AE=E5=A4=8D=E8=BE=BE?= =?UTF-8?q?=E6=A2=A6=E6=95=B0=E6=8D=AE=E5=BA=93=E5=88=97=E8=A1=A8=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 图标组件:新增 DatabaseIcons.tsx,10 种品牌 SVG logo + 7 种彩色文字标签覆盖全部数据源 - 品牌资源:下载 MySQL/PG/Redis/MongoDB/ClickHouse/SQLite/MariaDB/Doris/Sphinx/DuckDB 的 SVG(CC0 许可) - 类型扩展:SavedConnection 新增 iconType/iconColor 支持自定义图标和颜色 - 外观配置:ConnectionModal 新增"外观"配置区(图标选择器 + 14 色选择器 + 预览面板) - 数据源选择:Step1 数据源类型卡片全部统一为品牌图标 - 达梦修复:dameng_metadata.go 增加原生 SQL 查询和诊断日志,改善数据库列表获取 - refs #114 - refs #266 --- frontend/public/db-icons/clickhouse.svg | 1 + frontend/public/db-icons/diros.svg | 1 + frontend/public/db-icons/duckdb.svg | 1 + frontend/public/db-icons/mariadb.svg | 1 + frontend/public/db-icons/mongodb.svg | 1 + frontend/public/db-icons/mysql.svg | 1 + frontend/public/db-icons/postgres.svg | 1 + frontend/public/db-icons/redis.svg | 1 + frontend/public/db-icons/sphinx.svg | 1 + frontend/public/db-icons/sqlite.svg | 1 + frontend/src/components/ConnectionModal.tsx | 140 ++++++++++--- frontend/src/components/DatabaseIcons.tsx | 217 ++++++++++++++++++++ frontend/src/components/Sidebar.tsx | 5 +- frontend/src/types.ts | 2 + internal/db/dameng_metadata.go | 14 +- 15 files changed, 362 insertions(+), 26 deletions(-) create mode 100644 frontend/public/db-icons/clickhouse.svg create mode 100644 frontend/public/db-icons/diros.svg create mode 100644 frontend/public/db-icons/duckdb.svg create mode 100644 frontend/public/db-icons/mariadb.svg create mode 100644 frontend/public/db-icons/mongodb.svg create mode 100644 frontend/public/db-icons/mysql.svg create mode 100644 frontend/public/db-icons/postgres.svg create mode 100644 frontend/public/db-icons/redis.svg create mode 100644 frontend/public/db-icons/sphinx.svg create mode 100644 frontend/public/db-icons/sqlite.svg create mode 100644 frontend/src/components/DatabaseIcons.tsx diff --git a/frontend/public/db-icons/clickhouse.svg b/frontend/public/db-icons/clickhouse.svg new file mode 100644 index 0000000..689aca3 --- /dev/null +++ b/frontend/public/db-icons/clickhouse.svg @@ -0,0 +1 @@ +ClickHouse \ No newline at end of file diff --git a/frontend/public/db-icons/diros.svg b/frontend/public/db-icons/diros.svg new file mode 100644 index 0000000..7582151 --- /dev/null +++ b/frontend/public/db-icons/diros.svg @@ -0,0 +1 @@ +Apache Doris \ No newline at end of file diff --git a/frontend/public/db-icons/duckdb.svg b/frontend/public/db-icons/duckdb.svg new file mode 100644 index 0000000..feaab85 --- /dev/null +++ b/frontend/public/db-icons/duckdb.svg @@ -0,0 +1 @@ +DuckDB \ No newline at end of file diff --git a/frontend/public/db-icons/mariadb.svg b/frontend/public/db-icons/mariadb.svg new file mode 100644 index 0000000..fe068e7 --- /dev/null +++ b/frontend/public/db-icons/mariadb.svg @@ -0,0 +1 @@ +MariaDB \ No newline at end of file diff --git a/frontend/public/db-icons/mongodb.svg b/frontend/public/db-icons/mongodb.svg new file mode 100644 index 0000000..a4c8174 --- /dev/null +++ b/frontend/public/db-icons/mongodb.svg @@ -0,0 +1 @@ +MongoDB \ No newline at end of file diff --git a/frontend/public/db-icons/mysql.svg b/frontend/public/db-icons/mysql.svg new file mode 100644 index 0000000..195caad --- /dev/null +++ b/frontend/public/db-icons/mysql.svg @@ -0,0 +1 @@ +MySQL \ No newline at end of file diff --git a/frontend/public/db-icons/postgres.svg b/frontend/public/db-icons/postgres.svg new file mode 100644 index 0000000..dcf75b7 --- /dev/null +++ b/frontend/public/db-icons/postgres.svg @@ -0,0 +1 @@ +PostgreSQL \ No newline at end of file diff --git a/frontend/public/db-icons/redis.svg b/frontend/public/db-icons/redis.svg new file mode 100644 index 0000000..fc47db8 --- /dev/null +++ b/frontend/public/db-icons/redis.svg @@ -0,0 +1 @@ +Redis \ No newline at end of file diff --git a/frontend/public/db-icons/sphinx.svg b/frontend/public/db-icons/sphinx.svg new file mode 100644 index 0000000..ca57775 --- /dev/null +++ b/frontend/public/db-icons/sphinx.svg @@ -0,0 +1 @@ +Sphinx \ No newline at end of file diff --git a/frontend/public/db-icons/sqlite.svg b/frontend/public/db-icons/sqlite.svg new file mode 100644 index 0000000..a776ea1 --- /dev/null +++ b/frontend/public/db-icons/sqlite.svg @@ -0,0 +1 @@ +SQLite \ No newline at end of file diff --git a/frontend/src/components/ConnectionModal.tsx b/frontend/src/components/ConnectionModal.tsx index f7e13b4..037d76b 100644 --- a/frontend/src/components/ConnectionModal.tsx +++ b/frontend/src/components/ConnectionModal.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect, useRef, useMemo } from 'react'; import { Modal, Form, Input, InputNumber, Button, message, Checkbox, Divider, Select, Alert, Card, Row, Col, Typography, Collapse, Space, Table, Tag } from 'antd'; -import { DatabaseOutlined, ConsoleSqlOutlined, FileTextOutlined, CloudServerOutlined, AppstoreAddOutlined, CloudOutlined, CheckCircleFilled, CloseCircleFilled, LinkOutlined, EditOutlined, AppstoreOutlined } from '@ant-design/icons'; +import { DatabaseOutlined, ConsoleSqlOutlined, FileTextOutlined, CloudServerOutlined, AppstoreAddOutlined, CloudOutlined, CheckCircleFilled, CloseCircleFilled, LinkOutlined, EditOutlined, AppstoreOutlined, BgColorsOutlined } from '@ant-design/icons'; +import { getDbIcon, getDbDefaultColor, getDbIconLabel, DB_ICON_TYPES, PRESET_ICON_COLORS } from './DatabaseIcons'; import { useStore } from '../store'; import { buildOverlayWorkbenchTheme } from '../utils/overlayWorkbenchTheme'; import { normalizeOpacityForPlatform, resolveAppearanceValues } from '../utils/appearance'; @@ -105,7 +106,9 @@ const ConnectionModal: React.FC<{ const [dbType, setDbType] = useState('mysql'); const [step, setStep] = useState(1); // 1: Select Type, 2: Configure const [activeGroup, setActiveGroup] = useState(0); // Active category index in step 1 - const [activeConfigSection, setActiveConfigSection] = useState<'basic' | 'network'>('basic'); + const [activeConfigSection, setActiveConfigSection] = useState<'basic' | 'network' | 'appearance'>('basic'); + const [customIconType, setCustomIconType] = useState(undefined); + const [customIconColor, setCustomIconColor] = useState(undefined); const [activeNetworkConfig, setActiveNetworkConfig] = useState<'ssl' | 'ssh' | 'proxy' | 'httpTunnel'>('ssl'); const [testResult, setTestResult] = useState<{ type: 'success' | 'error', message: string } | null>(null); const [testErrorLogOpen, setTestErrorLogOpen] = useState(false); @@ -1061,6 +1064,8 @@ const ConnectionModal: React.FC<{ setRedisDbList([]); setMongoMembers([]); setUriFeedback(null); + setCustomIconType(undefined); + setCustomIconColor(undefined); setTypeSelectWarning(null); setDriverStatusLoaded(false); void refreshDriverStatus(); @@ -1146,6 +1151,8 @@ const ConnectionModal: React.FC<{ mongoReplicaPassword: config.mongoReplicaPassword || '' }); setUseSSL(!!config.useSSL); + setCustomIconType(initialValues.iconType); + setCustomIconColor(initialValues.iconColor); setUseSSH(config.useSSH || false); setUseProxy(hasProxy); setUseHttpTunnel(hasHttpTunnel); @@ -1212,7 +1219,9 @@ const ConnectionModal: React.FC<{ name: values.name || (isFileDatabaseType(values.type) ? (values.type === 'duckdb' ? 'DuckDB DB' : 'SQLite DB') : (values.type === 'redis' ? `Redis ${displayHost}` : displayHost)), config: config, includeDatabases: values.includeDatabases, - includeRedisDatabases: isRedisType ? values.includeRedisDatabases : undefined + includeRedisDatabases: isRedisType ? values.includeRedisDatabases : undefined, + iconType: customIconType, + iconColor: customIconColor, }; if (initialValues) { @@ -1735,32 +1744,32 @@ const ConnectionModal: React.FC<{ const dbTypeGroups = [ { label: '关系型数据库', items: [ - { key: 'mysql', name: 'MySQL', icon: }, - { key: 'mariadb', name: 'MariaDB', icon: }, - { key: 'diros', name: 'Doris', icon: }, - { key: 'sphinx', name: 'Sphinx', icon: }, - { key: 'clickhouse', name: 'ClickHouse', icon: }, - { key: 'postgres', name: 'PostgreSQL', icon: }, - { key: 'sqlserver', name: 'SQL Server', icon: }, - { key: 'sqlite', name: 'SQLite', icon: }, - { key: 'duckdb', name: 'DuckDB', icon: }, - { key: 'oracle', name: 'Oracle', icon: }, + { key: 'mysql', name: 'MySQL', icon: getDbIcon('mysql', undefined, 36) }, + { key: 'mariadb', name: 'MariaDB', icon: getDbIcon('mariadb', undefined, 36) }, + { key: 'diros', name: 'Doris', icon: getDbIcon('diros', undefined, 36) }, + { key: 'sphinx', name: 'Sphinx', icon: getDbIcon('sphinx', undefined, 36) }, + { key: 'clickhouse', name: 'ClickHouse', icon: getDbIcon('clickhouse', undefined, 36) }, + { key: 'postgres', name: 'PostgreSQL', icon: getDbIcon('postgres', undefined, 36) }, + { key: 'sqlserver', name: 'SQL Server', icon: getDbIcon('sqlserver', undefined, 36) }, + { key: 'sqlite', name: 'SQLite', icon: getDbIcon('sqlite', undefined, 36) }, + { key: 'duckdb', name: 'DuckDB', icon: getDbIcon('duckdb', undefined, 36) }, + { key: 'oracle', name: 'Oracle', icon: getDbIcon('oracle', undefined, 36) }, ]}, { label: '国产数据库', items: [ - { key: 'dameng', name: 'Dameng (达梦)', icon: }, - { key: 'kingbase', name: 'Kingbase (人大金仓)', icon: }, - { key: 'highgo', name: 'HighGo (瀚高)', icon: }, - { key: 'vastbase', name: 'Vastbase (海量)', icon: }, + { key: 'dameng', name: 'Dameng (达梦)', icon: getDbIcon('dameng', undefined, 36) }, + { key: 'kingbase', name: 'Kingbase (人大金仓)', icon: getDbIcon('kingbase', undefined, 36) }, + { key: 'highgo', name: 'HighGo (瀚高)', icon: getDbIcon('highgo', undefined, 36) }, + { key: 'vastbase', name: 'Vastbase (海量)', icon: getDbIcon('vastbase', undefined, 36) }, ]}, { label: 'NoSQL', items: [ - { key: 'mongodb', name: 'MongoDB', icon: }, - { key: 'redis', name: 'Redis', icon: }, + { key: 'mongodb', name: 'MongoDB', icon: getDbIcon('mongodb', undefined, 36) }, + { key: 'redis', name: 'Redis', icon: getDbIcon('redis', undefined, 36) }, ]}, { label: '时序数据库', items: [ - { key: 'tdengine', name: 'TDengine', icon: }, + { key: 'tdengine', name: 'TDengine', icon: getDbIcon('tdengine', undefined, 36) }, ]}, { label: '其他', items: [ - { key: 'custom', name: 'Custom (自定义)', icon: }, + { key: 'custom', name: 'Custom (自定义)', icon: getDbIcon('custom', undefined, 36) }, ]}, ]; @@ -2512,16 +2521,101 @@ const ConnectionModal: React.FC<{ /> )} {(() => { - const sectionItems: Array<{ key: 'basic' | 'network'; title: string; description: string; icon: React.ReactNode }> = [ + const sectionItems: Array<{ key: 'basic' | 'network' | 'appearance'; title: string; description: string; icon: React.ReactNode }> = [ { key: 'basic', title: '基础信息', description: '名称、地址、认证、URI 与数据库范围', icon: }, ...(!isCustom && !isFileDb ? [{ key: 'network' as const, title: '网络与安全', description: 'SSL、SSH、代理与高级连接', icon: }] : []), + { key: 'appearance', title: '外观', description: '自定义图标与颜色', icon: }, ]; const resolvedSection = sectionItems.some((item) => item.key === activeConfigSection) ? activeConfigSection : sectionItems[0]?.key || 'basic'; + + const effectiveIconType = customIconType || dbType; + const effectiveIconColor = customIconColor || getDbDefaultColor(effectiveIconType); + + const appearanceSection = ( +
+
+
图标
+
+ {DB_ICON_TYPES.map((iconKey) => { + const isActive = effectiveIconType === iconKey; + return ( + + ); + })} +
+
+ 当前:{getDbIconLabel(effectiveIconType)} +
+
+
+
颜色
+
+ {PRESET_ICON_COLORS.map((presetColor) => { + const isActive = effectiveIconColor === presetColor; + return ( +
+
+
+
预览
+
+ {getDbIcon(effectiveIconType, effectiveIconColor, 24)} + {form.getFieldValue('name') || '连接名称'} +
+ {(customIconType || customIconColor) && ( + + )} +
+
+ ); + const currentSectionContent = resolvedSection === 'basic' ? baseInfoSection - : networkSecuritySection; + : resolvedSection === 'appearance' + ? appearanceSection + : networkSecuritySection; if (sectionItems.length <= 1) { return currentSectionContent; diff --git a/frontend/src/components/DatabaseIcons.tsx b/frontend/src/components/DatabaseIcons.tsx new file mode 100644 index 0000000..6d55fb2 --- /dev/null +++ b/frontend/src/components/DatabaseIcons.tsx @@ -0,0 +1,217 @@ +import React from 'react'; + +// ─── 公共接口 ─────────────────────────────────────────────── + +export interface DbIconProps { + size?: number; + color?: string; +} + +// ─── 默认色表 ─────────────────────────────────────────────── + +const DB_DEFAULT_COLORS: Record = { + mysql: '#00758F', + mariadb: '#003545', + postgres: '#336791', + redis: '#DC382D', + mongodb: '#47A248', + kingbase: '#1890FF', + dameng: '#E6002D', + oracle: '#F80000', + sqlserver: '#CC2927', + clickhouse: '#FFBF00', + sqlite: '#003B57', + duckdb: '#FFC107', + vastbase: '#0066CC', + highgo: '#00A86B', + tdengine: '#2962FF', + diros: '#0050B3', + sphinx: '#2F5D62', + custom: '#888888', +}; + +export const getDbDefaultColor = (type: string): string => + DB_DEFAULT_COLORS[type?.toLowerCase()] || DB_DEFAULT_COLORS.custom; + +// ─── 有品牌 SVG 文件的数据库类型(文件在 /db-icons/ 下) ──── + +const BRAND_SVG_TYPES = new Set([ + 'mysql', 'mariadb', 'postgres', 'redis', 'mongodb', 'clickhouse', 'sqlite', + 'diros', 'sphinx', 'duckdb', +]); + +/** 品牌 SVG 图标:用 加载 /db-icons/*.svg */ +const BrandSvgIcon: React.FC<{ type: string; size: number; color?: string }> = ({ type, size, color }) => { + const bgColor = color || getDbDefaultColor(type); + return ( + + {type} + + ); +}; + +// ─── 彩色标签图标(fallback) ────────────────────────────── + +/** 通用彩色标签:填充背景 + 白色粗体缩写 */ +const ColorBadge: React.FC<{ size: number; color: string; label: string }> = ({ size, color, label }) => { + const textSize = label.length <= 2 ? size * 0.48 : size * 0.38; + return ( + + + 2 ? -0.5 : 0} + > + {label} + + + ); +}; + +// ─── 各数据库图标 ─────────────────────────────────────────── + +// 有品牌 SVG 的数据库 +const MySQLIcon: React.FC = ({ size = 16, color }) => ( + +); +const MariaDBIcon: React.FC = ({ size = 16, color }) => ( + +); +const PostgresIcon: React.FC = ({ size = 16, color }) => ( + +); +const RedisIcon: React.FC = ({ size = 16, color }) => ( + +); +const MongoDBIcon: React.FC = ({ size = 16, color }) => ( + +); +const ClickHouseIcon: React.FC = ({ size = 16, color }) => ( + +); +const SQLiteIcon: React.FC = ({ size = 16, color }) => ( + +); + +// 无品牌 SVG → 彩色文字标签 +const OracleIcon: React.FC = ({ size = 16, color }) => ( + +); +const SQLServerIcon: React.FC = ({ size = 16, color }) => ( + +); +const DorisIcon: React.FC = ({ size = 16, color }) => ( + +); +const SphinxIcon: React.FC = ({ size = 16, color }) => ( + +); +const DuckDBIcon: React.FC = ({ size = 16, color }) => ( + +); +const KingBaseIcon: React.FC = ({ size = 16, color }) => ( + +); +const DamengIcon: React.FC = ({ size = 16, color }) => ( + +); +const VastBaseIcon: React.FC = ({ size = 16, color }) => ( + +); +const HighGoIcon: React.FC = ({ size = 16, color }) => ( + +); +const TDengineIcon: React.FC = ({ size = 16, color }) => ( + +); + +/** Custom — 齿轮图标 */ +const CustomIcon: React.FC = ({ size = 16, color }) => { + const c = color || DB_DEFAULT_COLORS.custom; + return ( + + + + + + ); +}; + +// ─── 图标注册表 ───────────────────────────────────────────── + +const DorisIconFallback: React.FC = ({ size = 16, color }) => ( + +); +const SphinxIconFallback: React.FC = ({ size = 16, color }) => ( + +); + +const DB_ICON_MAP: Record> = { + mysql: MySQLIcon, + mariadb: MariaDBIcon, + diros: DorisIcon, + sphinx: SphinxIcon, + postgres: PostgresIcon, + redis: RedisIcon, + mongodb: MongoDBIcon, + kingbase: KingBaseIcon, + dameng: DamengIcon, + oracle: OracleIcon, + sqlserver: SQLServerIcon, + clickhouse: ClickHouseIcon, + sqlite: SQLiteIcon, + duckdb: DuckDBIcon, + vastbase: VastBaseIcon, + highgo: HighGoIcon, + tdengine: TDengineIcon, + custom: CustomIcon, +}; + +/** 可选图标类型列表(用于图标选择器 UI) */ +export const DB_ICON_TYPES: string[] = [ + 'mysql', 'mariadb', 'postgres', 'redis', 'mongodb', + 'oracle', 'sqlserver', 'sqlite', 'duckdb', 'clickhouse', + 'kingbase', 'dameng', 'vastbase', 'highgo', 'tdengine', 'custom', +]; + +/** 该类型是否有品牌 SVG 文件 */ +export const hasBrandSvg = (type: string): boolean => BRAND_SVG_TYPES.has(type?.toLowerCase()); + +/** 获取数据库图标 React 节点 */ +export const getDbIcon = (type: string, color?: string, size?: number): React.ReactNode => { + const key = (type || 'custom').toLowerCase(); + const Component = DB_ICON_MAP[key] || CustomIcon; + return ; +}; + +/** 获取数据库图标显示名称(中文) */ +export const getDbIconLabel = (type: string): string => { + const labels: Record = { + mysql: 'MySQL', mariadb: 'MariaDB', postgres: 'PostgreSQL', + redis: 'Redis', mongodb: 'MongoDB', oracle: 'Oracle', + sqlserver: 'SQL Server', clickhouse: 'ClickHouse', sqlite: 'SQLite', + duckdb: 'DuckDB', kingbase: '金仓', dameng: '达梦', + vastbase: 'VastBase', highgo: '瀚高', tdengine: 'TDengine', + custom: '自定义', + }; + return labels[type?.toLowerCase()] || type; +}; + +/** 预设颜色列表 */ +export const PRESET_ICON_COLORS: string[] = [ + '#336791', '#00758F', '#DC382D', '#47A248', '#F80000', + '#CC2927', '#1890FF', '#E6002D', '#FFBF00', '#2962FF', + '#00A86B', '#0066CC', '#FF6B35', '#7C3AED', +]; diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index ae0a9e9..d0f4e47 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -35,6 +35,7 @@ import { Tree, message, Dropdown, MenuProps, Input, Button, Modal, Form, Badge, import { useStore } from '../store'; import { buildOverlayWorkbenchTheme } from '../utils/overlayWorkbenchTheme'; import { SavedConnection } from '../types'; +import { getDbIcon } from './DatabaseIcons'; import { DBGetDatabases, DBGetTables, DBQuery, DBShowCreateTable, ExportTable, OpenSQLFile, ExecuteSQLFile, CancelSQLFileExecution, CreateDatabase, RenameDatabase, DropDatabase, RenameTable, DropTable, DropView, DropFunction, RenameView } from '../../wailsjs/go/app/App'; import { EventsOn } from '../../wailsjs/runtime/runtime'; import { normalizeOpacityForPlatform, resolveAppearanceValues } from '../utils/appearance'; @@ -329,7 +330,7 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }> return { title: conn.name, key: conn.id, - icon: conn.config.type === 'redis' ? : , + icon: getDbIcon(conn.iconType || conn.config.type, conn.iconColor, 22), type: 'connection', dataRef: conn, isLeaf: false, @@ -3603,7 +3604,7 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }> } const statusBadge = node.type === 'connection' || node.type === 'database' ? ( - + ) : null; const displayTitle = String(node.title ?? ''); diff --git a/frontend/src/types.ts b/frontend/src/types.ts index d173baf..ea10867 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -72,6 +72,8 @@ export interface SavedConnection { config: ConnectionConfig; includeDatabases?: string[]; includeRedisDatabases?: number[]; // Redis databases to show (0-15) + iconType?: string; // 自定义图标类型(如 'mysql','postgres'),不填则取 config.type + iconColor?: string; // 自定义图标颜色(十六进制),不填则取类型默认色 } export interface ConnectionTag { diff --git a/internal/db/dameng_metadata.go b/internal/db/dameng_metadata.go index c963da1..b0f698b 100644 --- a/internal/db/dameng_metadata.go +++ b/internal/db/dameng_metadata.go @@ -4,9 +4,15 @@ import ( "fmt" "sort" "strings" + + "GoNavi-Wails/internal/logger" ) var damengDatabaseQueries = []string{ + // 优先使用达梦原生系统表 + "SELECT DISTINCT OBJECT_NAME AS DATABASE_NAME FROM SYS.SYSOBJECTS WHERE TYPE$ = 'SCH' AND OBJECT_NAME NOT IN ('SYS','SYSDBA','SYSAUDITOR','SYSSSO','CTISYS','__RECYCLE_USER__') ORDER BY OBJECT_NAME", + "SELECT SCHEMA_NAME AS DATABASE_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('SYS','SYSDBA','SYSAUDITOR','SYSSSO','CTISYS','INFORMATION_SCHEMA') ORDER BY SCHEMA_NAME", + // Oracle 兼容层 "SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS DATABASE_NAME FROM DUAL", "SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER') AS DATABASE_NAME FROM DUAL", "SELECT USERNAME AS DATABASE_NAME FROM USER_USERS", @@ -24,12 +30,14 @@ func collectDamengDatabaseNames(query damengQueryFunc) ([]string, error) { dbs := make([]string, 0, 64) var lastErr error - for _, q := range damengDatabaseQueries { + for idx, q := range damengDatabaseQueries { data, _, err := query(q) if err != nil { + logger.Warnf("达梦 GetDatabases 查询[%d]失败:%v(SQL: %.80s…)", idx, err, q) lastErr = err continue } + newCount := 0 for _, row := range data { name := getDamengRowString(row, "DATABASE_NAME", @@ -58,10 +66,14 @@ func collectDamengDatabaseNames(query damengQueryFunc) ([]string, error) { } seen[key] = struct{}{} dbs = append(dbs, name) + newCount++ } + logger.Infof("达梦 GetDatabases 查询[%d]成功:返回 %d 行,新增 %d 条(SQL: %.80s…)", idx, len(data), newCount, q) } + logger.Infof("达梦 GetDatabases 最终结果:共 %d 条数据库/schema", len(dbs)) if len(dbs) == 0 && lastErr != nil { + logger.Warnf("达梦 GetDatabases 所有查询均失败,返回最后错误:%v", lastErr) return nil, lastErr }