|
package types
import (
"database/sql"
"errors"
"fmt"
"regexp"
"strings"
"github.com/RedHatInsights/insights-operator-utils/types"
"github.com/lib/pq"
"github.com/rs/zerolog/log"
)
type (
|
ValidationError validation error, for example when string is longer then expected
|
ValidationError = types . ValidationError
|
ItemNotFoundError shows that item with id ItemID wasn't found in the storage
|
ItemNotFoundError = types . ItemNotFoundError
)
|
ErrOldReport is an error returned if a more recent already
exists on the storage while attempting to write a report for a cluster.
|
var ErrOldReport = types . ErrOldReport
|
ErrEmptyReport is an error returned if an empty report or a report with
only empty attributes is found in the parsed message
|
var ErrEmptyReport = errors . New ( "empty report found in deserialized message" )
|
TableNotFoundError table not found error
|
type TableNotFoundError struct {
tableName string
}
|
Error returns error string
|
func ( err * TableNotFoundError ) Error ( ) string {
return fmt . Sprintf ( "no such table: %v" , err . tableName )
}
|
TableAlreadyExistsError represents table already exists error
|
type TableAlreadyExistsError struct {
tableName string
}
|
Error returns error string
|
func ( err * TableAlreadyExistsError ) Error ( ) string {
return fmt . Sprintf ( "table %v already exists" , err . tableName )
}
|
ForeignKeyError something violates foreign key error
|
type ForeignKeyError struct {
TableName string
ForeignKeyName string
|
Details can reveal you information about specific item violating fk
|
Details string
}
|
Error returns error string
|
func ( err * ForeignKeyError ) Error ( ) string {
return fmt . Sprintf (
`operation violates foreign key "%v" on table "%v"` , err . ForeignKeyName , err . TableName ,
)
}
|
ConvertDBError converts sql errors to those defined in this package
|
func ConvertDBError ( err error , itemID interface { } ) error {
if err == nil {
return nil
}
if err == sql . ErrNoRows {
if itemIDArray , ok := itemID . ( [ ] interface { } ) ; ok {
var strArray [ ] string
for _ , item := range itemIDArray {
strArray = append ( strArray , fmt . Sprint ( item ) )
}
itemID = strings . Join ( strArray , "/" )
}
return & ItemNotFoundError { ItemID : itemID }
}
err = convertPostgresError ( err )
return err
}
func regexGetFirstMatchOrLogError ( regexStr , str string ) string {
return regexGetNthMatchOrLogError ( regexStr , 1 , str )
}
func regexGetNthMatchOrLogError ( regexStr string , nMatch uint , str string ) string {
match , err := regexGetNthMatch ( regexStr , nMatch , str )
if err != nil {
log . Error ( ) .
Str ( "regex" , regexStr ) .
Str ( "str" , str ) .
Msg ( "unable to get first match from string" )
return ""
}
return match
}
func regexGetNthMatch ( regexStr string , nMatch uint , str string ) ( string , error ) {
regex := regexp . MustCompile ( regexStr )
if ! regex . MatchString ( str ) {
return "" , errors . New ( "regex doesn't match string" )
}
matches := regex . FindStringSubmatch ( str )
if uint ( len ( matches ) ) < nMatch + 1 {
return "" , errors . New ( "regexGetNthMatch unable to find match" )
}
return matches [ nMatch ] , nil
}
func convertPostgresError ( err error ) error {
pqError , ok := err . ( * pq . Error )
if ! ok {
return err
}
|
see https://www.postgresql.org/docs/current/errcodes-appendix.html to get the magic happening below
|
switch pqError . Code {
case pgDuplicateTableErrorCode :
return & TableAlreadyExistsError {
tableName : regexGetFirstMatchOrLogError ( `relation "(.+)" already exists` , pqError . Message ) ,
}
case pgUndefinedTableErrorCode :
return & TableNotFoundError {
tableName : regexGetNthMatchOrLogError ( `(table|relation) "(.+)" does not exist` , 2 , pqError . Message ) ,
}
case pgForeignKeyViolationErrorCode :
|
for some reason field Table is filled not in all errors
|
return & ForeignKeyError {
TableName : pqError . Table ,
ForeignKeyName : pqError . Constraint ,
Details : pqError . Detail ,
}
}
return err
}
|