🐛 fix(sql-editor): 修复存储过程与返回结果写语句的结果识别

- 补齐 SQL 分类逻辑,识别 SQL Server 裸存储过程调用、RETURNING/OUTPUT、SELECT INTO 及消息块场景
- 调整多语句执行与批量写入分支,避免返回行或服务端消息被 Exec 路径吞掉
- 为 PostgreSQL、OpenGauss、Kingbase、HighGo 补充 notice 回传能力并增加回归测试
This commit is contained in:
Syngnat
2026-06-14 21:37:02 +08:00
parent d7632e29a6
commit f2ffeeaf45
9 changed files with 668 additions and 15 deletions

View File

@@ -5,6 +5,7 @@ package db
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"net"
"net/url"
@@ -18,7 +19,7 @@ import (
"GoNavi-Wails/internal/ssh"
"GoNavi-Wails/internal/utils"
_ "gitea.com/kingbase/gokb" // Registers "kingbase" driver
gokb "gitea.com/kingbase/gokb" // Registers "kingbase" driver
)
type KingbaseDB struct {
@@ -27,6 +28,13 @@ type KingbaseDB struct {
forwarder *ssh.LocalForwarder // Store SSH tunnel forwarder
}
type kingbaseSessionExecer struct {
*sqlConnStatementExecer
}
var _ QueryMessageExecer = (*KingbaseDB)(nil)
var _ StatementQueryMessageExecer = (*kingbaseSessionExecer)(nil)
func quoteConnValue(v string) string {
if v == "" {
return "''"
@@ -280,6 +288,20 @@ func (k *KingbaseDB) QueryContext(ctx context.Context, query string) ([]map[stri
return scanRows(rows)
}
func (k *KingbaseDB) QueryContextWithMessages(ctx context.Context, query string) ([]map[string]interface{}, []string, []string, error) {
if k.conn == nil {
return nil, nil, nil, fmt.Errorf("连接未打开")
}
conn, err := k.conn.Conn(ctx)
if err != nil {
return nil, nil, nil, err
}
defer conn.Close()
return queryKingbaseConnWithMessages(ctx, conn, query)
}
func (k *KingbaseDB) Query(query string) ([]map[string]interface{}, []string, error) {
if k.conn == nil {
return nil, nil, fmt.Errorf("连接未打开")
@@ -293,6 +315,10 @@ func (k *KingbaseDB) Query(query string) ([]map[string]interface{}, []string, er
return scanRows(rows)
}
func (k *KingbaseDB) QueryWithMessages(query string) ([]map[string]interface{}, []string, []string, error) {
return k.QueryContextWithMessages(context.Background(), query)
}
func (k *KingbaseDB) ExecContext(ctx context.Context, query string) (int64, error) {
if k.conn == nil {
return 0, fmt.Errorf("连接未打开")
@@ -323,7 +349,7 @@ func (k *KingbaseDB) OpenSessionExecer(ctx context.Context) (StatementExecer, er
if err != nil {
return nil, err
}
return NewSQLConnStatementExecer(conn), nil
return &kingbaseSessionExecer{sqlConnStatementExecer: &sqlConnStatementExecer{conn: conn}}, nil
}
func (k *KingbaseDB) Exec(query string) (int64, error) {
@@ -337,6 +363,31 @@ func (k *KingbaseDB) Exec(query string) (int64, error) {
return res.RowsAffected()
}
func (e *kingbaseSessionExecer) QueryWithMessages(query string) ([]map[string]interface{}, []string, []string, error) {
return e.QueryContextWithMessages(context.Background(), query)
}
func (e *kingbaseSessionExecer) QueryContextWithMessages(ctx context.Context, query string) ([]map[string]interface{}, []string, []string, error) {
if e == nil || e.conn == nil {
return nil, nil, nil, fmt.Errorf("连接未打开")
}
return queryKingbaseConnWithMessages(ctx, e.conn, query)
}
func queryKingbaseConnWithMessages(ctx context.Context, conn *sql.Conn, query string) ([]map[string]interface{}, []string, []string, error) {
return querySQLConnWithTextNotices(ctx, conn, query, func(driverConn driver.Conn, addNotice func(string)) {
if addNotice == nil {
gokb.SetNoticeHandler(driverConn, nil)
return
}
gokb.SetNoticeHandler(driverConn, func(notice *gokb.Error) {
if notice != nil {
addNotice(notice.Message)
}
})
})
}
func (k *KingbaseDB) GetDatabases() ([]string, error) {
data, _, err := k.Query("SELECT datname FROM pg_database WHERE datistemplate = false")
if err == nil {