aboutsummaryrefslogtreecommitdiff
path: root/pkg/service/crud/crud.go
blob: 799eacb3c6c225f9f8e65735281e6a7a3f0c3b7d (plain) (blame)
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
package crud

import (
	"context"
	"errors"

	"github.com/uptrace/bun"
	"github.com/uptrace/bun/driver/pgdriver"
)

var ErrRecordAlreadyExists = errors.New("record already exists")

type Service[T any] struct {
	db *bun.DB
}

func NewService[T any](db *bun.DB) *Service[T] {
	return &Service[T]{
		db: db,
	}
}

func (s *Service[T]) Insert(ctx context.Context, model *T) error {
	if _, err := s.db.NewInsert().Model(model).Returning("*").Exec(ctx); err != nil {
		pqErr := pgdriver.Error{}
		if errors.As(err, &pqErr) {
			if pqErr.Field('C') == "23505" {
				return ErrRecordAlreadyExists
			}
		}

		return err
	}

	return nil
}

func (s *Service[T]) UpdatePk(ctx context.Context, model *T, columns []string) error {
	if _, err := s.db.NewUpdate().Model(model).WherePK(columns...).Column(columns...).Exec(ctx); err != nil {
		pqErr := pgdriver.Error{}
		if errors.As(err, &pqErr) {
			if pqErr.Field('C') == "23505" {
				return ErrRecordAlreadyExists
			}
		}

		return err
	}

	return nil
}

//nolint:revive
func (s *Service[T]) Update(ctx context.Context, model *T, columns []string, query string, args ...any) error {
	if _, err := s.db.NewUpdate().Model(model).Where(query, args...).Column(columns...).Exec(ctx); err != nil {
		pqErr := pgdriver.Error{}
		if errors.As(err, &pqErr) {
			if pqErr.Field('C') == "23505" {
				return ErrRecordAlreadyExists
			}
		}

		return err
	}

	return nil
}

func (s *Service[T]) FindOne(ctx context.Context, query string, args ...any) (*T, error) {
	m := new(T)

	return m, s.db.NewSelect().Model(m).Where(query, args...).Scan(ctx, m)
}

//nolint:revive
func (s *Service[T]) Find(ctx context.Context, query string, args ...any) ([]T, int, error) {
	m := make([]T, 0)
	c, err := s.db.NewSelect().Model(m).Where(query, args...).ScanAndCount(ctx, &m)

	return m, c, err
}

func (s *Service[T]) Delete(ctx context.Context, query string, args ...any) error {
	_, err := s.db.NewDelete().Model((*T)(nil)).Where(query, args...).Exec(ctx)

	return err
}