mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-12 16:02:48 +08:00
🐛 fix(db): 保留多写语句结果并修复 MySQL 字符集参数
- 多条写语句改为逐条返回 affectedRows,避免只显示最后一条结果 - 为写语句结果补充 statementIndex,保持语句与结果映射 - 保留 MySQL charset fallback 逗号,避免驱动解析成 %2C
This commit is contained in:
@@ -10,18 +10,19 @@ import (
|
||||
)
|
||||
|
||||
type fakeBatchWriteDB struct {
|
||||
batchCalls int
|
||||
execCalls int
|
||||
execQueries []string
|
||||
lastQuery string
|
||||
lastCtx context.Context
|
||||
queryCalls int
|
||||
queryMap map[string][]map[string]interface{}
|
||||
fieldMap map[string][]string
|
||||
messageMap map[string][]string
|
||||
multiResult map[string][]connection.ResultSetData
|
||||
queryErr map[string]error
|
||||
session *fakeBatchWriteSession
|
||||
batchCalls int
|
||||
execCalls int
|
||||
execQueries []string
|
||||
lastQuery string
|
||||
lastCtx context.Context
|
||||
queryCalls int
|
||||
queryMap map[string][]map[string]interface{}
|
||||
fieldMap map[string][]string
|
||||
messageMap map[string][]string
|
||||
multiResult map[string][]connection.ResultSetData
|
||||
queryErr map[string]error
|
||||
execAffected map[string]int64
|
||||
session *fakeBatchWriteSession
|
||||
}
|
||||
|
||||
func (f *fakeBatchWriteDB) Connect(config connection.ConnectionConfig) error {
|
||||
@@ -52,6 +53,9 @@ func (f *fakeBatchWriteDB) QueryWithMessages(query string) ([]map[string]interfa
|
||||
func (f *fakeBatchWriteDB) Exec(query string) (int64, error) {
|
||||
f.execCalls++
|
||||
f.execQueries = append(f.execQueries, query)
|
||||
if affected, ok := f.execAffected[query]; ok {
|
||||
return affected, nil
|
||||
}
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
@@ -91,6 +95,9 @@ func (f *fakeBatchWriteDB) ExecContext(ctx context.Context, query string) (int64
|
||||
f.lastCtx = ctx
|
||||
f.execCalls++
|
||||
f.execQueries = append(f.execQueries, query)
|
||||
if affected, ok := f.execAffected[query]; ok {
|
||||
return affected, nil
|
||||
}
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
@@ -440,13 +447,20 @@ func TestDBQueryWithCancel_DuckDBQueriesDoNotInheritConnectTimeout(t *testing.T)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDBQueryMultiUsesBatchWriteExecerForAllWriteStatements(t *testing.T) {
|
||||
func TestDBQueryMultiPreservesPerStatementResultsForMultipleWriteStatements(t *testing.T) {
|
||||
originalNewDatabaseFunc := newDatabaseFunc
|
||||
t.Cleanup(func() {
|
||||
newDatabaseFunc = originalNewDatabaseFunc
|
||||
})
|
||||
|
||||
fakeDB := &fakeBatchWriteDB{}
|
||||
firstStmt := "DELETE FROM assets_asset"
|
||||
secondStmt := "DELETE FROM assets_assetcategory"
|
||||
fakeDB := &fakeBatchWriteDB{
|
||||
execAffected: map[string]int64{
|
||||
firstStmt: 5,
|
||||
secondStmt: 10,
|
||||
},
|
||||
}
|
||||
newDatabaseFunc = func(dbType string) (db.Database, error) {
|
||||
return fakeDB, nil
|
||||
}
|
||||
@@ -458,31 +472,37 @@ func TestDBQueryMultiUsesBatchWriteExecerForAllWriteStatements(t *testing.T) {
|
||||
Port: 1433,
|
||||
User: "sa",
|
||||
}
|
||||
query := "INSERT INTO demo(id) VALUES (1);\nINSERT INTO demo(id) VALUES (2);"
|
||||
query := firstStmt + ";\n" + secondStmt + ";"
|
||||
|
||||
result := app.DBQueryMulti(config, "testdb", query, "batch-write-test")
|
||||
if !result.Success {
|
||||
t.Fatalf("expected DBQueryMulti success, got failure: %s", result.Message)
|
||||
}
|
||||
if fakeDB.batchCalls != 1 {
|
||||
t.Fatalf("expected batch path to run once, got %d", fakeDB.batchCalls)
|
||||
if fakeDB.batchCalls != 0 {
|
||||
t.Fatalf("expected multiple write statements to skip batch path so each result can be preserved, got %d", fakeDB.batchCalls)
|
||||
}
|
||||
if fakeDB.execCalls != 0 {
|
||||
t.Fatalf("expected sequential exec path to be skipped, got execCalls=%d", fakeDB.execCalls)
|
||||
if fakeDB.execCalls != 2 {
|
||||
t.Fatalf("expected sequential exec path to run twice, got execCalls=%d", fakeDB.execCalls)
|
||||
}
|
||||
if fakeDB.lastQuery != query {
|
||||
t.Fatalf("expected batch query to stay intact, got %q", fakeDB.lastQuery)
|
||||
if len(fakeDB.execQueries) != 2 || fakeDB.execQueries[0] != firstStmt || fakeDB.execQueries[1] != secondStmt {
|
||||
t.Fatalf("expected sequential execs to preserve statement order, got %#v", fakeDB.execQueries)
|
||||
}
|
||||
|
||||
resultSets, ok := result.Data.([]connection.ResultSetData)
|
||||
if !ok {
|
||||
t.Fatalf("expected []connection.ResultSetData, got %T", result.Data)
|
||||
}
|
||||
if len(resultSets) != 1 || len(resultSets[0].Rows) != 1 {
|
||||
t.Fatalf("expected one affectedRows result set, got %#v", resultSets)
|
||||
if len(resultSets) != 2 {
|
||||
t.Fatalf("expected one affectedRows result set per statement, got %#v", resultSets)
|
||||
}
|
||||
if got := resultSets[0].Rows[0]["affectedRows"]; got != int64(500) {
|
||||
t.Fatalf("expected affectedRows=500, got %#v", got)
|
||||
if len(resultSets[0].Rows) != 1 || len(resultSets[1].Rows) != 1 {
|
||||
t.Fatalf("expected both result sets to contain a single affectedRows row, got %#v", resultSets)
|
||||
}
|
||||
if got := resultSets[0].Rows[0]["affectedRows"]; got != int64(5) {
|
||||
t.Fatalf("expected first affectedRows=5, got %#v", got)
|
||||
}
|
||||
if got := resultSets[1].Rows[0]["affectedRows"]; got != int64(10) {
|
||||
t.Fatalf("expected second affectedRows=10, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user