• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 12302730510

12 Dec 2024 06:40PM UTC coverage: 58.624% (+9.7%) from 48.92%
12302730510

Pull #9242

github

aakselrod
docs: update release-notes for 0.19.0
Pull Request #9242: Reapply #8644

25 of 41 new or added lines in 4 files covered. (60.98%)

2 existing lines in 1 file now uncovered.

134425 of 229301 relevant lines covered (58.62%)

19268.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.81
/sqldb/sqlerrors.go
1
//go:build !js && !(windows && (arm || 386)) && !(linux && (ppc64 || mips || mipsle || mips64))
2

3
package sqldb
4

5
import (
6
        "errors"
7
        "fmt"
8
        "strings"
9

10
        "github.com/jackc/pgconn"
11
        "github.com/jackc/pgerrcode"
12
        "modernc.org/sqlite"
13
        sqlite3 "modernc.org/sqlite/lib"
14
)
15

16
var (
17
        // ErrRetriesExceeded is returned when a transaction is retried more
18
        // than the max allowed valued without a success.
19
        ErrRetriesExceeded = errors.New("db tx retries exceeded")
20

21
        // postgresErrMsgs are strings that signify retriable errors resulting
22
        // from serialization failures.
23
        postgresErrMsgs = []string{
24
                "could not serialize access",
25
                "current transaction is aborted",
26
                "not enough elements in RWConflictPool",
27
                "deadlock detected",
28
                "commit unexpectedly resulted in rollback",
29
        }
30
)
31

32
// MapSQLError attempts to interpret a given error as a database agnostic SQL
33
// error.
34
func MapSQLError(err error) error {
114✔
35
        if err == nil {
114✔
36
                return nil
×
37
        }
×
38

39
        // Attempt to interpret the error as a sqlite error.
40
        var sqliteErr *sqlite.Error
114✔
41
        if errors.As(err, &sqliteErr) {
123✔
42
                return parseSqliteError(sqliteErr)
9✔
43
        }
9✔
44

45
        // Attempt to interpret the error as a postgres error.
46
        var pqErr *pgconn.PgError
105✔
47
        if errors.As(err, &pqErr) {
114✔
48
                return parsePostgresError(pqErr)
9✔
49
        }
9✔
50

51
        // Sometimes the error won't be properly wrapped, so we'll need to
52
        // inspect raw error itself to detect something we can wrap properly.
53
        // This handles a postgres variant of the error.
54
        for _, postgresErrMsg := range postgresErrMsgs {
572✔
55
                if strings.Contains(err.Error(), postgresErrMsg) {
477✔
56
                        return &ErrSerializationError{
1✔
57
                                DBError: err,
1✔
58
                        }
1✔
59
                }
1✔
60
        }
61

62
        // We'll also attempt to catch this for sqlite, that uses a slightly
63
        // different error message. This is taken from:
64
        // https://gitlab.com/cznic/sqlite/-/blob/v1.25.0/sqlite.go#L75.
65
        const sqliteErrMsg = "SQLITE_BUSY"
95✔
66
        if strings.Contains(err.Error(), sqliteErrMsg) {
95✔
67
                return &ErrSerializationError{
×
68
                        DBError: err,
×
69
                }
×
70
        }
×
71

72
        // Return original error if it could not be classified as a database
73
        // specific error.
74
        return err
95✔
75
}
76

77
// parsePostgresError attempts to parse a sqlite error as a database agnostic
78
// SQL error.
79
func parseSqliteError(sqliteErr *sqlite.Error) error {
9✔
80
        switch sqliteErr.Code() {
9✔
81
        // Handle unique constraint violation error.
82
        case sqlite3.SQLITE_CONSTRAINT_UNIQUE:
8✔
83
                return &ErrSQLUniqueConstraintViolation{
8✔
84
                        DBError: sqliteErr,
8✔
85
                }
8✔
86

87
        case sqlite3.SQLITE_CONSTRAINT_PRIMARYKEY:
1✔
88
                return &ErrSQLUniqueConstraintViolation{
1✔
89
                        DBError: sqliteErr,
1✔
90
                }
1✔
91

92
        // Database is currently busy, so we'll need to try again.
93
        case sqlite3.SQLITE_BUSY:
×
94
                return &ErrSerializationError{
×
95
                        DBError: sqliteErr,
×
96
                }
×
97

98
        default:
×
99
                return fmt.Errorf("unknown sqlite error: %w", sqliteErr)
×
100
        }
101
}
102

103
// parsePostgresError attempts to parse a postgres error as a database agnostic
104
// SQL error.
105
func parsePostgresError(pqErr *pgconn.PgError) error {
9✔
106
        switch pqErr.Code {
9✔
107
        // Handle unique constraint violation error.
108
        case pgerrcode.UniqueViolation:
9✔
109
                return &ErrSQLUniqueConstraintViolation{
9✔
110
                        DBError: pqErr,
9✔
111
                }
9✔
112

113
        // Unable to serialize the transaction, so we'll need to try again.
114
        case pgerrcode.SerializationFailure:
×
115
                return &ErrSerializationError{
×
116
                        DBError: pqErr,
×
117
                }
×
118

119
        // In failed SQL transaction because we didn't catch a previous
120
        // serialization error, so return this one as a serialization error.
NEW
121
        case pgerrcode.InFailedSQLTransaction:
×
NEW
122
                return &ErrSerializationError{
×
NEW
123
                        DBError: pqErr,
×
NEW
124
                }
×
125

126
        // Deadlock detedted because of a serialization error, so return this
127
        // one as a serialization error.
NEW
128
        case pgerrcode.DeadlockDetected:
×
NEW
129
                return &ErrSerializationError{
×
NEW
130
                        DBError: pqErr,
×
NEW
131
                }
×
132

133
        default:
×
134
                return fmt.Errorf("unknown postgres error: %w", pqErr)
×
135
        }
136
}
137

138
// ErrSQLUniqueConstraintViolation is an error type which represents a database
139
// agnostic SQL unique constraint violation.
140
type ErrSQLUniqueConstraintViolation struct {
141
        DBError error
142
}
143

144
func (e ErrSQLUniqueConstraintViolation) Error() string {
96✔
145
        return fmt.Sprintf("sql unique constraint violation: %v", e.DBError)
96✔
146
}
96✔
147

148
// ErrSerializationError is an error type which represents a database agnostic
149
// error that a transaction couldn't be serialized with other concurrent db
150
// transactions.
151
type ErrSerializationError struct {
152
        DBError error
153
}
154

155
// Unwrap returns the wrapped error.
156
func (e ErrSerializationError) Unwrap() error {
×
157
        return e.DBError
×
158
}
×
159

160
// Error returns the error message.
161
func (e ErrSerializationError) Error() string {
1✔
162
        return e.DBError.Error()
1✔
163
}
1✔
164

165
// IsSerializationError returns true if the given error is a serialization
166
// error.
167
func IsSerializationError(err error) bool {
96✔
168
        var serializationError *ErrSerializationError
96✔
169
        return errors.As(err, &serializationError)
96✔
170
}
96✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc