main / internal/infra/persistence/sqlite/user_repo.go
1.5 KB · Go Raw
1package sqlite
2
3import (
4 "context"
5 "database/sql"
6 "errors"
7
8 "github.com/mattn/go-sqlite3"
9
10 "gitgud/internal/domain"
11)
12
13type UserRepo struct {
14 db *sql.DB
15}
16
17func NewUserRepo(db *sql.DB) *UserRepo {
18 return &UserRepo{db: db}
19}
20
21func (r *UserRepo) Create(ctx context.Context, u *domain.User) error {
22 res, err := r.db.ExecContext(ctx, `INSERT INTO users(username,email,password_hash) VALUES(?,?,?)`,
23 u.Username, u.Email, u.PasswordHash)
24 if err != nil {
25 if isUniqueViolation(err) {
26 return domain.ErrConflict
27 }
28 return err
29 }
30 u.ID, _ = res.LastInsertId()
31 return nil
32}
33
34func (r *UserRepo) ByUsername(ctx context.Context, name string) (*domain.User, error) {
35 return r.queryUser(ctx,
36 `SELECT id, username, email, password_hash, created_at FROM users WHERE username = ?`,
37 name)
38}
39
40func (r *UserRepo) ByID(ctx context.Context, id string) (*domain.User, error) {
41 return r.queryUser(ctx,
42 `SELECT id, username, email, password_hash, created_at FROM users WHERE id = ?`,
43 id)
44}
45
46func (r *UserRepo) queryUser(ctx context.Context, query string, arg any) (*domain.User, error) {
47 var u domain.User
48 err := r.db.QueryRowContext(ctx, query, arg).Scan(
49 &u.ID, &u.Username, &u.Email, &u.PasswordHash, &u.CreatedAt)
50 if err != nil {
51 if errors.Is(err, sql.ErrNoRows) {
52 return nil, domain.ErrNotFound
53 }
54 return nil, err
55 }
56 return &u, nil
57}
58
59func isUniqueViolation(err error) bool {
60 var sqliteErr sqlite3.Error
61 return errors.As(err, &sqliteErr) &&
62 sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique
63}