From 737896627a67aa5de2a533dffd08e888f4226206 Mon Sep 17 00:00:00 2001 From: jonclex Date: Wed, 15 Apr 2026 10:06:44 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(mysql):=20=E8=A1=A8=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=8E=92=E9=99=A4=E8=A7=86=E5=9B=BE=20refs=20bug#375?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/db/mariadb_impl.go | 7 +++++-- internal/db/mysql_impl.go | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/internal/db/mariadb_impl.go b/internal/db/mariadb_impl.go index c13e83b..e2f59e0 100644 --- a/internal/db/mariadb_impl.go +++ b/internal/db/mariadb_impl.go @@ -185,9 +185,12 @@ func (m *MariaDB) GetDatabases() ([]string, error) { } func (m *MariaDB) GetTables(dbName string) ([]string, error) { - query := "SHOW TABLES" + query := "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME" if dbName != "" { - query = fmt.Sprintf("SHOW TABLES FROM `%s`", dbName) + query = fmt.Sprintf( + "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = '%s' AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME", + strings.ReplaceAll(dbName, "'", "''"), + ) } data, _, err := m.Query(query) diff --git a/internal/db/mysql_impl.go b/internal/db/mysql_impl.go index d93e1f1..0e9071f 100644 --- a/internal/db/mysql_impl.go +++ b/internal/db/mysql_impl.go @@ -424,9 +424,12 @@ func (m *MySQLDB) GetDatabases() ([]string, error) { } func (m *MySQLDB) GetTables(dbName string) ([]string, error) { - query := "SHOW TABLES" + query := "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME" if dbName != "" { - query = fmt.Sprintf("SHOW TABLES FROM `%s`", dbName) + query = fmt.Sprintf( + "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = '%s' AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME", + strings.ReplaceAll(dbName, "'", "''"), + ) } data, _, err := m.Query(query) From c631feef91fbaa499850af4252073236d7d0d161 Mon Sep 17 00:00:00 2001 From: jonclex Date: Wed, 15 Apr 2026 10:27:22 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(ui):=20=E8=A1=A8=E6=A6=82=E8=A7=88?= =?UTF-8?q?=E6=8E=92=E9=99=A4=E8=A7=86=E5=9B=BE=20refs=20bug#375?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/TableOverview.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/TableOverview.tsx b/frontend/src/components/TableOverview.tsx index 6b07484..5672be6 100644 --- a/frontend/src/components/TableOverview.tsx +++ b/frontend/src/components/TableOverview.tsx @@ -55,10 +55,23 @@ const getMetadataDialect = (connType: string, driver?: string): string => { }; const buildTableStatusSQL = (dialect: string, dbName: string, schemaName?: string): string => { - const escapeLiteral = (s: string) => s.replace(/'/g, "''"); - switch (dialect) { + const escapeLiteral = (s: string) => s.replace(/'/g, "''"); + switch (dialect) { case 'mysql': - return `SHOW TABLE STATUS FROM \`${dbName.replace(/`/g, '``')}\``; + return ` +SELECT + TABLE_NAME AS table_name, + TABLE_COMMENT AS table_comment, + TABLE_ROWS AS table_rows, + DATA_LENGTH AS data_length, + INDEX_LENGTH AS index_length, + ENGINE AS engine, + CREATE_TIME AS create_time, + UPDATE_TIME AS update_time +FROM information_schema.tables +WHERE table_schema = '${escapeLiteral(dbName)}' + AND table_type = 'BASE TABLE' +ORDER BY table_name`; case 'postgres': case 'kingbase': case 'vastbase': From 9b50e9c9c8e1bb9653bd953a77e9e9df2be7f04e Mon Sep 17 00:00:00 2001 From: jonclex Date: Wed, 15 Apr 2026 14:42:45 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(custom+mysql):CustomDB(driver=3Dmysql)?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=B2=A1=E6=9C=89=E5=90=8C=E6=AD=A5=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8Ccustom=E9=93=BE=E6=8E=A5=E6=89=93=E5=BC=80?= =?UTF-8?q?=E6=97=B6schema=E6=8A=A5=E9=94=99=EF=BC=8C=E5=8F=8C=E5=87=BB?= =?UTF-8?q?=E8=A1=A8=E6=9F=A5=E8=AF=A2=E6=8A=A5=E9=94=99=20refs=20bug#385?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/DataGrid.tsx | 6 ++-- frontend/src/components/DataViewer.tsx | 8 +++--- internal/db/custom_impl.go | 39 ++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index ce4a380..896dc76 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -31,7 +31,7 @@ import { v4 as generateUuid } from 'uuid'; import 'react-resizable/css/styles.css'; import { buildOrderBySQL, buildPaginatedSelectSQL, buildWhereSQL, escapeLiteral, hasExplicitSort, quoteIdentPart, quoteQualifiedIdent, withSortBufferTuningSQL, type FilterCondition } from '../utils/sql'; import { isMacLikePlatform, normalizeOpacityForPlatform, resolveAppearanceValues } from '../utils/appearance'; -import { getDataSourceCapabilities } from '../utils/dataSourceCapabilities'; +import { getDataSourceCapabilities, resolveDataSourceType } from '../utils/dataSourceCapabilities'; import { buildRpcConnectionConfig } from '../utils/connectionRpcConfig'; import { resolveDataTableColumnWidth, @@ -4002,7 +4002,7 @@ const DataGrid: React.FC = ({ return; } - const dbType = config.type || ''; + const dbType = resolveDataSourceType(config); const pkWhere = buildPkWhereSql(records, dbType); if (!pkWhere) { await exportData(records, format); @@ -4071,7 +4071,7 @@ const DataGrid: React.FC = ({ return; } - const sql = buildCurrentPageSql(config.type || ''); + const sql = buildCurrentPageSql(resolveDataSourceType(config)); if (!sql) { await exportData(displayData, format); return; diff --git a/frontend/src/components/DataViewer.tsx b/frontend/src/components/DataViewer.tsx index e841482..bcdf1bf 100644 --- a/frontend/src/components/DataViewer.tsx +++ b/frontend/src/components/DataViewer.tsx @@ -7,7 +7,7 @@ import DataGrid, { GONAVI_ROW_KEY } from './DataGrid'; import { buildOrderBySQL, buildPaginatedSelectSQL, buildWhereSQL, hasExplicitSort, quoteIdentPart, quoteQualifiedIdent, withSortBufferTuningSQL, type FilterCondition } from '../utils/sql'; import { buildMongoCountCommand, buildMongoFilter, buildMongoFindCommand, buildMongoSort } from '../utils/mongodb'; import { buildOracleApproximateTotalSql, parseApproximateTableCountRow, resolveApproximateTableCountStrategy } from '../utils/approximateTableCount'; -import { getDataSourceCapabilities } from '../utils/dataSourceCapabilities'; +import { getDataSourceCapabilities, resolveDataSourceType } from '../utils/dataSourceCapabilities'; import { resolveDataViewerAutoFetchAction } from '../utils/dataViewerAutoFetch'; import { buildRpcConnectionConfig } from '../utils/connectionRpcConfig'; @@ -396,7 +396,7 @@ const DataViewer: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAct ssh: conn.config.ssh || { host: "", port: 22, user: "", password: "", keyPath: "" } }; - const dbType = config.type || ''; + const dbType = resolveDataSourceType(config); const dbTypeLower = String(dbType || '').trim().toLowerCase(); const isMySQLFamily = dbTypeLower === 'mysql' || dbTypeLower === 'mariadb' || dbTypeLower === 'diros'; @@ -855,7 +855,7 @@ const DataViewer: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAct const exportSqlWithFilter = useMemo(() => { const tableName = String(tab.tableName || '').trim(); - const dbType = String(currentConnConfig?.type || '').trim(); + const dbType = resolveDataSourceType(currentConnConfig); if (!tableName || !dbType) return ''; const whereSQL = buildWhereSQL(dbType, filterConditions); @@ -869,7 +869,7 @@ const DataViewer: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAct sql = withSortBufferTuningSQL(normalizedType, sql, 32 * 1024 * 1024); } return sql; - }, [tab.tableName, currentConnConfig?.type, filterConditions, sortInfo, pkColumns]); + }, [tab.tableName, currentConnConfig?.type, currentConnConfig?.driver, filterConditions, sortInfo, pkColumns]); useEffect(() => { const action = resolveDataViewerAutoFetchAction({ diff --git a/internal/db/custom_impl.go b/internal/db/custom_impl.go index 8d80895..d4fe312 100644 --- a/internal/db/custom_impl.go +++ b/internal/db/custom_impl.go @@ -114,6 +114,38 @@ func (c *CustomDB) GetDatabases() ([]string, error) { // We'll try a generic query or return empty. // Users using custom might know their DB context is single. + if c.driver == "mysql" { + data, _, err := c.Query("SHOW DATABASES") + if err == nil { + var dbs []string + for _, row := range data { + for _, v := range row { + name := strings.TrimSpace(fmt.Sprintf("%v", v)) + if name != "" { + dbs = append(dbs, name) + } + break + } + } + if len(dbs) > 0 { + return dbs, nil + } + } + + // Fallback for restricted accounts: at least expose current database. + data, _, fallbackErr := c.Query("SELECT DATABASE() AS database_name") + if fallbackErr == nil { + for _, row := range data { + for _, v := range row { + name := strings.TrimSpace(fmt.Sprintf("%v", v)) + if name != "" && !strings.EqualFold(name, "") && !strings.EqualFold(name, "null") { + return []string{name}, nil + } + } + } + } + } + // Best effort: return []string{}, nil } @@ -123,9 +155,12 @@ func (c *CustomDB) GetTables(dbName string) ([]string, error) { query := "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'" // If mysql-like if c.driver == "mysql" { - query = "SHOW TABLES" + query = "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME" if dbName != "" { - query = fmt.Sprintf("SHOW TABLES FROM `%s`", dbName) + query = fmt.Sprintf( + "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = '%s' AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME", + strings.ReplaceAll(dbName, "'", "''"), + ) } } else if c.driver == "postgres" || c.driver == "kingbase" { query = `