diff --git a/app/main.go b/app/main.go index 8d2834e..4e6d4b4 100644 --- a/app/main.go +++ b/app/main.go @@ -10,6 +10,7 @@ import ( "repo-pattern/app/repository/smartfilter" "time" + "github.com/google/uuid" "gorm.io/gorm" ) @@ -19,14 +20,15 @@ var ( ) type CertFilter struct { - Alive *bool `filterfield:"field=alive,operator=EQ"` - SerialNumber *string `filterfield:"field=serial_number,operator=NE"` - SerialNumberContains *string `filterfield:"field=serial_number,operator=LIKE"` - IssuerContains *string `filterfield:"field=issuer,operator=ILIKE"` - Id *string `filterfield:"field=id,operator=EQ"` - Ids *[]string `filterfield:"field=id,operator=IN"` - IdsNot *[]string `filterfield:"field=id,operator=NOT_IN"` - CreatedAt_Lt *time.Time `filterfield:"field=created_at,operator=LT"` + Alive *bool `filterfield:"field=alive,operator=EQ"` + SerialNumber *string `filterfield:"field=serial_number,operator=NE"` + SerialNumberContains *string `filterfield:"field=serial_number,operator=LIKE"` + IssuerContains *string `filterfield:"field=issuer,operator=ILIKE"` + Id *uuid.UUID `filterfield:"field=id,operator=EQ"` + Ids *[]uuid.UUID `filterfield:"field=id,operator=IN"` + IdsNot *[]string `filterfield:"field=id,operator=NOT_IN"` + CreatedAt_Lt *time.Time `filterfield:"field=created_at,operator=LT"` + Timestamps *[]time.Time `filterfield:"field=created_at,operator=IN"` } func doMagic(db *gorm.DB) { @@ -37,9 +39,14 @@ func doMagic(db *gorm.DB) { // serialNumber := "222" // serialNumberContains := "323" // issuer := "FINA" - // location, _ := time.LoadLocation("UTC") - // createdTime := time.Date(2024, 5, 26, 16, 8, 0, 0, location) - ids := []string{"eb2bcac6-5173-4dbb-93b7-e7c03b924a03", "db9fb837-3483-4736-819d-f427dc8cda23", "1fece5e7-8e8d-4828-8298-3b1f07fd29ff"} + location, _ := time.LoadLocation("UTC") + createdTime := time.Date(2024, 5, 26, 16, 8, 0, 0, location) + + id1, _ := uuid.Parse("eb2bcac6-5173-4dbb-93b7-e7c03b924a03") + id2, _ := uuid.Parse("db9fb837-3483-4736-819d-f427dc8cda23") + id3, _ := uuid.Parse("1fece5e7-8e8d-4828-8298-3b1f07fd29ff") + + ids := []uuid.UUID{id1, id2, id3} filter := CertFilter{ // Alive: &FALSE, @@ -48,7 +55,7 @@ func doMagic(db *gorm.DB) { // SerialNumberContains: &serialNumberContains, Ids: &ids, // IssuerContains: &issuer, - // CreatedAt_Lt: &createdTime, + CreatedAt_Lt: &createdTime, } query, err = smartfilter.ToQuery(models.Cert{}, filter, query) @@ -86,7 +93,7 @@ func doGet(db *gorm.DB) { repo := repository.RepoBase[models.Cert]{} repo.Init(db) - id := "db9fb837-3483-4736-819d-f427dc8cda23" + id, _ := uuid.Parse("db9fb837-3483-4736-819d-f427dc8cda23") filter := CertFilter{ Id: &id, @@ -103,7 +110,7 @@ func doExists(db *gorm.DB) { repo := repository.RepoBase[models.Cert]{} repo.Init(db) - id := "db9fb837-3483-4736-819d-f427dc8cda23" + id, _ := uuid.Parse("db9fb837-3483-4736-819d-f427dc8cda23") filter := CertFilter{ Id: &id, diff --git a/app/repository/repository_test.go b/app/repository/repository_test.go index 690640f..0812be3 100644 --- a/app/repository/repository_test.go +++ b/app/repository/repository_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/DATA-DOG/go-sqlmock" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -32,7 +33,7 @@ func NewMockDB() (*sql.DB, *gorm.DB, sqlmock.Sqlmock) { } type MyModel struct { - Id int + Id uuid.UUID Value string Count int } @@ -42,9 +43,9 @@ func (m MyModel) TableName() string { } type MyModelFilter struct { - Id *int `filterfield:"field=id,operator=EQ"` - Value *string `filterfield:"field=value,operator=EQ"` - Count *int `filterfield:"field=count,operator=GT"` + Id *uuid.UUID `filterfield:"field=id,operator=EQ"` + Value *string `filterfield:"field=value,operator=EQ"` + Count *int `filterfield:"field=count,operator=GT"` } func TestListMethod(t *testing.T) { @@ -166,7 +167,7 @@ func TestListMethod(t *testing.T) { repo := RepoBase[MyModel]{} repo.Init(db) - id := 123 + id := uuid.New() filter := MyModelFilter{ Id: &id, } @@ -190,7 +191,7 @@ func TestListMethod(t *testing.T) { repo := RepoBase[MyModel]{} repo.Init(db) - id := 123 + id := uuid.New() count := 456 value := "some value" filter := MyModelFilter{ @@ -218,7 +219,7 @@ func TestListMethod(t *testing.T) { repo := RepoBase[MyModel]{} repo.Init(db) - id := 123 + id := uuid.New() count := 456 value := "some value" filter := MyModelFilter{ diff --git a/app/repository/smartfilter/filterfield.go b/app/repository/smartfilter/filterfield.go index 1593cdc..a4cf4b8 100644 --- a/app/repository/smartfilter/filterfield.go +++ b/app/repository/smartfilter/filterfield.go @@ -4,6 +4,8 @@ import ( "fmt" "reflect" "time" + + "github.com/google/uuid" ) type FilterField struct { @@ -131,17 +133,41 @@ func strValueGetter(ff *FilterField, v reflect.Value) error { } func timeValueGetter(ff *FilterField, v reflect.Value) error { - timeValue, ok := v.Interface().(time.Time) - if !ok { - return fmt.Errorf("error converting interface to time") + value, err := timeValueToStr(v) + if err != nil { + return err } - value := timeValue.Format(time.RFC3339) - ff.strValue = &value ff.valueKind = reflect.String return nil } +func uuidValueGetter(ff *FilterField, v reflect.Value) error { + value, err := uuidValueToStr(v) + if err != nil { + return err + } + ff.strValue = &value + ff.valueKind = reflect.String + return nil +} + +func timeValueToStr(v reflect.Value) (string, error) { + value, ok := v.Interface().(time.Time) + if !ok { + return "", fmt.Errorf("error converting interface to time") + } + return value.Format(time.RFC3339), nil +} + +func uuidValueToStr(v reflect.Value) (string, error) { + value, ok := v.Interface().(uuid.UUID) + if !ok { + return "", fmt.Errorf("error converting interface to uuid") + } + return value.String(), nil +} + func unsupportedValueGetter(ff *FilterField, v reflect.Value) error { return fmt.Errorf("unsupported type: %v", v.Type()) } @@ -183,16 +209,18 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc { // return interfaceEncoder case reflect.Struct: // check if value type is time - timeType := reflect.TypeOf(time.Time{}) - if t == timeType { + if t == reflect.TypeOf(time.Time{}) { return timeValueGetter } // case reflect.Map: // return newMapEncoder(t) case reflect.Slice: return newSliceGetter(t) - // case reflect.Array: - // return newArrayGetter(t) + case reflect.Array: + if t == reflect.TypeOf(uuid.UUID{}) { + return uuidValueGetter + } + return newArrayGetter(t) case reflect.Pointer: return newPtrValueGetter(t) } @@ -246,6 +274,22 @@ func (sg sliceGetter) getValue(ff *FilterField, v reflect.Value) error { ff.appendFloat(element.Float()) case reflect.String: ff.appendStr(element.String()) + case reflect.Struct: + if element.Type() == reflect.TypeOf(time.Time{}) { + value, err := timeValueToStr(element) + if err != nil { + return err + } + ff.appendStr(value) + } + case reflect.Array: + if element.Type() == reflect.TypeOf(uuid.UUID{}) { + value, err := uuidValueToStr(element) + if err != nil { + return err + } + ff.appendStr(value) + } } } return nil