From 0a0ed77794987a60061dff4cb585c69b1b0a5917 Mon Sep 17 00:00:00 2001 From: Eden Kirin Date: Tue, 18 Jun 2024 23:43:21 +0200 Subject: [PATCH] Basics --- Makefile | 2 +- app/main.go | 31 +++++++++++ app/models/cert.go | 2 +- app/repository/smartfilter.go | 97 +++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 app/repository/smartfilter.go diff --git a/Makefile b/Makefile index f3c1f7d..4a9da8c 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ VERSION_TAG=$$(date +%y%m%d.%H%M) run: - @air + go run app/main.go .PHONY: test diff --git a/app/main.go b/app/main.go index 0875cbd..095201e 100644 --- a/app/main.go +++ b/app/main.go @@ -5,9 +5,38 @@ import ( "repo-pattern/app/lib/cfg" "repo-pattern/app/lib/db" "repo-pattern/app/lib/logging" + "repo-pattern/app/models" "repo-pattern/app/repository" + + "gorm.io/gorm" ) +var ( + TRUE = true + FALSE = false +) + +func doMagic(db *gorm.DB) { + var err error + query := db + + f := repository.SmartCertFilter[models.Cert]{ + Alive: &TRUE, + } + + query, err = f.ToQuery(query) + if err != nil { + panic(err) + } + + var certs []models.Cert + + query.Find(&certs) + for n, cert := range certs { + fmt.Printf(">> [%d] %+v\n", n, cert.Id) + } +} + func main() { cfg.Init() logging.Init() @@ -16,5 +45,7 @@ func main() { db := db.InitDB() repository.Dao = repository.CreateDAO(db) + doMagic(db) + fmt.Println("Running...") } diff --git a/app/models/cert.go b/app/models/cert.go index 5ea378d..6d5a013 100644 --- a/app/models/cert.go +++ b/app/models/cert.go @@ -23,6 +23,6 @@ type Cert struct { UpdatedAt time.Time `faker:"-"` } -func (m *Cert) TableName() string { +func (m Cert) TableName() string { return "certificates" } diff --git a/app/repository/smartfilter.go b/app/repository/smartfilter.go new file mode 100644 index 0000000..266e2e0 --- /dev/null +++ b/app/repository/smartfilter.go @@ -0,0 +1,97 @@ +package repository + +import ( + "fmt" + "reflect" + "slices" + "strings" + + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/schema" +) + +const TAG_NAME = "filterfield" +const TAG_VALUE_SEPARATOR = "," + +type Operator string + +const ( + OperatorEQ Operator = "EQ" + OperatorIN Operator = "IN" +) + +var OPERATORS = []Operator{OperatorEQ, OperatorIN} + +type FilterField struct { + Name string + Operator Operator +} + +type SmartCertFilter[T schema.Tabler] struct { + Model T + Alive *bool `filterfield:"alive,EQ"` + Id *uuid.UUID `filterfield:"id,EQ"` + Ids *[]uuid.UUID `filterfield:"id,IN"` + CompanyId *uuid.UUID `filterfield:"company_id,EQ"` +} + +func (f SmartCertFilter[T]) ToQuery(query *gorm.DB) (*gorm.DB, error) { + tableName := f.Model.TableName() + + fmt.Printf("Table name: %s\n", tableName) + fmt.Printf("%+v\n", f) + + st := reflect.TypeOf(f) + modelName := st.Name() + + for i := 0; i < st.NumField(); i++ { + field := st.Field(i) + tagValue := field.Tag.Get(TAG_NAME) + if len(tagValue) == 0 { + continue + } + + filterField, err := getFilterField(tagValue) + if err != nil { + return nil, fmt.Errorf("%s.%s: %s", modelName, field.Name, err) + } + + fmt.Printf( + "tagValue: %s, Name: %s, Operator: %s\n", + tagValue, + filterField.Name, + filterField.Operator, + ) + + switch filterField.Operator { + case OperatorEQ: + query = applyFilterEQ(query, tableName, filterField) + } + } + + // query = query.Where("certificates.alive=?", true) + + return query, nil +} + +func applyFilterEQ(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB { + return query +} + +func getFilterField(tagValue string) (*FilterField, error) { + values := strings.Split(tagValue, TAG_VALUE_SEPARATOR) + if len(values) != 2 { + return nil, fmt.Errorf("incorrect number of tag values: %s", tagValue) + } + + operator := Operator(values[1]) + if !slices.Contains(OPERATORS, operator) { + return nil, fmt.Errorf("unknown operator: %s", operator) + } + + f := FilterField{ + Operator: operator, + } + return &f, nil +}