github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/db/tag.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package db 20 21 import ( 22 "context" 23 "fmt" 24 "github.com/jackc/pgerrcode" 25 "github.com/jackc/pgx/v5/pgconn" 26 "github.com/pkg/errors" 27 "gorm.io/gorm" 28 "strings" 29 30 "github.com/e154/smart-home/common/apperr" 31 ) 32 33 // Tags ... 34 type Tags struct { 35 Db *gorm.DB 36 } 37 38 // Tag ... 39 type Tag struct { 40 Id int64 `gorm:"primary_key"` 41 Name string 42 } 43 44 // TableName ... 45 func (d *Tag) TableName() string { 46 return "tags" 47 } 48 49 // Add ... 50 func (n Tags) Add(ctx context.Context, tag *Tag) (id int64, err error) { 51 if err = n.Db.WithContext(ctx).Create(tag).Error; err != nil { 52 err = errors.Wrap(apperr.ErrTagAdd, err.Error()) 53 return 54 } 55 id = tag.Id 56 return 57 } 58 59 // List ... 60 func (n *Tags) List(ctx context.Context, limit, offset int, orderBy, sort string, query *string, names *[]string) (list []*Tag, total int64, err error) { 61 62 list = make([]*Tag, 0) 63 q := n.Db.WithContext(ctx).Model(Tag{}) 64 if query != nil { 65 q = q.Where("name LIKE ? or source LIKE ?", "%"+*query+"%", "%"+*query+"%") 66 } 67 if names != nil { 68 q = q.Where("name IN (?)", *names) 69 } 70 if err = q.Count(&total).Error; err != nil { 71 err = errors.Wrap(apperr.ErrTagList, err.Error()) 72 return 73 } 74 err = q. 75 Limit(limit). 76 Offset(offset). 77 //Order(fmt.Sprintf("%s %s", sort, orderBy)). 78 Find(&list). 79 Error 80 if err != nil { 81 err = errors.Wrap(apperr.ErrTagList, err.Error()) 82 } 83 return 84 } 85 86 // GetByName ... 87 func (n *Tags) GetByName(ctx context.Context, name string) (tag *Tag, err error) { 88 tag = &Tag{} 89 err = n.Db.WithContext(ctx).Model(tag). 90 Where("name = ?", name). 91 First(&tag).Error 92 93 if err != nil { 94 if errors.Is(err, gorm.ErrRecordNotFound) { 95 err = errors.Wrap(apperr.ErrTagNotFound, fmt.Sprintf("name \"%s\"", name)) 96 return 97 } 98 err = errors.Wrap(apperr.ErrTagGet, err.Error()) 99 } 100 101 return 102 } 103 104 // GetById ... 105 func (n *Tags) GetById(ctx context.Context, id int64) (tag *Tag, err error) { 106 tag = &Tag{} 107 err = n.Db.WithContext(ctx).Model(tag). 108 Where("id = ?", id). 109 First(&tag).Error 110 111 if err != nil { 112 if errors.Is(err, gorm.ErrRecordNotFound) { 113 err = errors.Wrap(apperr.ErrTagNotFound, fmt.Sprintf("id \"%d\"", id)) 114 return 115 } 116 err = errors.Wrap(apperr.ErrTagGet, err.Error()) 117 } 118 119 return 120 } 121 122 // Delete ... 123 func (n *Tags) Delete(ctx context.Context, name string) (err error) { 124 if err = n.Db.WithContext(ctx).Delete(&Tag{Name: name}).Error; err != nil { 125 err = errors.Wrap(apperr.ErrTagDelete, err.Error()) 126 } 127 return 128 } 129 130 // Update ... 131 func (n *Tags) Update(ctx context.Context, tag *Tag) (err error) { 132 err = n.Db.WithContext(ctx).Model(&Tag{Id: tag.Id}).Updates(map[string]interface{}{ 133 "name": tag.Name, 134 }).Error 135 if err != nil { 136 var pgErr *pgconn.PgError 137 if errors.As(err, &pgErr) { 138 switch pgErr.Code { 139 case pgerrcode.UniqueViolation: 140 if strings.Contains(pgErr.Message, "tag_name_unq") { 141 err = errors.Wrap(apperr.ErrTagUpdate, fmt.Sprintf("tag name \"%s\" not unique", tag.Name)) 142 return 143 } 144 default: 145 fmt.Printf("unknown code \"%s\"\n", pgErr.Code) 146 } 147 } 148 err = errors.Wrap(apperr.ErrTagUpdate, err.Error()) 149 return 150 } 151 152 return 153 } 154 155 // Search ... 156 func (n *Tags) Search(ctx context.Context, query string, limit, offset int) (list []*Tag, total int64, err error) { 157 158 q := n.Db.WithContext(ctx).Model(&Tag{}). 159 Where("name LIKE ?", "%"+query+"%") 160 161 if err = q.Count(&total).Error; err != nil { 162 err = errors.Wrap(apperr.ErrTagSearch, err.Error()) 163 return 164 } 165 166 q = q. 167 Limit(limit). 168 Offset(offset). 169 Order("name ASC") 170 171 list = make([]*Tag, 0) 172 if err = q.Find(&list).Error; err != nil { 173 err = errors.Wrap(apperr.ErrTagSearch, err.Error()) 174 } 175 return 176 }