mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-11 09:13:36 +08:00
132 lines
3.4 KiB
Go
132 lines
3.4 KiB
Go
package sync
|
|
|
|
import (
|
|
"GoNavi-Wails/internal/connection"
|
|
"GoNavi-Wails/internal/db"
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type syncDriverContextKey struct{}
|
|
|
|
// markSyncDriverContext keeps RunSync's historical Query/Exec dispatch intact
|
|
// while allowing callers that explicitly choose RunSyncContext to opt in to
|
|
// the optional context-aware driver methods. This matters for compatibility
|
|
// with wrappers that override Query/Exec but inherit unrelated context methods.
|
|
func markSyncDriverContext(ctx context.Context) context.Context {
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
return context.WithValue(ctx, syncDriverContextKey{}, true)
|
|
}
|
|
|
|
func syncDriverContextEnabled(ctx context.Context) bool {
|
|
enabled, _ := ctx.Value(syncDriverContextKey{}).(bool)
|
|
return enabled
|
|
}
|
|
|
|
type syncQueryContexter interface {
|
|
QueryContext(context.Context, string) ([]map[string]interface{}, []string, error)
|
|
}
|
|
|
|
type syncExecContexter interface {
|
|
ExecContext(context.Context, string) (int64, error)
|
|
}
|
|
|
|
type syncBatchApplyContexter interface {
|
|
ApplyChangesContext(context.Context, string, connection.ChangeSet) error
|
|
}
|
|
|
|
func (s *SyncEngine) context() context.Context {
|
|
if s == nil || s.ctx == nil {
|
|
return context.Background()
|
|
}
|
|
return s.ctx
|
|
}
|
|
|
|
func (s *SyncEngine) contextError() error {
|
|
return s.context().Err()
|
|
}
|
|
|
|
func querySyncDatabaseContext(ctx context.Context, database db.Database, query string) ([]map[string]interface{}, []string, error) {
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
if err := ctx.Err(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if syncDriverContextEnabled(ctx) {
|
|
if contextDatabase, ok := database.(syncQueryContexter); ok {
|
|
return contextDatabase.QueryContext(ctx, query)
|
|
}
|
|
}
|
|
rows, columns, err := database.Query(query)
|
|
if err != nil {
|
|
return rows, columns, err
|
|
}
|
|
if contextErr := ctx.Err(); contextErr != nil {
|
|
return nil, nil, contextErr
|
|
}
|
|
return rows, columns, nil
|
|
}
|
|
|
|
func execSyncDatabaseContext(ctx context.Context, database db.Database, query string) (int64, error) {
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
if err := ctx.Err(); err != nil {
|
|
return 0, err
|
|
}
|
|
if syncDriverContextEnabled(ctx) {
|
|
if contextDatabase, ok := database.(syncExecContexter); ok {
|
|
return contextDatabase.ExecContext(ctx, query)
|
|
}
|
|
}
|
|
affected, err := database.Exec(query)
|
|
if err != nil {
|
|
return affected, err
|
|
}
|
|
if contextErr := ctx.Err(); contextErr != nil {
|
|
return affected, contextErr
|
|
}
|
|
return affected, nil
|
|
}
|
|
|
|
func applySyncChangesContext(ctx context.Context, applier db.BatchApplier, tableName string, changes connection.ChangeSet) error {
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
if err := ctx.Err(); err != nil {
|
|
return err
|
|
}
|
|
if syncDriverContextEnabled(ctx) {
|
|
if contextApplier, ok := applier.(syncBatchApplyContexter); ok {
|
|
return contextApplier.ApplyChangesContext(ctx, tableName, changes)
|
|
}
|
|
}
|
|
if err := applier.ApplyChanges(tableName, changes); err != nil {
|
|
return err
|
|
}
|
|
return ctx.Err()
|
|
}
|
|
|
|
func executeSyncSQLStatementsContext(ctx context.Context, database db.Database, statements []string) error {
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
for _, statement := range statements {
|
|
statement = strings.TrimSpace(statement)
|
|
if statement == "" {
|
|
continue
|
|
}
|
|
if err := ctx.Err(); err != nil {
|
|
return err
|
|
}
|
|
if _, err := execSyncDatabaseContext(ctx, database, statement); err != nil {
|
|
return fmt.Errorf("执行 SQL 失败:%s: %w", statement, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|