From 43e01b4bca996cd8a17704bb0fb9afa9dc85e8d8 Mon Sep 17 00:00:00 2001 From: Eden Kirin Date: Thu, 20 Jun 2024 00:52:40 +0200 Subject: [PATCH] Time filter --- app/main.go | 18 +++--- app/repository/smartfilter/filterfield.go | 69 +++++++++-------------- app/repository/smartfilter/smartfilter.go | 28 +++++---- 3 files changed, 55 insertions(+), 60 deletions(-) diff --git a/app/main.go b/app/main.go index b9b4a31..1693148 100644 --- a/app/main.go +++ b/app/main.go @@ -8,6 +8,7 @@ import ( "repo-pattern/app/models" "repo-pattern/app/repository" "repo-pattern/app/repository/smartfilter" + "time" "gorm.io/gorm" ) @@ -21,17 +22,20 @@ func doMagic(db *gorm.DB) { var err error query := db - // id, _ := uuid.FromBytes([]byte("6dc096ab-5c03-427e-b808-c669f7446131")) + // id := "6dc096ab-5c03-427e-b808-c669f7446131" // serialNumber := "222" // serialNumberContains := "323" - issuer := "FINA" + // issuer := "FINA" + location, _ := time.LoadLocation("UTC") + createdTime := time.Date(2024, 5, 26, 16, 8, 0, 0, location) f := smartfilter.SmartCertFilter[models.Cert]{ - Alive: &FALSE, - // Id: &id, + // Alive: &FALSE, + // Id: &id, // SerialNumber: &serialNumber, // SerialNumberContains: &serialNumberContains, - IssuerContains: &issuer, + // IssuerContains: &issuer, + CreatedAt_Lt: &createdTime, } query, err = f.ToQuery(query) @@ -41,9 +45,9 @@ func doMagic(db *gorm.DB) { var certs []models.Cert - query.Find(&certs) + query.Order("created_at").Find(&certs) for n, cert := range certs { - fmt.Printf(">> [%d] %+v\n", n, cert.Id) + fmt.Printf(">> [%d] %+v %s\n", n, cert.Id, cert.CreatedAt) } } diff --git a/app/repository/smartfilter/filterfield.go b/app/repository/smartfilter/filterfield.go index bc58810..f82874d 100644 --- a/app/repository/smartfilter/filterfield.go +++ b/app/repository/smartfilter/filterfield.go @@ -3,9 +3,7 @@ package smartfilter import ( "fmt" "reflect" - "strconv" - - "github.com/google/uuid" + "time" ) type FilterField struct { @@ -18,44 +16,25 @@ type FilterField struct { uintValue *uint64 floatValue *float64 strValue *string + timeValue *time.Time } -func (ff *FilterField) getValue(v reflect.Value) string { +func (ff *FilterField) setValueFromReflection(v reflect.Value) { fn := typeGetter(v.Type()) fn(ff, v) - - switch ff.valueKind { - case reflect.Bool: - if *ff.boolValue { - return "TRUE" - } else { - return "FALSE" - } - case reflect.Int: - return strconv.FormatInt(*ff.intValue, 10) - case reflect.Uint: - return strconv.FormatUint(*ff.uintValue, 10) - case reflect.Float32: - return "some float 32" - case reflect.Float64: - return "some float 64" - case reflect.String: - return *ff.strValue - } - return "???" } -func (ff *FilterField) getValueWithOperator(v reflect.Value) string { - value := ff.getValue(v) +// func (ff *FilterField) getValueWithOperator(v reflect.Value) string { +// value := ff.getValue(v) - switch ff.valueKind { - case reflect.Bool: - return fmt.Sprintf("IS %s", value) - case reflect.Int, reflect.Uint, reflect.Float32, reflect.Float64, reflect.String: - return fmt.Sprintf("= %s", value) - } - return "???" -} +// switch ff.valueKind { +// case reflect.Bool: +// return fmt.Sprintf("IS %s", value) +// case reflect.Int, reflect.Uint, reflect.Float32, reflect.Float64, reflect.String: +// return fmt.Sprintf("= %s", value) +// } +// return "???" +// } type valueGetterFunc func(ff *FilterField, v reflect.Value) error @@ -94,12 +73,13 @@ func strValueGetter(ff *FilterField, v reflect.Value) error { return nil } -func uuidValueGetter(ff *FilterField, v reflect.Value) error { - uid, err := uuid.FromBytes([]byte(v.String())) - if err != nil { - return err +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 := uid.String() + value := timeValue.Format(time.RFC3339) + ff.strValue = &value ff.valueKind = reflect.String return nil @@ -144,8 +124,12 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc { return strValueGetter // case reflect.Interface: // return interfaceEncoder - // case reflect.Struct: - // return newStructEncoder(t) + case reflect.Struct: + // check if value type is time + timeType := reflect.TypeOf(time.Time{}) + if t == timeType { + return timeValueGetter + } // case reflect.Map: // return newMapEncoder(t) // case reflect.Slice: @@ -154,9 +138,8 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc { // return newArrayEncoder(t) case reflect.Pointer: return newPtrValueGetter(t) - default: - return unsupportedValueGetter } + return unsupportedValueGetter } type ptrValueGetter struct { diff --git a/app/repository/smartfilter/smartfilter.go b/app/repository/smartfilter/smartfilter.go index 94049be..04f4b05 100644 --- a/app/repository/smartfilter/smartfilter.go +++ b/app/repository/smartfilter/smartfilter.go @@ -5,8 +5,8 @@ import ( "reflect" "slices" "strings" + "time" - "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/schema" ) @@ -29,13 +29,13 @@ var operatorHandlers = map[Operator]handlerFunc{ type SmartCertFilter[T schema.Tabler] struct { Model T - Alive *bool `filterfield:"alive,EQ"` - SerialNumber *string `filterfield:"serial_number,NE"` - SerialNumberContains *string `filterfield:"serial_number,LIKE"` - IssuerContains *string `filterfield:"issuer,ILIKE"` - Id *uuid.UUID `filterfield:"id,EQ"` - Ids *[]uuid.UUID `filterfield:"id,IN"` - CompanyId *uuid.UUID `filterfield:"company_id,EQ"` + Alive *bool `filterfield:"alive,EQ"` + SerialNumber *string `filterfield:"serial_number,NE"` + SerialNumberContains *string `filterfield:"serial_number,LIKE"` + IssuerContains *string `filterfield:"issuer,ILIKE"` + Id *string `filterfield:"id,EQ"` + Ids *[]string `filterfield:"id,IN"` + CreatedAt_Lt *time.Time `filterfield:"created_at,LT"` } func (f SmartCertFilter[T]) ToQuery(query *gorm.DB) (*gorm.DB, error) { @@ -72,8 +72,8 @@ func (f SmartCertFilter[T]) ToQuery(query *gorm.DB) (*gorm.DB, error) { return nil, fmt.Errorf("%s.%s: %s", modelName, field.Name, err) } - strValue := filterField.getValue(fieldReflect) - fmt.Printf(">>> filterField: %+v ==== %s\n", filterField, strValue) + // must be called! + filterField.setValueFromReflection(fieldReflect) operatorHandler, ok := operatorHandlers[filterField.Operator] if !ok { @@ -173,6 +173,8 @@ func handleOperatorGT(query *gorm.DB, tableName string, filterField *FilterField query = applyFilterGT(query, tableName, filterField, *filterField.uintValue) case reflect.Float32, reflect.Float64: query = applyFilterGT(query, tableName, filterField, *filterField.floatValue) + case reflect.String: + query = applyFilterGT(query, tableName, filterField, *filterField.strValue) default: return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) } @@ -193,6 +195,8 @@ func handleOperatorGE(query *gorm.DB, tableName string, filterField *FilterField query = applyFilterGE(query, tableName, filterField, *filterField.uintValue) case reflect.Float32, reflect.Float64: query = applyFilterGE(query, tableName, filterField, *filterField.floatValue) + case reflect.String: + query = applyFilterGE(query, tableName, filterField, *filterField.strValue) default: return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) } @@ -213,6 +217,8 @@ func handleOperatorLT(query *gorm.DB, tableName string, filterField *FilterField query = applyFilterLT(query, tableName, filterField, *filterField.uintValue) case reflect.Float32, reflect.Float64: query = applyFilterLT(query, tableName, filterField, *filterField.floatValue) + case reflect.String: + query = applyFilterLT(query, tableName, filterField, *filterField.strValue) default: return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) } @@ -233,6 +239,8 @@ func handleOperatorLE(query *gorm.DB, tableName string, filterField *FilterField query = applyFilterLE(query, tableName, filterField, *filterField.uintValue) case reflect.Float32, reflect.Float64: query = applyFilterLE(query, tableName, filterField, *filterField.floatValue) + case reflect.String: + query = applyFilterLE(query, tableName, filterField, *filterField.strValue) default: return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) }