44 "errors"
55 "strconv"
66 "strings"
7+
8+ "github.com/nalgeon/redka/internal/core"
79)
810
911// SQL dialect.
@@ -17,6 +19,24 @@ const (
1719
1820var ErrDialect = errors .New ("unknown SQL dialect" )
1921
22+ // ConstraintFailed checks if the error is due to
23+ // a constraint violation on a column.
24+ // Error examples:
25+ // - sqlite3.Error (NOT NULL constraint failed: rkey.type)
26+ // - *pq.Error (pq: null value in column "type" of relation "rkey" violates not-null constraint)
27+ func (d Dialect ) ConstraintFailed (err error , constraint , table string , column string ) bool {
28+ var message string
29+ switch d {
30+ case DialectPostgres :
31+ message = `"` + column + `" of relation "` + table +
32+ `" violates ` + strings .ReplaceAll (constraint , " " , "-" ) + ` constraint`
33+ case DialectSqlite :
34+ message = constraint + " constraint failed: " + table + "." + column
35+ }
36+ errStr := strings .ToLower (err .Error ())
37+ return strings .Contains (errStr , message )
38+ }
39+
2040// Enumerate replaces ? placeholders with $1, $2, ... $n.
2141func (d Dialect ) Enumerate (query string ) string {
2242 if d == DialectSqlite {
@@ -70,3 +90,16 @@ func (d Dialect) LimitAll() string {
7090 }
7191 return "limit all"
7292}
93+
94+ // Returns ErrKeyType if the error is due to a not-null
95+ // constraint violation on rkey.type.
96+ // Otherwise, returns the original error.
97+ func (d Dialect ) TypedError (err error ) error {
98+ if err == nil {
99+ return nil
100+ }
101+ if d .ConstraintFailed (err , "not null" , "rkey" , "type" ) {
102+ return core .ErrKeyType
103+ }
104+ return err
105+ }
0 commit comments