From b67bc14e5e437f3436114e7b7fe92f405e7c12e0 Mon Sep 17 00:00:00 2001 From: Eden Kirin Date: Sat, 22 Jun 2024 21:59:39 +0200 Subject: [PATCH] Working arrays --- app/inheritance/inheritance.go | 74 ------------- app/inheritance/methods.go | 43 -------- app/main.go | 19 ++-- app/repository/smartfilter/filterfield.go | 126 ++++++++++++++++++---- app/repository/smartfilter/filters.go | 10 +- app/repository/smartfilter/handlers.go | 26 ++++- app/repository/smartfilter/operators.go | 21 ++-- app/repository/smartfilter/smartfilter.go | 22 ++-- 8 files changed, 171 insertions(+), 170 deletions(-) delete mode 100644 app/inheritance/inheritance.go delete mode 100644 app/inheritance/methods.go diff --git a/app/inheritance/inheritance.go b/app/inheritance/inheritance.go deleted file mode 100644 index 2f0ca61..0000000 --- a/app/inheritance/inheritance.go +++ /dev/null @@ -1,74 +0,0 @@ -package inheritance - -import "fmt" - -type Model struct{} - -type MyModel struct { - Model -} - -type MethodInitInterface interface { - Init(dbConn int) -} - -type RepoBase[T interface{}] struct { - DbConn int - GetMethod[T] - ListMethod[T] - methods []MethodInitInterface -} - -func (b *RepoBase[T]) InitMethods(dbConn int) { - for _, method := range b.methods { - method.Init(dbConn) - } -} - -type CRUDRepo[T interface{}] struct { - RepoBase[T] - SaveMethod[T] -} - -func (m *CRUDRepo[T]) Init(dbConn int) { - m.methods = []MethodInitInterface{&m.GetMethod, &m.ListMethod, &m.SaveMethod} - m.InitMethods(dbConn) -} - -func DoInheritanceTest() { - repo := RepoBase[MyModel]{ - DbConn: 111, - // GetMethod: GetMethod{ - // DbConn: 666, - // }, - // ListMethod: ListMethod{ - // DbConn: 777, - // }, - } - repo.GetMethod.Init(888) - repo.ListMethod.Init(888) - - repo.GetMethod.Get() - repo.List() - - fmt.Printf("outside Base: %d\n", repo.DbConn) - fmt.Printf("outside GetMethod: %d\n", repo.GetMethod.DbConn) - fmt.Printf("outside ListMethod: %d\n", repo.ListMethod.DbConn) - - fmt.Println("----------------") - - crudRepo := CRUDRepo[MyModel]{} - crudRepo.Init(999) - - crudRepo.Get() - crudRepo.List() - crudRepo.Save() - - fmt.Printf("outside GetMethod: %d\n", crudRepo.GetMethod.DbConn) - fmt.Printf("outside ListMethod: %d\n", crudRepo.ListMethod.DbConn) - fmt.Printf("outside SaveMethod: %d\n", crudRepo.SaveMethod.DbConn) - - // repo.DbConn = 123 - // repo.SomeGetVar = 456 - // repo.DoSomething() -} diff --git a/app/inheritance/methods.go b/app/inheritance/methods.go deleted file mode 100644 index 3a46116..0000000 --- a/app/inheritance/methods.go +++ /dev/null @@ -1,43 +0,0 @@ -package inheritance - -import "fmt" - -type GetMethod[T interface{}] struct { - SomeGetVar int - DbConn int -} - -func (m *GetMethod[T]) Init(dbConn int) { - m.DbConn = dbConn -} - -func (m GetMethod[T]) Get() T { - var model T - fmt.Printf("Get DbConn: %d\n", m.DbConn) - return model -} - -type ListMethod[T interface{}] struct { - SomeListVar int - DbConn int -} - -func (m *ListMethod[T]) Init(dbConn int) { - m.DbConn = dbConn -} - -func (m ListMethod[T]) List() { - fmt.Printf("List DbConn: %d\n", m.DbConn) -} - -type SaveMethod[T interface{}] struct { - DbConn int -} - -func (m *SaveMethod[T]) Init(dbConn int) { - m.DbConn = dbConn -} - -func (m SaveMethod[T]) Save() { - fmt.Printf("List DbConn: %d\n", m.DbConn) -} diff --git a/app/main.go b/app/main.go index e0c86b5..30c07a4 100644 --- a/app/main.go +++ b/app/main.go @@ -8,7 +8,6 @@ import ( "repo-pattern/app/models" "repo-pattern/app/repository" "repo-pattern/app/repository/smartfilter" - "time" "gorm.io/gorm" ) @@ -25,19 +24,19 @@ func doMagic(db *gorm.DB) { // id := "6dc096ab-5c03-427e-b808-c669f7446131" // serialNumber := "222" // serialNumberContains := "323" - issuer := "FINA" - location, _ := time.LoadLocation("UTC") - createdTime := time.Date(2024, 5, 26, 16, 8, 0, 0, location) + // 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"} filter := smartfilter.CertFilter{ - Alive: &FALSE, + // Alive: &FALSE, // Id: &id, // SerialNumber: &serialNumber, // SerialNumberContains: &serialNumberContains, - Ids: &ids, - IssuerContains: &issuer, - CreatedAt_Lt: &createdTime, + Ids: &ids, + // IssuerContains: &issuer, + // CreatedAt_Lt: &createdTime, } query, err = smartfilter.ToQuery(models.Cert{}, filter, query) @@ -113,9 +112,9 @@ func main() { db := db.InitDB() repository.Dao = repository.CreateDAO(db) - // doMagic(db) + doMagic(db) // doList(db) // doGet(db) - doExists(db) + // doExists(db) // inheritance.DoInheritanceTest() } diff --git a/app/repository/smartfilter/filterfield.go b/app/repository/smartfilter/filterfield.go index 96455c0..714d433 100644 --- a/app/repository/smartfilter/filterfield.go +++ b/app/repository/smartfilter/filterfield.go @@ -10,12 +10,17 @@ type FilterField struct { Name string Operator Operator - valueKind reflect.Kind - boolValue *bool - intValue *int64 - uintValue *uint64 - floatValue *float64 - strValue *string + valueKind reflect.Kind + boolValue *bool + intValue *int64 + uintValue *uint64 + floatValue *float64 + strValue *string + boolValues *[]bool + intValues *[]int64 + uintValues *[]uint64 + floatValues *[]float64 + strValues *[]string } func (ff *FilterField) setValueFromReflection(v reflect.Value) { @@ -23,6 +28,71 @@ func (ff *FilterField) setValueFromReflection(v reflect.Value) { fn(ff, v) } +func (ff *FilterField) appendStr(value string) { + var valueArray []string + + if ff.strValues == nil { + valueArray = make([]string, 0) + } else { + valueArray = *ff.strValues + } + valueArray = append(valueArray, value) + ff.strValues = &valueArray + ff.valueKind = reflect.String +} + +func (ff *FilterField) appendBool(value bool) { + var valueArray []bool + + if ff.boolValues == nil { + valueArray = make([]bool, 0) + } else { + valueArray = *ff.boolValues + } + valueArray = append(valueArray, value) + ff.boolValues = &valueArray + ff.valueKind = reflect.Bool +} + +func (ff *FilterField) appendInt(value int64) { + var valueArray []int64 + + if ff.boolValues == nil { + valueArray = make([]int64, 0) + } else { + valueArray = *ff.intValues + } + valueArray = append(valueArray, value) + ff.intValues = &valueArray + ff.valueKind = reflect.Int +} + +func (ff *FilterField) appendUint(value uint64) { + var valueArray []uint64 + + if ff.boolValues == nil { + valueArray = make([]uint64, 0) + } else { + valueArray = *ff.uintValues + } + valueArray = append(valueArray, value) + ff.uintValues = &valueArray + ff.valueKind = reflect.Int +} + +func (ff *FilterField) appendFloat(value float64) { + var valueArray []float64 + + if ff.boolValues == nil { + valueArray = make([]float64, 0) + } else { + valueArray = *ff.floatValues + } + valueArray = append(valueArray, value) + ff.floatValues = &valueArray + ff.valueKind = reflect.Int +} + type valueGetterFunc func(ff *FilterField, v reflect.Value) error func boolValueGetter(ff *FilterField, v reflect.Value) error { @@ -121,8 +191,8 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc { // return newMapEncoder(t) case reflect.Slice: return newSliceGetter(t) - case reflect.Array: - return newArrayGetter(t) + // case reflect.Array: + // return newArrayGetter(t) case reflect.Pointer: return newPtrValueGetter(t) } @@ -130,44 +200,64 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc { } type ptrValueGetter struct { - elemEnc valueGetterFunc + elemGetter valueGetterFunc } func (pvg ptrValueGetter) getValue(ff *FilterField, v reflect.Value) error { - pvg.elemEnc(ff, v.Elem()) + pvg.elemGetter(ff, v.Elem()) return nil } func newPtrValueGetter(t reflect.Type) valueGetterFunc { - enc := ptrValueGetter{elemEnc: typeGetter(t.Elem())} + enc := ptrValueGetter{elemGetter: typeGetter(t.Elem())} return enc.getValue } type arrayGetter struct { - elemEnc valueGetterFunc + elemGetter valueGetterFunc } func (ag arrayGetter) getValue(ff *FilterField, v reflect.Value) error { - ag.elemEnc(ff, v.Elem()) + ag.elemGetter(ff, v.Elem()) return nil } func newArrayGetter(t reflect.Type) valueGetterFunc { - enc := arrayGetter{elemEnc: typeGetter(t.Elem())} + enc := arrayGetter{elemGetter: typeGetter(t.Elem())} return enc.getValue } type sliceGetter struct { - elemEnc valueGetterFunc + elemGetter valueGetterFunc } func (sg sliceGetter) getValue(ff *FilterField, v reflect.Value) error { - fmt.Printf("%+v\n", v.Slice(0, 1)) - sg.elemEnc(ff, v.Elem()) + for n := range v.Len() { + element := v.Index(n) + fmt.Printf("ELEMENT: %+v\n", element) + + switch element.Kind() { + case reflect.Bool: + ff.appendBool(element.Bool()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + ff.appendInt(element.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + ff.appendUint(element.Uint()) + case reflect.Float32, reflect.Float64: + ff.appendFloat(element.Float()) + case reflect.String: + ff.appendStr(element.String()) + } + } + fmt.Println(v.Len()) + fmt.Printf(">>> getValue %+v\n", v) + fmt.Printf(">>> ff %+v\n", ff.strValues) + // fmt.Printf("%+v\n", v.Slice(0, 1)) + // sg.elemGetter(ff, v.Elem()) return nil } func newSliceGetter(t reflect.Type) valueGetterFunc { - enc := sliceGetter{elemEnc: typeGetter(t.Elem())} + enc := sliceGetter{elemGetter: newArrayGetter(t)} return enc.getValue } diff --git a/app/repository/smartfilter/filters.go b/app/repository/smartfilter/filters.go index 7cc77e1..5a1cb40 100644 --- a/app/repository/smartfilter/filters.go +++ b/app/repository/smartfilter/filters.go @@ -51,7 +51,13 @@ func applyFilterLE[T bool | int64 | uint64 | float64 | string]( } func applyFilterIN[T bool | int64 | uint64 | float64 | string]( - query *gorm.DB, tableName string, filterField *FilterField, value T, + query *gorm.DB, tableName string, filterField *FilterField, value *[]T, ) *gorm.DB { - return query.Where(fmt.Sprintf("%s.%s IN ?", tableName, filterField.Name), value) + return query.Where(fmt.Sprintf("%s.%s IN (?)", tableName, filterField.Name), *value) +} + +func applyFilterNOT_IN[T bool | int64 | uint64 | float64 | string]( + query *gorm.DB, tableName string, filterField *FilterField, value *[]T, +) *gorm.DB { + return query.Where(fmt.Sprintf("%s.%s NOT IN (?)", tableName, filterField.Name), *value) } diff --git a/app/repository/smartfilter/handlers.go b/app/repository/smartfilter/handlers.go index 68ce695..332b1ff 100644 --- a/app/repository/smartfilter/handlers.go +++ b/app/repository/smartfilter/handlers.go @@ -112,14 +112,32 @@ func handleOperatorLE(query *gorm.DB, tableName string, filterField *FilterField func handleOperatorIN(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB { switch filterField.valueKind { + case reflect.Bool: + return applyFilterIN(query, tableName, filterField, filterField.boolValues) case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: - return applyFilterIN(query, tableName, filterField, *filterField.intValue) + return applyFilterIN(query, tableName, filterField, filterField.intValues) case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return applyFilterIN(query, tableName, filterField, *filterField.uintValue) + return applyFilterIN(query, tableName, filterField, filterField.uintValues) case reflect.Float32, reflect.Float64: - return applyFilterIN(query, tableName, filterField, *filterField.floatValue) + return applyFilterIN(query, tableName, filterField, filterField.floatValues) case reflect.String: - return applyFilterIN(query, tableName, filterField, *filterField.strValue) + return applyFilterIN(query, tableName, filterField, filterField.strValues) + } + return nil +} + +func handleOperatorNOT_IN(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB { + switch filterField.valueKind { + case reflect.Bool: + return applyFilterNOT_IN(query, tableName, filterField, filterField.boolValues) + case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: + return applyFilterNOT_IN(query, tableName, filterField, filterField.intValues) + case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return applyFilterNOT_IN(query, tableName, filterField, filterField.uintValues) + case reflect.Float32, reflect.Float64: + return applyFilterNOT_IN(query, tableName, filterField, filterField.floatValues) + case reflect.String: + return applyFilterNOT_IN(query, tableName, filterField, filterField.strValues) } return nil } diff --git a/app/repository/smartfilter/operators.go b/app/repository/smartfilter/operators.go index 24e0c61..10be9b7 100644 --- a/app/repository/smartfilter/operators.go +++ b/app/repository/smartfilter/operators.go @@ -3,20 +3,21 @@ package smartfilter type Operator string const ( - OperatorEQ Operator = "EQ" - OperatorNE Operator = "NE" - OperatorGT Operator = "GT" - OperatorGE Operator = "GE" - OperatorLT Operator = "LT" - OperatorLE Operator = "LE" - OperatorLIKE Operator = "LIKE" - OperatorILIKE Operator = "ILIKE" - OperatorIN Operator = "IN" + OperatorEQ Operator = "EQ" + OperatorNE Operator = "NE" + OperatorGT Operator = "GT" + OperatorGE Operator = "GE" + OperatorLT Operator = "LT" + OperatorLE Operator = "LE" + OperatorLIKE Operator = "LIKE" + OperatorILIKE Operator = "ILIKE" + OperatorIN Operator = "IN" + OperatorNOT_IN Operator = "NOT_IN" ) var OPERATORS = []Operator{ OperatorEQ, OperatorNE, OperatorGT, OperatorGE, OperatorLT, OperatorLE, OperatorLIKE, OperatorILIKE, - OperatorIN, + OperatorIN, OperatorNOT_IN, } diff --git a/app/repository/smartfilter/smartfilter.go b/app/repository/smartfilter/smartfilter.go index 53e68cd..5349696 100644 --- a/app/repository/smartfilter/smartfilter.go +++ b/app/repository/smartfilter/smartfilter.go @@ -17,15 +17,16 @@ const TAG_VALUE_SEPARATOR = "," type handlerFunc func(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB var operatorHandlers = map[Operator]handlerFunc{ - OperatorEQ: handleOperatorEQ, - OperatorNE: handleOperatorNE, - OperatorGT: handleOperatorGT, - OperatorGE: handleOperatorGE, - OperatorLT: handleOperatorLT, - OperatorLE: handleOperatorLE, - OperatorLIKE: handleOperatorLIKE, - OperatorILIKE: handleOperatorILIKE, - OperatorIN: handleOperatorIN, + OperatorEQ: handleOperatorEQ, + OperatorNE: handleOperatorNE, + OperatorGT: handleOperatorGT, + OperatorGE: handleOperatorGE, + OperatorLT: handleOperatorLT, + OperatorLE: handleOperatorLE, + OperatorLIKE: handleOperatorLIKE, + OperatorILIKE: handleOperatorILIKE, + OperatorIN: handleOperatorIN, + OperatorNOT_IN: handleOperatorNOT_IN, } type CertFilter struct { @@ -35,6 +36,7 @@ type CertFilter struct { IssuerContains *string `filterfield:"issuer,ILIKE"` Id *string `filterfield:"id,EQ"` Ids *[]string `filterfield:"id,IN"` + IdsNot *[]string `filterfield:"id,NOT_IN"` CreatedAt_Lt *time.Time `filterfield:"created_at,LT"` } @@ -73,6 +75,8 @@ func getFilterFields(filter interface{}) []ReflectedStructField { value: fieldValue, }) } + fmt.Println("-------------- RES --------------") + fmt.Printf("%+v\n", res) return res }