Time filter

This commit is contained in:
Eden Kirin
2024-06-20 00:52:40 +02:00
parent 8f4ea5b648
commit 43e01b4bca
3 changed files with 55 additions and 60 deletions

View File

@ -8,6 +8,7 @@ import (
"repo-pattern/app/models" "repo-pattern/app/models"
"repo-pattern/app/repository" "repo-pattern/app/repository"
"repo-pattern/app/repository/smartfilter" "repo-pattern/app/repository/smartfilter"
"time"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -21,17 +22,20 @@ func doMagic(db *gorm.DB) {
var err error var err error
query := db query := db
// id, _ := uuid.FromBytes([]byte("6dc096ab-5c03-427e-b808-c669f7446131")) // id := "6dc096ab-5c03-427e-b808-c669f7446131"
// serialNumber := "222" // serialNumber := "222"
// serialNumberContains := "323" // 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]{ f := smartfilter.SmartCertFilter[models.Cert]{
Alive: &FALSE, // Alive: &FALSE,
// Id: &id, // Id: &id,
// SerialNumber: &serialNumber, // SerialNumber: &serialNumber,
// SerialNumberContains: &serialNumberContains, // SerialNumberContains: &serialNumberContains,
IssuerContains: &issuer, // IssuerContains: &issuer,
CreatedAt_Lt: &createdTime,
} }
query, err = f.ToQuery(query) query, err = f.ToQuery(query)
@ -41,9 +45,9 @@ func doMagic(db *gorm.DB) {
var certs []models.Cert var certs []models.Cert
query.Find(&certs) query.Order("created_at").Find(&certs)
for n, cert := range 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)
} }
} }

View File

@ -3,9 +3,7 @@ package smartfilter
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"strconv" "time"
"github.com/google/uuid"
) )
type FilterField struct { type FilterField struct {
@ -18,44 +16,25 @@ type FilterField struct {
uintValue *uint64 uintValue *uint64
floatValue *float64 floatValue *float64
strValue *string 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 := typeGetter(v.Type())
fn(ff, v) 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 { // func (ff *FilterField) getValueWithOperator(v reflect.Value) string {
value := ff.getValue(v) // value := ff.getValue(v)
switch ff.valueKind { // switch ff.valueKind {
case reflect.Bool: // case reflect.Bool:
return fmt.Sprintf("IS %s", value) // return fmt.Sprintf("IS %s", value)
case reflect.Int, reflect.Uint, reflect.Float32, reflect.Float64, reflect.String: // case reflect.Int, reflect.Uint, reflect.Float32, reflect.Float64, reflect.String:
return fmt.Sprintf("= %s", value) // return fmt.Sprintf("= %s", value)
} // }
return "???" // return "???"
} // }
type valueGetterFunc func(ff *FilterField, v reflect.Value) error type valueGetterFunc func(ff *FilterField, v reflect.Value) error
@ -94,12 +73,13 @@ func strValueGetter(ff *FilterField, v reflect.Value) error {
return nil return nil
} }
func uuidValueGetter(ff *FilterField, v reflect.Value) error { func timeValueGetter(ff *FilterField, v reflect.Value) error {
uid, err := uuid.FromBytes([]byte(v.String())) timeValue, ok := v.Interface().(time.Time)
if err != nil { if !ok {
return err return fmt.Errorf("error converting interface to time")
} }
value := uid.String() value := timeValue.Format(time.RFC3339)
ff.strValue = &value ff.strValue = &value
ff.valueKind = reflect.String ff.valueKind = reflect.String
return nil return nil
@ -144,8 +124,12 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc {
return strValueGetter return strValueGetter
// case reflect.Interface: // case reflect.Interface:
// return interfaceEncoder // return interfaceEncoder
// case reflect.Struct: case reflect.Struct:
// return newStructEncoder(t) // check if value type is time
timeType := reflect.TypeOf(time.Time{})
if t == timeType {
return timeValueGetter
}
// case reflect.Map: // case reflect.Map:
// return newMapEncoder(t) // return newMapEncoder(t)
// case reflect.Slice: // case reflect.Slice:
@ -154,9 +138,8 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc {
// return newArrayEncoder(t) // return newArrayEncoder(t)
case reflect.Pointer: case reflect.Pointer:
return newPtrValueGetter(t) return newPtrValueGetter(t)
default:
return unsupportedValueGetter
} }
return unsupportedValueGetter
} }
type ptrValueGetter struct { type ptrValueGetter struct {

View File

@ -5,8 +5,8 @@ import (
"reflect" "reflect"
"slices" "slices"
"strings" "strings"
"time"
"github.com/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/schema" "gorm.io/gorm/schema"
) )
@ -33,9 +33,9 @@ type SmartCertFilter[T schema.Tabler] struct {
SerialNumber *string `filterfield:"serial_number,NE"` SerialNumber *string `filterfield:"serial_number,NE"`
SerialNumberContains *string `filterfield:"serial_number,LIKE"` SerialNumberContains *string `filterfield:"serial_number,LIKE"`
IssuerContains *string `filterfield:"issuer,ILIKE"` IssuerContains *string `filterfield:"issuer,ILIKE"`
Id *uuid.UUID `filterfield:"id,EQ"` Id *string `filterfield:"id,EQ"`
Ids *[]uuid.UUID `filterfield:"id,IN"` Ids *[]string `filterfield:"id,IN"`
CompanyId *uuid.UUID `filterfield:"company_id,EQ"` CreatedAt_Lt *time.Time `filterfield:"created_at,LT"`
} }
func (f SmartCertFilter[T]) ToQuery(query *gorm.DB) (*gorm.DB, error) { 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) return nil, fmt.Errorf("%s.%s: %s", modelName, field.Name, err)
} }
strValue := filterField.getValue(fieldReflect) // must be called!
fmt.Printf(">>> filterField: %+v ==== %s\n", filterField, strValue) filterField.setValueFromReflection(fieldReflect)
operatorHandler, ok := operatorHandlers[filterField.Operator] operatorHandler, ok := operatorHandlers[filterField.Operator]
if !ok { if !ok {
@ -173,6 +173,8 @@ func handleOperatorGT(query *gorm.DB, tableName string, filterField *FilterField
query = applyFilterGT(query, tableName, filterField, *filterField.uintValue) query = applyFilterGT(query, tableName, filterField, *filterField.uintValue)
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
query = applyFilterGT(query, tableName, filterField, *filterField.floatValue) query = applyFilterGT(query, tableName, filterField, *filterField.floatValue)
case reflect.String:
query = applyFilterGT(query, tableName, filterField, *filterField.strValue)
default: default:
return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) 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) query = applyFilterGE(query, tableName, filterField, *filterField.uintValue)
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
query = applyFilterGE(query, tableName, filterField, *filterField.floatValue) query = applyFilterGE(query, tableName, filterField, *filterField.floatValue)
case reflect.String:
query = applyFilterGE(query, tableName, filterField, *filterField.strValue)
default: default:
return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) 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) query = applyFilterLT(query, tableName, filterField, *filterField.uintValue)
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
query = applyFilterLT(query, tableName, filterField, *filterField.floatValue) query = applyFilterLT(query, tableName, filterField, *filterField.floatValue)
case reflect.String:
query = applyFilterLT(query, tableName, filterField, *filterField.strValue)
default: default:
return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) 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) query = applyFilterLE(query, tableName, filterField, *filterField.uintValue)
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
query = applyFilterLE(query, tableName, filterField, *filterField.floatValue) query = applyFilterLE(query, tableName, filterField, *filterField.floatValue)
case reflect.String:
query = applyFilterLE(query, tableName, filterField, *filterField.strValue)
default: default:
return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator) return nil, fmt.Errorf("invalid field type for operator %s", filterField.Operator)
} }