gitlab.com/ignitionrobotics/web/ign-go@v1.0.0-rc4/repository/sql_repository.go (about) 1 package repository 2 3 import ( 4 "github.com/jinzhu/gorm" 5 "gitlab.com/ignitionrobotics/web/ign-go/reflect" 6 ) 7 8 // NewRepositorySQL initializes a new Repository implementation for SQL databases. 9 func NewRepositorySQL(db *gorm.DB, entity Model) Repository { 10 return &repositorySQL{ 11 DB: db, 12 entity: entity, 13 } 14 } 15 16 // repositorySQL implements Repository using gorm to support SQL databases. 17 type repositorySQL struct { 18 DB *gorm.DB 19 entity Model 20 } 21 22 // Create inserts a single entry. 23 // entity: The entry to insert. 24 func (r *repositorySQL) Create(entity Model) (Model, error) { 25 result, err := r.CreateBulk([]Model{entity}) 26 if err != nil { 27 return nil, err 28 } 29 return result[0], nil 30 } 31 32 // CreateBulk is a bulk operation to create multiple entries with a single operation. 33 // entities: should be a slice of the same data structure implementing Model. 34 func (r *repositorySQL) CreateBulk(entities []Model) ([]Model, error) { 35 for _, entity := range entities { 36 err := r.DB.Model(r.Model()).Create(entity).Error 37 if err != nil { 38 return nil, err 39 } 40 } 41 return entities, nil 42 } 43 44 // Find filters entries and stores filtered entries in output. 45 // output: will contain the result of the query. It must be a pointer to a slice. 46 // offset: defines the number of results to skip before loading values to output. 47 // limit: defines the maximum number of entries to return. A nil value returns infinite results. 48 // filters: filter entries by field value. 49 func (r *repositorySQL) Find(output interface{}, offset, limit *int, filters ...Filter) error { 50 q := r.startQuery() 51 if limit != nil { 52 q = q.Limit(*limit) 53 if offset != nil { 54 q = q.Offset(*offset) 55 } 56 } 57 58 q = r.setQueryFilters(q, filters) 59 q = q.Find(output) 60 err := q.Error 61 if err != nil { 62 return err 63 } 64 return nil 65 } 66 67 // FindOne filters entries and stores the first filtered entry in output, it must be a pointer to 68 // a data structure implementing Model. 69 func (r *repositorySQL) FindOne(output Model, filters ...Filter) error { 70 if len(filters) == 0 { 71 return ErrNoFilter 72 } 73 q := r.startQuery() 74 q = r.setQueryFilters(q, filters) 75 q = q.First(output) 76 return q.Error 77 } 78 79 // Update updates all model entries that match the provided filters with the given data. 80 // data: must be a map[string]interface{} 81 // filters: filter entries that should be updated. 82 func (r *repositorySQL) Update(data interface{}, filters ...Filter) error { 83 q := r.startQuery() 84 q = r.setQueryFilters(q, filters) 85 q = q.Update(data) 86 return q.Error 87 } 88 89 // Delete removes all the model entries that match filters. 90 // filters: filter entries that should be deleted. 91 func (r *repositorySQL) Delete(filters ...Filter) error { 92 q := r.startQuery() 93 q = r.setQueryFilters(q, filters) 94 q = q.Delete(r.Model()) 95 err := q.Error 96 if err != nil { 97 return err 98 } 99 return nil 100 } 101 102 // FirstOrCreate inserts a new entry if the given filters don't find any existing record. 103 // entity: must be a pointer to a Model implementation. Results will be saved in this argument if the record exists. 104 func (r *repositorySQL) FirstOrCreate(entity Model, filters ...Filter) error { 105 q := r.startQuery() 106 q = r.setQueryFilters(q, filters) 107 return q.FirstOrCreate(entity).Error 108 } 109 110 // startQuery inits a gorm query for this repository's model. Multiple filters are ANDd together. 111 func (r *repositorySQL) startQuery() *gorm.DB { 112 return r.DB.Model(r.Model()) 113 } 114 115 // setQueryFilters applies the given filters to a gorm query. 116 func (r *repositorySQL) setQueryFilters(q *gorm.DB, filters []Filter) *gorm.DB { 117 for _, f := range filters { 118 q = q.Where(f.Template, f.Values...) 119 } 120 return q 121 } 122 123 // Model returns this repository's model. 124 func (r *repositorySQL) Model() Model { 125 return reflect.NewInstance(r.entity).(Model) 126 }