github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/pgwire/pgerror/constraint_name.go (about) 1 // Copyright 2020 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package pgerror 12 13 import ( 14 "context" 15 "fmt" 16 17 "github.com/cockroachdb/errors" 18 "github.com/cockroachdb/errors/errorspb" 19 "github.com/gogo/protobuf/proto" 20 ) 21 22 // WithConstraintName decorates the error with a severity. 23 func WithConstraintName(err error, constraint string) error { 24 if err == nil { 25 return nil 26 } 27 28 return &withConstraintName{cause: err, constraint: constraint} 29 } 30 31 // GetConstraintName attempts to unwrap and find a Severity. 32 func GetConstraintName(err error) string { 33 if c := (*withConstraintName)(nil); errors.As(err, &c) { 34 return c.constraint 35 } 36 return "" 37 } 38 39 type withConstraintName struct { 40 cause error 41 constraint string 42 } 43 44 var _ error = (*withConstraintName)(nil) 45 var _ errors.SafeDetailer = (*withConstraintName)(nil) 46 var _ fmt.Formatter = (*withConstraintName)(nil) 47 var _ errors.SafeFormatter = (*withConstraintName)(nil) 48 49 func (w *withConstraintName) Error() string { return w.cause.Error() } 50 func (w *withConstraintName) Cause() error { return w.cause } 51 func (w *withConstraintName) Unwrap() error { return w.cause } 52 func (w *withConstraintName) SafeDetails() []string { 53 // The constraint name is considered PII. 54 return nil 55 } 56 57 func (w *withConstraintName) Format(s fmt.State, verb rune) { errors.FormatError(w, s, verb) } 58 59 func (w *withConstraintName) SafeFormatError(p errors.Printer) (next error) { 60 if p.Detail() { 61 p.Printf("constraint name: %s", w.constraint) 62 } 63 return w.cause 64 } 65 66 func encodeWithConstraintName(_ context.Context, err error) (string, []string, proto.Message) { 67 w := err.(*withConstraintName) 68 return "", nil, &errorspb.StringPayload{Msg: w.constraint} 69 } 70 71 // decodeWithConstraintName is a custom decoder that will be used when decoding 72 // withConstraintName error objects. 73 // Note that as the last argument it takes proto.Message (and not 74 // protoutil.Message which is required by linter) because the latter brings in 75 // additional dependencies into this package and the former is sufficient here. 76 func decodeWithConstraintName( 77 _ context.Context, cause error, _ string, _ []string, payload proto.Message, 78 ) error { 79 m, ok := payload.(*errorspb.StringPayload) 80 if !ok { 81 // If this ever happens, this means some version of the library 82 // (presumably future) changed the payload type, and we're 83 // receiving this here. In this case, give up and let 84 // DecodeError use the opaque type. 85 return nil 86 } 87 return &withConstraintName{cause: cause, constraint: m.Msg} 88 } 89 90 func init() { 91 key := errors.GetTypeKey((*withConstraintName)(nil)) 92 errors.RegisterWrapperEncoder(key, encodeWithConstraintName) 93 errors.RegisterWrapperDecoder(key, decodeWithConstraintName) 94 }