github.com/angryronald/go-kit@v0.0.0-20240505173814-ff2bd9c79dbf/generic/repository/sql/generic.repository.immutable.go (about) 1 package sql 2 3 import ( 4 "context" 5 "fmt" 6 7 "gorm.io/gorm" 8 9 "github.com/google/uuid" 10 11 "github.com/angryronald/go-kit/appcontext" 12 "github.com/angryronald/go-kit/cast" 13 "github.com/angryronald/go-kit/generic/repository" 14 ) 15 16 type ImmutableGenericRepository struct { 17 db *gorm.DB 18 } 19 20 func (r *ImmutableGenericRepository) FindAll(ctx context.Context, params map[string]interface{}, conditionalOperations []repository.ConditionalOperation, relationalOperations []repository.RelationalOperation, page int, limit int, result interface{}) (interface{}, error) { 21 if !repository.IsValidOperations(conditionalOperations, relationalOperations, params) { 22 return nil, repository.ErrBadParameters 23 } 24 25 where := "true" 26 i := 0 27 args := []interface{}{} 28 if len(params) > 0 { 29 where = fmt.Sprintf(`%s %s`, where, repository.AND) 30 } 31 for k, v := range params { 32 switch conditionalOperations[i] { 33 case repository.IN: 34 encapsulation := "" 35 if !repository.AreAllNumbers(v.([]interface{})) { 36 encapsulation = "'" 37 } 38 where = fmt.Sprintf(`%s %s %s (%s)`, where, k, conditionalOperations[i], repository.StringJoin(v.([]interface{}), encapsulation)) 39 40 break 41 42 case repository.ILIKE, repository.LIKE: 43 where = fmt.Sprintf(`%s %s %s ?`, where, k, conditionalOperations[i]) 44 args = append(args, fmt.Sprintf("%%%s%%", v)) 45 break 46 47 default: 48 where = fmt.Sprintf(`%s %s %s ?`, where, k, conditionalOperations[i]) 49 args = append(args, v) 50 } 51 52 if i < len(relationalOperations) { 53 where = fmt.Sprintf(`%s %s`, where, relationalOperations[i]) 54 } 55 i++ 56 } 57 58 order := fmt.Sprintf(`"created_at" %s`, repository.DESC) 59 60 if page == 0 && limit == 0 { 61 if err := r.db.Where( 62 where, 63 args..., 64 ).Order(order).Find(&result).Error; err != nil { 65 return nil, err 66 } 67 68 return result, nil 69 } 70 71 if err := r.db.Where( 72 where, 73 args..., 74 ).Order(order). 75 Offset((page - 1) * limit). 76 Limit(limit). 77 Find(&result).Error; err != nil { 78 return nil, err 79 } 80 81 return result, nil 82 } 83 84 func (r *ImmutableGenericRepository) FindOne(ctx context.Context, key string, value interface{}, result interface{}) (interface{}, error) { 85 where := fmt.Sprintf(`%s %s ?`, key, repository.EQUAL_WITH) 86 args := []interface{}{ 87 value, 88 } 89 if err := r.db.Where( 90 where, 91 args, 92 ).First(&result).Error; err != nil { 93 return nil, err 94 } 95 96 return result, nil 97 } 98 99 func (r *ImmutableGenericRepository) FindByID(ctx context.Context, id uuid.UUID, result interface{}) (interface{}, error) { 100 where := fmt.Sprintf(`"id" %s ?`, repository.EQUAL_WITH) 101 args := []interface{}{ 102 id, 103 } 104 if err := r.db.Where( 105 where, 106 args, 107 ).First(&result).Error; err != nil { 108 return nil, err 109 } 110 111 return result, nil 112 } 113 114 func (r *ImmutableGenericRepository) Insert(ctx context.Context, data interface{}) (interface{}, error) { 115 newID, err := uuid.NewRandom() 116 if err != nil { 117 return nil, err 118 } 119 if err = repository.UpdatePropertyValue(data, "ID", newID); err != nil { 120 return nil, err 121 } 122 if err = repository.UpdatePropertyValue(data, "CreatedBy", appcontext.UserID(ctx)); err != nil { 123 return nil, err 124 } 125 126 if err := r.db.Create(data).Error; err != nil { 127 if err == gorm.ErrDuplicatedKey { 128 return nil, repository.ErrConflict 129 } 130 return nil, err 131 } 132 return data, nil 133 } 134 135 func (r *ImmutableGenericRepository) BulkInsert(ctx context.Context, data interface{}) (interface{}, error) { 136 tx := r.db.Begin() 137 defer func() { 138 if r := recover(); r != nil { 139 tx.Rollback() 140 } 141 }() 142 143 copyOfData, err := repository.CopySliceOfPointers(data) 144 if err != nil { 145 return nil, err 146 } 147 148 dataInArray := cast.StructPointerArrayToInterfacePointerArray(copyOfData) 149 for i := 0; i < len(dataInArray); i++ { 150 newID, err := uuid.NewRandom() 151 if err != nil { 152 return nil, err 153 } 154 155 if err = repository.UpdatePropertyValue(dataInArray[i], "ID", newID); err != nil { 156 return nil, err 157 } 158 if err = repository.UpdatePropertyValue(dataInArray[i], "CreatedBy", appcontext.UserID(ctx)); err != nil { 159 return nil, err 160 } 161 } 162 163 dataInArrayWithIdentity, err := repository.CopySliceOfPointersWithIdentitySeparated(copyOfData, dataInArray) 164 if err != nil { 165 return nil, err 166 } 167 168 if err := r.db.Create(dataInArrayWithIdentity).Error; err != nil { 169 tx.Rollback() 170 if err == gorm.ErrDuplicatedKey { 171 return nil, repository.ErrConflict 172 } 173 return nil, err 174 } 175 return dataInArrayWithIdentity, tx.Commit().Error 176 } 177 178 func (r *ImmutableGenericRepository) Query(ctx context.Context, query string, params []interface{}, result interface{}) (interface{}, error) { 179 if err := r.db.Raw(query, params...).Find(&result).Error; err != nil { 180 return nil, err 181 } 182 183 return result, nil 184 } 185 186 func NewImmutableRepository(db *gorm.DB) repository.ImmutableGenericRepositoryInterface { 187 return &ImmutableGenericRepository{ 188 db: db, 189 } 190 }