Filter field getters
This commit is contained in:
@ -7,7 +7,9 @@ import (
|
|||||||
"repo-pattern/app/lib/logging"
|
"repo-pattern/app/lib/logging"
|
||||||
"repo-pattern/app/models"
|
"repo-pattern/app/models"
|
||||||
"repo-pattern/app/repository"
|
"repo-pattern/app/repository"
|
||||||
|
"repo-pattern/app/repository/smartfilter"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,8 +22,11 @@ func doMagic(db *gorm.DB) {
|
|||||||
var err error
|
var err error
|
||||||
query := db
|
query := db
|
||||||
|
|
||||||
f := repository.SmartCertFilter[models.Cert]{
|
id, _ := uuid.FromBytes([]byte("6dc096ab-5c03-427e-b808-c669f7446131"))
|
||||||
|
|
||||||
|
f := smartfilter.SmartCertFilter[models.Cert]{
|
||||||
Alive: &TRUE,
|
Alive: &TRUE,
|
||||||
|
Id: &id,
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err = f.ToQuery(query)
|
query, err = f.ToQuery(query)
|
||||||
|
|||||||
105
app/repository/smartfilter/filterfield.go
Normal file
105
app/repository/smartfilter/filterfield.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package smartfilter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type valueGetterFunc func(ff *FilterField, v reflect.Value) error
|
||||||
|
|
||||||
|
type FilterField struct {
|
||||||
|
Name string
|
||||||
|
Operator Operator
|
||||||
|
|
||||||
|
boolValue bool
|
||||||
|
intValue int64
|
||||||
|
uintValue uint64
|
||||||
|
floatValue float64
|
||||||
|
strValue string
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
ff.boolValue = v.Bool()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func intValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
ff.intValue = v.Int()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uintValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
ff.uintValue = v.Uint()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func floatValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
ff.floatValue = v.Float()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func strValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
ff.strValue = v.String()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uuidValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
uid, err := uuid.FromBytes([]byte(v.String()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ff.strValue = uid.String()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsupportedValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
|
return fmt.Errorf("unsupported type: %v", v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc {
|
||||||
|
// If we have a non-pointer value whose type implements
|
||||||
|
// Marshaler with a value receiver, then we're better off taking
|
||||||
|
// the address of the value - otherwise we end up with an
|
||||||
|
// allocation as we cast the value to an interface.
|
||||||
|
// if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
|
||||||
|
// return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
|
||||||
|
// }
|
||||||
|
// if t.Implements(marshalerType) {
|
||||||
|
// return marshalerEncoder
|
||||||
|
// }
|
||||||
|
// if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
|
||||||
|
// return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
|
||||||
|
// }
|
||||||
|
// if t.Implements(textMarshalerType) {
|
||||||
|
// return textMarshalerEncoder
|
||||||
|
// }
|
||||||
|
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
return boolValueGetter
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return intValueGetter
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return uintValueGetter
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return floatValueGetter
|
||||||
|
case reflect.String:
|
||||||
|
return strValueGetter
|
||||||
|
// case reflect.Interface:
|
||||||
|
// return interfaceEncoder
|
||||||
|
// case reflect.Struct:
|
||||||
|
// return newStructEncoder(t)
|
||||||
|
// case reflect.Map:
|
||||||
|
// return newMapEncoder(t)
|
||||||
|
// case reflect.Slice:
|
||||||
|
// return newSliceEncoder(t)
|
||||||
|
// case reflect.Array:
|
||||||
|
// return newArrayEncoder(t)
|
||||||
|
// case reflect.Pointer:
|
||||||
|
// return newPtrEncoder(t)
|
||||||
|
default:
|
||||||
|
return unsupportedValueGetter
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package repository
|
package smartfilter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -23,11 +23,6 @@ const (
|
|||||||
|
|
||||||
var OPERATORS = []Operator{OperatorEQ, OperatorIN}
|
var OPERATORS = []Operator{OperatorEQ, OperatorIN}
|
||||||
|
|
||||||
type FilterField struct {
|
|
||||||
Name string
|
|
||||||
Operator Operator
|
|
||||||
}
|
|
||||||
|
|
||||||
type SmartCertFilter[T schema.Tabler] struct {
|
type SmartCertFilter[T schema.Tabler] struct {
|
||||||
Model T
|
Model T
|
||||||
Alive *bool `filterfield:"alive,EQ"`
|
Alive *bool `filterfield:"alive,EQ"`
|
||||||
@ -40,33 +35,46 @@ func (f SmartCertFilter[T]) ToQuery(query *gorm.DB) (*gorm.DB, error) {
|
|||||||
tableName := f.Model.TableName()
|
tableName := f.Model.TableName()
|
||||||
|
|
||||||
fmt.Printf("Table name: %s\n", tableName)
|
fmt.Printf("Table name: %s\n", tableName)
|
||||||
fmt.Printf("%+v\n", f)
|
// fmt.Printf("%+v\n", f)
|
||||||
|
|
||||||
st := reflect.TypeOf(f)
|
st := reflect.TypeOf(f)
|
||||||
modelName := st.Name()
|
modelName := st.Name()
|
||||||
|
reflectValue := reflect.ValueOf(f)
|
||||||
|
|
||||||
for i := 0; i < st.NumField(); i++ {
|
for i := 0; i < st.NumField(); i++ {
|
||||||
field := st.Field(i)
|
field := st.Field(i)
|
||||||
tagValue := field.Tag.Get(TAG_NAME)
|
tagValue := field.Tag.Get(TAG_NAME)
|
||||||
|
|
||||||
|
// skip field if filter tag is not present
|
||||||
if len(tagValue) == 0 {
|
if len(tagValue) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fieldReflect := reflectValue.FieldByName(field.Name)
|
||||||
|
|
||||||
|
// skip field if value is nil
|
||||||
|
if fieldReflect.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t := fieldReflect.Type()
|
||||||
|
fmt.Printf(">>> %+v --- %+v\n", field, t)
|
||||||
|
|
||||||
filterField, err := getFilterField(tagValue)
|
filterField, err := getFilterField(tagValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s.%s: %s", modelName, field.Name, err)
|
return nil, fmt.Errorf("%s.%s: %s", modelName, field.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(
|
// fmt.Printf(
|
||||||
"tagValue: %s, Name: %s, Operator: %s\n",
|
// "tagValue: %s, Name: %s, Operator: %s\n",
|
||||||
tagValue,
|
// tagValue,
|
||||||
filterField.Name,
|
// filterField.Name,
|
||||||
filterField.Operator,
|
// filterField.Operator,
|
||||||
)
|
// )
|
||||||
|
|
||||||
switch filterField.Operator {
|
switch filterField.Operator {
|
||||||
case OperatorEQ:
|
case OperatorEQ:
|
||||||
query = applyFilterEQ(query, tableName, filterField)
|
query = applyFilterEQ[string](query, tableName, filterField)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +83,9 @@ func (f SmartCertFilter[T]) ToQuery(query *gorm.DB) (*gorm.DB, error) {
|
|||||||
return query, nil
|
return query, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyFilterEQ(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB {
|
func applyFilterEQ[T int | bool | string](query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB {
|
||||||
|
// query = query.Where(fmt.Sprint("%s.%s = ?", tableName, filterField.Name), )
|
||||||
|
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user