diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx
index 49458a5..427a49f 100644
--- a/frontend/src/components/DataGrid.tsx
+++ b/frontend/src/components/DataGrid.tsx
@@ -8,14 +8,19 @@ import { useStore } from '../store';
import { v4 as uuidv4 } from 'uuid';
import 'react-resizable/css/styles.css';
+// Normalize RFC3339-like datetime strings to `YYYY-MM-DD HH:mm:ss` for display/editing.
+const normalizeDateTimeString = (val: string) => {
+ const match = val.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})/);
+ if (!match) return val;
+ return `${match[1]} ${match[2]}`;
+};
+
// --- Helper: Format Value ---
const formatCellValue = (val: any) => {
if (val === null) return NULL;
if (typeof val === 'object') return JSON.stringify(val);
if (typeof val === 'string') {
- if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(val)) {
- return val.replace('T', ' ').replace(/\+.*$/, '').replace(/Z$/, '');
- }
+ return normalizeDateTimeString(val);
}
return String(val);
};
@@ -103,13 +108,15 @@ const EditableCell: React.FC = React.memo(({
const toggleEdit = () => {
setEditing(!editing);
- form.setFieldsValue({ [dataIndex]: record[dataIndex] });
+ const raw = record[dataIndex];
+ const initialValue = typeof raw === 'string' ? normalizeDateTimeString(raw) : raw;
+ form.setFieldsValue({ [dataIndex]: initialValue });
};
const save = async () => {
try {
if (!form) return;
- const values = await form.validateFields();
+ const values = await form.validateFields([dataIndex]);
toggleEdit();
handleSave({ ...record, ...values });
} catch (errInfo) {
@@ -278,6 +285,7 @@ const DataGrid: React.FC = ({
setModifiedRows({});
setDeletedRowKeys(new Set());
setSelectedRowKeys([]);
+ form.resetFields();
}, [tableName, dbName, connectionId]); // Reset on context change
const displayData = useMemo(() => {
diff --git a/frontend/src/components/DataViewer.tsx b/frontend/src/components/DataViewer.tsx
index fc4f0fd..db332a4 100644
--- a/frontend/src/components/DataViewer.tsx
+++ b/frontend/src/components/DataViewer.tsx
@@ -41,11 +41,18 @@ const DataViewer: React.FC<{ tab: TabData }> = ({ tab }) => {
ssh: conn.config.ssh || { host: "", port: 22, user: "", password: "", keyPath: "" }
};
- const quoteIdent = (ident: string) => {
+ const quoteIdentPart = (ident: string) => {
if (!ident) return ident;
if (config.type === 'mysql') return `\`${ident.replace(/`/g, '``')}\``;
return `"${ident.replace(/"/g, '""')}"`;
};
+ const quoteQualifiedIdent = (ident: string) => {
+ const raw = (ident || '').trim();
+ if (!raw) return raw;
+ const parts = raw.split('.').filter(Boolean);
+ if (parts.length <= 1) return quoteIdentPart(raw);
+ return parts.map(quoteIdentPart).join('.');
+ };
const escapeLiteral = (val: string) => val.replace(/'/g, "''");
const dbName = tab.dbName || '';
@@ -55,19 +62,19 @@ const DataViewer: React.FC<{ tab: TabData }> = ({ tab }) => {
filterConditions.forEach(cond => {
if (cond.column && cond.value) {
if (cond.op === 'LIKE') {
- whereParts.push(`${quoteIdent(cond.column)} LIKE '%${escapeLiteral(cond.value)}%'`);
+ whereParts.push(`${quoteIdentPart(cond.column)} LIKE '%${escapeLiteral(cond.value)}%'`);
} else {
- whereParts.push(`${quoteIdent(cond.column)} ${cond.op} '${escapeLiteral(cond.value)}'`);
+ whereParts.push(`${quoteIdentPart(cond.column)} ${cond.op} '${escapeLiteral(cond.value)}'`);
}
}
});
const whereSQL = whereParts.length > 0 ? `WHERE ${whereParts.join(' AND ')}` : "";
- const countSql = `SELECT COUNT(*) as total FROM ${quoteIdent(tableName)} ${whereSQL}`;
+ const countSql = `SELECT COUNT(*) as total FROM ${quoteQualifiedIdent(tableName)} ${whereSQL}`;
- let sql = `SELECT * FROM ${quoteIdent(tableName)} ${whereSQL}`;
+ let sql = `SELECT * FROM ${quoteQualifiedIdent(tableName)} ${whereSQL}`;
if (sortInfo && sortInfo.order) {
- sql += ` ORDER BY ${quoteIdent(sortInfo.columnKey)} ${sortInfo.order === 'ascend' ? 'ASC' : 'DESC'}`;
+ sql += ` ORDER BY ${quoteIdentPart(sortInfo.columnKey)} ${sortInfo.order === 'ascend' ? 'ASC' : 'DESC'}`;
}
const offset = (page - 1) * size;
sql += ` LIMIT ${size} OFFSET ${offset}`;
diff --git a/internal/app/db_context.go b/internal/app/db_context.go
new file mode 100644
index 0000000..684c7a3
--- /dev/null
+++ b/internal/app/db_context.go
@@ -0,0 +1,56 @@
+package app
+
+import (
+ "strings"
+
+ "GoNavi-Wails/internal/connection"
+)
+
+func normalizeRunConfig(config connection.ConnectionConfig, dbName string) connection.ConnectionConfig {
+ runConfig := config
+ name := strings.TrimSpace(dbName)
+ if name == "" {
+ return runConfig
+ }
+
+ switch strings.ToLower(strings.TrimSpace(config.Type)) {
+ case "mysql", "postgres", "kingbase":
+ // 这些类型的 dbName 表示“数据库”,需要写入连接配置以选择目标库。
+ runConfig.Database = name
+ case "dameng":
+ // 达梦使用 schema 参数,沿用现有行为:dbName 表示 schema。
+ runConfig.Database = name
+ default:
+ // oracle: dbName 表示 schema/owner,不能覆盖 config.Database(服务名)
+ // sqlite: 无需设置 Database
+ // custom: 语义不明确,避免污染缓存 key
+ }
+
+ return runConfig
+}
+
+func normalizeSchemaAndTable(config connection.ConnectionConfig, dbName string, tableName string) (string, string) {
+ rawTable := strings.TrimSpace(tableName)
+ rawDB := strings.TrimSpace(dbName)
+ if rawTable == "" {
+ return rawDB, rawTable
+ }
+
+ if parts := strings.SplitN(rawTable, ".", 2); len(parts) == 2 {
+ schema := strings.TrimSpace(parts[0])
+ table := strings.TrimSpace(parts[1])
+ if schema != "" && table != "" {
+ return schema, table
+ }
+ }
+
+ switch strings.ToLower(strings.TrimSpace(config.Type)) {
+ case "postgres", "kingbase":
+ // PG/金仓:dbName 在 UI 里是“数据库”,schema 需从 tableName 或使用默认 public。
+ return "public", rawTable
+ default:
+ // MySQL:dbName 表示数据库;Oracle/达梦:dbName 表示 schema/owner。
+ return rawDB, rawTable
+ }
+}
+
diff --git a/internal/app/methods_db.go b/internal/app/methods_db.go
index 1e31820..fa010be 100644
--- a/internal/app/methods_db.go
+++ b/internal/app/methods_db.go
@@ -83,10 +83,7 @@ func (a *App) MySQLShowCreateTable(config connection.ConnectionConfig, dbName st
}
func (a *App) DBQuery(config connection.ConnectionConfig, dbName string, query string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
@@ -143,10 +140,7 @@ func (a *App) DBGetDatabases(config connection.ConnectionConfig) connection.Quer
}
func (a *App) DBGetTables(config connection.ConnectionConfig, dbName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
@@ -169,10 +163,7 @@ func (a *App) DBGetTables(config connection.ConnectionConfig, dbName string) con
}
func (a *App) DBShowCreateTable(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
@@ -180,7 +171,8 @@ func (a *App) DBShowCreateTable(config connection.ConnectionConfig, dbName strin
return connection.QueryResult{Success: false, Message: err.Error()}
}
- sqlStr, err := dbInst.GetCreateStatement(dbName, tableName)
+ schemaName, pureTableName := normalizeSchemaAndTable(config, dbName, tableName)
+ sqlStr, err := dbInst.GetCreateStatement(schemaName, pureTableName)
if err != nil {
logger.Error(err, "DBShowCreateTable 获取建表语句失败:%s 表=%s", formatConnSummary(runConfig), tableName)
return connection.QueryResult{Success: false, Message: err.Error()}
@@ -190,17 +182,15 @@ func (a *App) DBShowCreateTable(config connection.ConnectionConfig, dbName strin
}
func (a *App) DBGetColumns(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
- columns, err := dbInst.GetColumns(dbName, tableName)
+ schemaName, pureTableName := normalizeSchemaAndTable(config, dbName, tableName)
+ columns, err := dbInst.GetColumns(schemaName, pureTableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
@@ -209,17 +199,15 @@ func (a *App) DBGetColumns(config connection.ConnectionConfig, dbName string, ta
}
func (a *App) DBGetIndexes(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
- indexes, err := dbInst.GetIndexes(dbName, tableName)
+ schemaName, pureTableName := normalizeSchemaAndTable(config, dbName, tableName)
+ indexes, err := dbInst.GetIndexes(schemaName, pureTableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
@@ -228,17 +216,15 @@ func (a *App) DBGetIndexes(config connection.ConnectionConfig, dbName string, ta
}
func (a *App) DBGetForeignKeys(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
- fks, err := dbInst.GetForeignKeys(dbName, tableName)
+ schemaName, pureTableName := normalizeSchemaAndTable(config, dbName, tableName)
+ fks, err := dbInst.GetForeignKeys(schemaName, pureTableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
@@ -247,17 +233,15 @@ func (a *App) DBGetForeignKeys(config connection.ConnectionConfig, dbName string
}
func (a *App) DBGetTriggers(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
- triggers, err := dbInst.GetTriggers(dbName, tableName)
+ schemaName, pureTableName := normalizeSchemaAndTable(config, dbName, tableName)
+ triggers, err := dbInst.GetTriggers(schemaName, pureTableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
@@ -266,10 +250,7 @@ func (a *App) DBGetTriggers(config connection.ConnectionConfig, dbName string, t
}
func (a *App) DBGetAllColumns(config connection.ConnectionConfig, dbName string) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
diff --git a/internal/app/methods_file.go b/internal/app/methods_file.go
index d28b83b..e717fe6 100644
--- a/internal/app/methods_file.go
+++ b/internal/app/methods_file.go
@@ -135,10 +135,7 @@ func (a *App) ImportData(config connection.ConnectionConfig, dbName, tableName s
return connection.QueryResult{Success: true, Message: "No data to import"}
}
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
@@ -164,21 +161,16 @@ func (a *App) ImportData(config connection.ConnectionConfig, dbName, tableName s
values = append(values, fmt.Sprintf("'%s'", vStr))
}
}
-
- query := fmt.Sprintf("INSERT INTO `%s` (%s) VALUES (%s)",
- tableName,
- strings.Join(cols, ", "),
- strings.Join(values, ", "))
-
- if runConfig.Type == "postgres" {
- pgCols := make([]string, len(cols))
- for i, c := range cols { pgCols[i] = fmt.Sprintf("\"%s\"", c) }
- query = fmt.Sprintf("INSERT INTO \"%s\" (%s) VALUES (%s)",
- tableName,
- strings.Join(pgCols, ", "),
- strings.Join(values, ", "))
+ quotedCols := make([]string, len(cols))
+ for i, c := range cols {
+ quotedCols[i] = quoteIdentByType(runConfig.Type, c)
}
+ query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)",
+ quoteQualifiedIdentByType(runConfig.Type, tableName),
+ strings.Join(quotedCols, ", "),
+ strings.Join(values, ", "))
+
_, err := dbInst.Exec(query)
if err != nil {
errCount++
@@ -192,10 +184,7 @@ func (a *App) ImportData(config connection.ConnectionConfig, dbName, tableName s
}
func (a *App) ApplyChanges(config connection.ConnectionConfig, dbName, tableName string, changes connection.ChangeSet) connection.QueryResult {
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
@@ -223,20 +212,14 @@ func (a *App) ExportTable(config connection.ConnectionConfig, dbName string, tab
return connection.QueryResult{Success: false, Message: "Cancelled"}
}
- runConfig := config
- if dbName != "" {
- runConfig.Database = dbName
- }
+ runConfig := normalizeRunConfig(config, dbName)
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
- query := fmt.Sprintf("SELECT * FROM `%s`", tableName)
- if runConfig.Type == "postgres" {
- query = fmt.Sprintf("SELECT * FROM \"%s\"", tableName)
- }
+ query := fmt.Sprintf("SELECT * FROM %s", quoteQualifiedIdentByType(runConfig.Type, tableName))
data, columns, err := dbInst.Query(query)
if err != nil {
@@ -318,6 +301,45 @@ data, columns, err := dbInst.Query(query)
return connection.QueryResult{Success: true, Message: "Export successful"}
}
+func quoteIdentByType(dbType string, ident string) string {
+ if ident == "" {
+ return ident
+ }
+
+ switch dbType {
+ case "mysql":
+ return "`" + strings.ReplaceAll(ident, "`", "``") + "`"
+ default:
+ return `"` + strings.ReplaceAll(ident, `"`, `""`) + `"`
+ }
+}
+
+func quoteQualifiedIdentByType(dbType string, ident string) string {
+ raw := strings.TrimSpace(ident)
+ if raw == "" {
+ return raw
+ }
+
+ parts := strings.Split(raw, ".")
+ if len(parts) <= 1 {
+ return quoteIdentByType(dbType, raw)
+ }
+
+ quotedParts := make([]string, 0, len(parts))
+ for _, part := range parts {
+ part = strings.TrimSpace(part)
+ if part == "" {
+ continue
+ }
+ quotedParts = append(quotedParts, quoteIdentByType(dbType, part))
+ }
+
+ if len(quotedParts) == 0 {
+ return quoteIdentByType(dbType, raw)
+ }
+ return strings.Join(quotedParts, ".")
+}
+
// ExportData exports provided data to a file
func (a *App) ExportData(data []map[string]interface{}, columns []string, defaultName string, format string) connection.QueryResult {
if defaultName == "" {
diff --git a/internal/db/custom_impl.go b/internal/db/custom_impl.go
index 4fcfdcc..3d21faa 100644
--- a/internal/db/custom_impl.go
+++ b/internal/db/custom_impl.go
@@ -92,7 +92,11 @@ func (c *CustomDB) Query(query string) ([]map[string]interface{}, []string, erro
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}
@@ -136,13 +140,22 @@ func (c *CustomDB) GetTables(dbName string) ([]string, error) {
query = fmt.Sprintf("SHOW TABLES FROM `%s`", dbName)
}
} else if c.driver == "postgres" || c.driver == "kingbase" {
- if dbName != "" && dbName != "public" {
- query = fmt.Sprintf("SELECT table_name FROM information_schema.tables WHERE table_schema = '%s'", dbName)
+ query = `
+ SELECT table_schema AS schemaname, table_name AS tablename
+ FROM information_schema.tables
+ WHERE table_type = 'BASE TABLE'
+ AND table_schema NOT IN ('pg_catalog', 'information_schema')`
+ if dbName != "" {
+ query += fmt.Sprintf(" AND table_schema = '%s'", dbName)
}
+ query += " ORDER BY table_schema, table_name"
} else if c.driver == "sqlite" {
query = "SELECT name FROM sqlite_master WHERE type='table'"
} else if c.driver == "oracle" || c.driver == "dm" {
query = "SELECT table_name FROM user_tables"
+ if dbName != "" {
+ query = fmt.Sprintf("SELECT owner, table_name FROM all_tables WHERE owner = '%s' ORDER BY table_name", strings.ToUpper(dbName))
+ }
}
// Fallback generic execution
@@ -153,6 +166,18 @@ func (c *CustomDB) GetTables(dbName string) ([]string, error) {
var tables []string
for _, row := range data {
+ if schema, okSchema := row["schemaname"]; okSchema {
+ if name, okName := row["tablename"]; okName {
+ tables = append(tables, fmt.Sprintf("%v.%v", schema, name))
+ continue
+ }
+ }
+ if owner, okOwner := row["OWNER"]; okOwner {
+ if name, okName := row["TABLE_NAME"]; okName {
+ tables = append(tables, fmt.Sprintf("%v.%v", owner, name))
+ continue
+ }
+ }
// iterate keys to find likely column
for k, v := range row {
if strings.Contains(strings.ToLower(k), "name") || strings.Contains(strings.ToLower(k), "table") {
diff --git a/internal/db/dameng_impl.go b/internal/db/dameng_impl.go
index 2fe1ba3..e8b7b31 100644
--- a/internal/db/dameng_impl.go
+++ b/internal/db/dameng_impl.go
@@ -123,7 +123,11 @@ func (d *DamengDB) Query(query string) ([]map[string]interface{}, []string, erro
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}
@@ -166,7 +170,7 @@ func (d *DamengDB) GetDatabases() ([]string, error) {
}
func (d *DamengDB) GetTables(dbName string) ([]string, error) {
- query := fmt.Sprintf("SELECT table_name FROM all_tables WHERE owner = '%s'", strings.ToUpper(dbName))
+ query := fmt.Sprintf("SELECT owner, table_name FROM all_tables WHERE owner = '%s' ORDER BY table_name", strings.ToUpper(dbName))
if dbName == "" {
query = "SELECT table_name FROM user_tables"
}
@@ -178,6 +182,14 @@ func (d *DamengDB) GetTables(dbName string) ([]string, error) {
var tables []string
for _, row := range data {
+ if dbName != "" {
+ if owner, okOwner := row["OWNER"]; okOwner {
+ if name, okName := row["TABLE_NAME"]; okName {
+ tables = append(tables, fmt.Sprintf("%v.%v", owner, name))
+ continue
+ }
+ }
+ }
if val, ok := row["TABLE_NAME"]; ok {
tables = append(tables, fmt.Sprintf("%v", val))
}
diff --git a/internal/db/kingbase_impl.go b/internal/db/kingbase_impl.go
index 7d62c22..a85210f 100644
--- a/internal/db/kingbase_impl.go
+++ b/internal/db/kingbase_impl.go
@@ -154,7 +154,11 @@ func (k *KingbaseDB) Query(query string) ([]map[string]interface{}, []string, er
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}
@@ -193,15 +197,14 @@ func (k *KingbaseDB) GetDatabases() ([]string, error) {
}
func (k *KingbaseDB) GetTables(dbName string) ([]string, error) {
- // Usually restricted to current database connection in PG/Kingbase
- // dbName param is often Schema in PG context, or ignored if we are connected to a specific DB.
- // But in PG, cross-database queries are not standard without dblink.
- // We assume dbName here might mean Schema (public, etc.)
-
- query := "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"
- if dbName != "" && dbName != "public" {
- query = fmt.Sprintf("SELECT table_name FROM information_schema.tables WHERE table_schema = '%s'", dbName)
- }
+ // Kingbase: tables are scoped by the current DB connection; include schema to avoid search_path issues.
+ query := `
+ SELECT table_schema AS schemaname, table_name AS tablename
+ FROM information_schema.tables
+ WHERE table_type = 'BASE TABLE'
+ AND table_schema NOT IN ('pg_catalog', 'information_schema')
+ AND table_schema NOT LIKE 'pg_%'
+ ORDER BY table_schema, table_name`
data, _, err := k.Query(query)
if err != nil {
@@ -210,6 +213,12 @@ func (k *KingbaseDB) GetTables(dbName string) ([]string, error) {
var tables []string
for _, row := range data {
+ schema, okSchema := row["schemaname"]
+ name, okName := row["tablename"]
+ if okSchema && okName {
+ tables = append(tables, fmt.Sprintf("%v.%v", schema, name))
+ continue
+ }
if val, ok := row["table_name"]; ok {
tables = append(tables, fmt.Sprintf("%v", val))
}
diff --git a/internal/db/mysql_impl.go b/internal/db/mysql_impl.go
index 7c8c041..fdd11d2 100644
--- a/internal/db/mysql_impl.go
+++ b/internal/db/mysql_impl.go
@@ -111,7 +111,11 @@ func (m *MySQLDB) Query(query string) ([]map[string]interface{}, []string, error
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}
diff --git a/internal/db/oracle_impl.go b/internal/db/oracle_impl.go
index ef162fe..95598b8 100644
--- a/internal/db/oracle_impl.go
+++ b/internal/db/oracle_impl.go
@@ -129,7 +129,11 @@ func (o *OracleDB) Query(query string) ([]map[string]interface{}, []string, erro
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}
@@ -171,7 +175,7 @@ func (o *OracleDB) GetTables(dbName string) ([]string, error) {
// dbName is Schema/Owner
query := "SELECT table_name FROM user_tables"
if dbName != "" {
- query = fmt.Sprintf("SELECT table_name FROM all_tables WHERE owner = '%s'", strings.ToUpper(dbName))
+ query = fmt.Sprintf("SELECT owner, table_name FROM all_tables WHERE owner = '%s' ORDER BY table_name", strings.ToUpper(dbName))
}
data, _, err := o.Query(query)
@@ -181,6 +185,14 @@ func (o *OracleDB) GetTables(dbName string) ([]string, error) {
var tables []string
for _, row := range data {
+ if dbName != "" {
+ if owner, okOwner := row["OWNER"]; okOwner {
+ if name, okName := row["TABLE_NAME"]; okName {
+ tables = append(tables, fmt.Sprintf("%v.%v", owner, name))
+ continue
+ }
+ }
+ }
if val, ok := row["TABLE_NAME"]; ok {
tables = append(tables, fmt.Sprintf("%v", val))
}
diff --git a/internal/db/postgres_impl.go b/internal/db/postgres_impl.go
index 42602f1..fba01da 100644
--- a/internal/db/postgres_impl.go
+++ b/internal/db/postgres_impl.go
@@ -112,7 +112,11 @@ rows, err := p.conn.Query(query)
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}
@@ -150,7 +154,7 @@ func (p *PostgresDB) GetDatabases() ([]string, error) {
}
func (p *PostgresDB) GetTables(dbName string) ([]string, error) {
- query := "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema'"
+ query := "SELECT schemaname, tablename FROM pg_catalog.pg_tables WHERE schemaname != 'information_schema' AND schemaname NOT LIKE 'pg_%' ORDER BY schemaname, tablename"
data, _, err := p.Query(query)
if err != nil {
return nil, err
@@ -158,8 +162,14 @@ func (p *PostgresDB) GetTables(dbName string) ([]string, error) {
var tables []string
for _, row := range data {
- if val, ok := row["tablename"]; ok {
- tables = append(tables, fmt.Sprintf("%v", val))
+ schema, okSchema := row["schemaname"]
+ name, okName := row["tablename"]
+ if okSchema && okName {
+ tables = append(tables, fmt.Sprintf("%v.%v", schema, name))
+ continue
+ }
+ if okName {
+ tables = append(tables, fmt.Sprintf("%v", name))
}
}
return tables, nil
diff --git a/internal/db/sqlite_impl.go b/internal/db/sqlite_impl.go
index 681dea4..01daa1e 100644
--- a/internal/db/sqlite_impl.go
+++ b/internal/db/sqlite_impl.go
@@ -87,7 +87,11 @@ func (s *SQLiteDB) Query(query string) ([]map[string]interface{}, []string, erro
val := values[i]
b, ok := val.([]byte)
if ok {
- v = string(b)
+ if b == nil {
+ v = nil
+ } else {
+ v = string(b)
+ }
} else {
v = val
}