-
Notifications
You must be signed in to change notification settings - Fork 0
/
repository.go
133 lines (115 loc) · 3.98 KB
/
repository.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package postgres
import (
"context"
"database/sql"
"go.uber.org/zap"
images "github.com/go-park-mail-ru/2023_1_PracticalDev/internal/images/client"
pkgErrors "github.com/go-park-mail-ru/2023_1_PracticalDev/internal/pkg/errors"
"github.com/go-park-mail-ru/2023_1_PracticalDev/internal/profile"
"github.com/pkg/errors"
)
type postgresRepository struct {
db *sql.DB
log *zap.Logger
imgServ images.ImageClient
}
func NewPostgresRepository(db *sql.DB, imgServ images.ImageClient, log *zap.Logger) profile.Repository {
return &postgresRepository{db, log, imgServ}
}
func (rep *postgresRepository) GetProfileByUser(userId int) (profile.Profile, error) {
const getCmd = `SELECT username, name, profile_image, website_url
FROM users
WHERE id = $1;`
row := rep.db.QueryRow(getCmd, userId)
var prof profile.Profile
var profileImage, websiteUrl sql.NullString
err := row.Scan(&prof.Username, &prof.Name, &profileImage, &websiteUrl)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return profile.Profile{}, errors.Wrap(pkgErrors.ErrProfileNotFound, err.Error())
} else {
return profile.Profile{}, errors.Wrap(pkgErrors.ErrDb, err.Error())
}
}
prof.ProfileImage = profileImage.String
prof.WebsiteUrl = websiteUrl.String
return prof, nil
}
const fullUpdateCmd = `UPDATE users
SET username = $1::VARCHAR,
name = $2::VARCHAR,
profile_image = $3::VARCHAR,
website_url = $4::VARCHAR
WHERE id = $5
RETURNING username, name, profile_image, website_url;`
func (rep *postgresRepository) FullUpdate(params *profile.FullUpdateParams) (profile.Profile, error) {
url, err := rep.imgServ.UploadImage(context.TODO(), ¶ms.ProfileImage)
if err != nil {
return profile.Profile{}, errors.Wrap(pkgErrors.ErrImageService, err.Error())
}
row := rep.db.QueryRow(fullUpdateCmd,
params.Username,
params.Name,
url,
params.WebsiteUrl,
params.Id,
)
var prof profile.Profile
var profileImage, websiteUrl sql.NullString
err = row.Scan(&prof.Username, &prof.Name, &profileImage, &websiteUrl)
if err != nil {
return profile.Profile{}, errors.Wrap(pkgErrors.ErrDb, err.Error())
}
prof.ProfileImage = profileImage.String
prof.WebsiteUrl = websiteUrl.String
return prof, nil
}
const partialUpdateCmd = `UPDATE users
SET username = CASE WHEN $1::BOOLEAN THEN $2::VARCHAR ELSE username END,
name = CASE WHEN $3::BOOLEAN THEN $4::VARCHAR ELSE name END,
profile_image = CASE WHEN $5::BOOLEAN THEN $6::VARCHAR ELSE profile_image END,
website_url = CASE WHEN $7::BOOLEAN THEN $8::VARCHAR ELSE website_url END
WHERE id = $9
RETURNING username, name, profile_image, website_url;`
func (rep *postgresRepository) PartialUpdate(params *profile.PartialUpdateParams) (profile.Profile, error) {
var url string
var err error
if params.UpdateProfileImage {
url, err = rep.imgServ.UploadImage(context.TODO(), ¶ms.ProfileImage)
if err != nil {
return profile.Profile{}, errors.Wrap(pkgErrors.ErrImageService, err.Error())
}
}
row := rep.db.QueryRow(partialUpdateCmd,
params.UpdateUsername,
params.Username,
params.UpdateName,
params.Name,
params.UpdateProfileImage,
url,
params.UpdateWebsiteUrl,
params.WebsiteUrl,
params.Id,
)
var prof profile.Profile
var profileImage, websiteUrl sql.NullString
err = row.Scan(&prof.Username, &prof.Name, &profileImage, &websiteUrl)
if err != nil {
return profile.Profile{}, errors.Wrap(pkgErrors.ErrDb, err.Error())
}
prof.ProfileImage = profileImage.String
prof.WebsiteUrl = websiteUrl.String
return prof, nil
}
const isUsernameAvailableCmd = `SELECT NOT EXISTS(SELECT id
FROM users
WHERE username = $1 AND id <> $2) AS available;`
func (rep *postgresRepository) IsUsernameAvailable(username string, userId int) (bool, error) {
row := rep.db.QueryRow(isUsernameAvailableCmd, username, userId)
var available bool
err := row.Scan(&available)
if err != nil {
return false, errors.Wrap(pkgErrors.ErrDb, err.Error())
}
return available, nil
}