mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-02 13:01:45 +08:00
🐛 fix(db): 修复金仓读查询结果空页
- 调整 PG 类数据库只读查询路径,优先使用普通 Query 返回真实结果集 - 避免金仓原生多结果集返回空行列时吞掉可展示数据 - 补充金仓读查询与原生空结果回退测试覆盖
This commit is contained in:
@@ -1225,6 +1225,7 @@ func (a *App) DBQueryMulti(config connection.ConnectionConfig, dbName string, qu
|
||||
isReadStmt := isReadOnlySQLQuery(runConfig.Type, stmt)
|
||||
tryQueryStmtFirst := shouldTryQueryResultFirst(runConfig.Type, stmt)
|
||||
if isReadStmt || tryQueryStmtFirst {
|
||||
preferPlainReadQuery := isReadStmt && shouldPreferPlainReadQueryResult(runConfig.Type)
|
||||
var (
|
||||
data []map[string]interface{}
|
||||
columns []string
|
||||
@@ -1248,7 +1249,9 @@ func (a *App) DBQueryMulti(config connection.ConnectionConfig, dbName string, qu
|
||||
}
|
||||
return err
|
||||
}
|
||||
if sessionMultiQueryMessageTarget != nil {
|
||||
if preferPlainReadQuery {
|
||||
err = runStatementQuery()
|
||||
} else if sessionMultiQueryMessageTarget != nil {
|
||||
statementResults, messages, err = sessionMultiQueryMessageTarget.QueryMultiContextWithMessages(ctx, stmt)
|
||||
usedMultiResult = true
|
||||
} else if sessionMultiQueryTarget != nil {
|
||||
@@ -1394,7 +1397,7 @@ func nativeReadOnlyResultsMissingTabularPayload(allReadOnly bool, results []conn
|
||||
|
||||
func shouldUseNativeMultiResultBatch(dbType string, statements []string, allReadOnly bool) bool {
|
||||
if allReadOnly {
|
||||
return true
|
||||
return !shouldPreferPlainReadQueryResult(dbType)
|
||||
}
|
||||
if !strings.EqualFold(strings.TrimSpace(dbType), "sqlserver") {
|
||||
return false
|
||||
@@ -1412,6 +1415,15 @@ func shouldUseNativeMultiResultBatch(dbType string, statements []string, allRead
|
||||
return true
|
||||
}
|
||||
|
||||
func shouldPreferPlainReadQueryResult(dbType string) bool {
|
||||
switch resolveDDLDBType(connection.ConnectionConfig{Type: dbType}) {
|
||||
case "postgres", "kingbase", "highgo", "vastbase", "opengauss", "gaussdb":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func shouldTryQueryResultFirst(dbType string, query string) bool {
|
||||
isSQLServer := isSQLServerDBType(dbType)
|
||||
if sqlWriteStatementReturnsRows(dbType, query) {
|
||||
|
||||
@@ -1787,7 +1787,7 @@ func TestDBQueryMultiFallsBackToPlainQueryWhenSequentialMultiStillReturnsBlankRe
|
||||
}
|
||||
|
||||
app := NewAppWithSecretStore(secretstore.NewUnavailableStore("test"))
|
||||
config := connection.ConnectionConfig{Type: "kingbase", Host: "127.0.0.1", Port: 54321, User: "system"}
|
||||
config := connection.ConnectionConfig{Type: "mysql", Host: "127.0.0.1", Port: 3306, User: "root"}
|
||||
|
||||
result := app.DBQueryMulti(config, "ldf_server_dbs_dev", query, "sequential-blank-native-read-fallback-test")
|
||||
if !result.Success {
|
||||
@@ -1817,6 +1817,67 @@ func TestDBQueryMultiFallsBackToPlainQueryWhenSequentialMultiStillReturnsBlankRe
|
||||
}
|
||||
}
|
||||
|
||||
func TestDBQueryMultiPrefersPlainQueryForKingbaseReadResults(t *testing.T) {
|
||||
originalNewDatabaseFunc := newDatabaseFunc
|
||||
t.Cleanup(func() {
|
||||
newDatabaseFunc = originalNewDatabaseFunc
|
||||
})
|
||||
|
||||
query := "SELECT * FROM ldf_server.mes_work_order"
|
||||
nativeEmptyRowsResult := []connection.ResultSetData{{
|
||||
Rows: []map[string]interface{}{},
|
||||
Columns: []string{"id", "work_order"},
|
||||
}}
|
||||
baseDB := &fakeBatchWriteDB{
|
||||
queryMap: map[string][]map[string]interface{}{
|
||||
query: {
|
||||
{"id": 1001, "work_order": "MO-20260629"},
|
||||
},
|
||||
},
|
||||
fieldMap: map[string][]string{
|
||||
query: {"id", "work_order"},
|
||||
},
|
||||
multiResult: map[string][]connection.ResultSetData{
|
||||
query: nativeEmptyRowsResult,
|
||||
},
|
||||
queryErr: map[string]error{},
|
||||
}
|
||||
fakeDB := &fakeNativeMultiResultDB{fakeBatchWriteDB: baseDB}
|
||||
newDatabaseFunc = func(dbType string) (db.Database, error) {
|
||||
return fakeDB, nil
|
||||
}
|
||||
|
||||
app := NewAppWithSecretStore(secretstore.NewUnavailableStore("test"))
|
||||
config := connection.ConnectionConfig{Type: "kingbase", Host: "127.0.0.1", Port: 54321, User: "system"}
|
||||
|
||||
result := app.DBQueryMulti(config, "ldf_server_dbs_dev", query, "kingbase-plain-query-result-test")
|
||||
if !result.Success {
|
||||
t.Fatalf("expected DBQueryMulti success, got failure: %s", result.Message)
|
||||
}
|
||||
if fakeDB.multiCalls != 0 {
|
||||
t.Fatalf("expected kingbase read query to skip top-level native multi-result path, got %d calls", fakeDB.multiCalls)
|
||||
}
|
||||
if baseDB.session == nil {
|
||||
t.Fatal("expected DBQueryMulti to open a pinned session for kingbase read query")
|
||||
}
|
||||
if baseDB.session.queryCalls != 1 {
|
||||
t.Fatalf("expected kingbase read query to use plain session query once, got %d calls", baseDB.session.queryCalls)
|
||||
}
|
||||
resultSets, ok := result.Data.([]connection.ResultSetData)
|
||||
if !ok {
|
||||
t.Fatalf("expected []connection.ResultSetData, got %T", result.Data)
|
||||
}
|
||||
if len(resultSets) != 1 {
|
||||
t.Fatalf("expected one result set, got %#v", resultSets)
|
||||
}
|
||||
if !reflect.DeepEqual(resultSets[0].Columns, []string{"id", "work_order"}) {
|
||||
t.Fatalf("expected plain query columns, got %#v", resultSets[0].Columns)
|
||||
}
|
||||
if got := resultSets[0].Rows[0]["work_order"]; got != "MO-20260629" {
|
||||
t.Fatalf("expected plain query SELECT result work_order=MO-20260629, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDBQueryMultiUsesPinnedSessionForSequentialFallback(t *testing.T) {
|
||||
originalNewDatabaseFunc := newDatabaseFunc
|
||||
t.Cleanup(func() {
|
||||
|
||||
Reference in New Issue
Block a user