package sq import ( "errors" "fmt" "gogs.mikescher.com/BlackForestBytes/goext/langext" "time" ) //TODO UNFINISHED // this is not finished // idea was that we can register converter in the database struct // they get inherited from the transactions // and when marshallingunmarshaling (sq.Query | sq.QueryAll) // or marshaling (sq.InsertSingle) // the types get converter automatically... type DBTypeConverter interface { ModelTypeString() string DBTypeString() string ModelToDB(v any) (any, error) DBToModel(v any) (any, error) } var ConverterBoolToBit = NewDBTypeConverter[bool, int](func(v bool) (int, error) { return langext.Conditional(v, 1, 0), nil }, func(v int) (bool, error) { if v == 0 { return false, nil } if v == 1 { return true, nil } return false, errors.New(fmt.Sprintf("invalid valud for boolean: '%d'", v)) }) var ConverterTimeToUnixMillis = NewDBTypeConverter[time.Time, int64](func(v time.Time) (int64, error) { return v.UnixMilli(), nil }, func(v int64) (time.Time, error) { return time.UnixMilli(v), nil }) var ConverterOptTimeToUnixMillis = NewDBTypeConverter[*time.Time, *int64](func(v *time.Time) (*int64, error) { if v == nil { return nil, nil } return langext.Ptr(v.UnixMilli()), nil }, func(v *int64) (*time.Time, error) { if v == nil { return nil, nil } return langext.Ptr(time.UnixMilli(*v)), nil }) type dbTypeConverterImpl[TModelData any, TDBData any] struct { dbTypeString string modelTypeString string todb func(v TModelData) (TDBData, error) tomodel func(v TDBData) (TModelData, error) } func (t *dbTypeConverterImpl[TModelData, TDBData]) ModelTypeString() string { return t.modelTypeString } func (t *dbTypeConverterImpl[TModelData, TDBData]) DBTypeString() string { return t.dbTypeString } func (t *dbTypeConverterImpl[TModelData, TDBData]) ModelToDB(v any) (any, error) { if vv, ok := v.(TModelData); ok { return t.todb(vv) } return nil, errors.New(fmt.Sprintf("Unexpected value in DBTypeConverter, expected '%s', found '%T'", t.modelTypeString, v)) } func (t *dbTypeConverterImpl[TModelData, TDBData]) DBToModel(v any) (any, error) { if vv, ok := v.(TDBData); ok { return t.tomodel(vv) } return nil, errors.New(fmt.Sprintf("Unexpected value in DBTypeConverter, expected '%s', found '%T'", t.dbTypeString, v)) } func NewDBTypeConverter[TModelData any, TDBData any](todb func(v TModelData) (TDBData, error), tomodel func(v TDBData) (TModelData, error)) DBTypeConverter { return &dbTypeConverterImpl[TModelData, TDBData]{ dbTypeString: fmt.Sprintf("%T", *new(TDBData)), modelTypeString: fmt.Sprintf("%T", *new(TModelData)), todb: todb, tomodel: tomodel, } }