ikurotime / gitgud

public
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}