link-go/link/repository.go
2021-03-13 01:43:08 +06:00

95 lines
1.7 KiB
Go

package link
import (
"context"
"errors"
"github.com/jackc/pgtype"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
"net/url"
)
type Repository interface {
Save(link *Link) error
FindById(id string) (*Link, error)
DeleteById(id string) error
}
type PgRepository struct {
pool *pgxpool.Pool
}
func (r *PgRepository) Save(link *Link) error {
ctx := context.Background()
tx, err := r.pool.Begin(ctx)
if err != nil {
return err
}
sql := `
INSERT INTO links (id, name, redirect_url, creation_time)
VALUES ($1, $2, $3, $4::timestamp)
`
_, err = tx.Exec(ctx, sql, link.Id, link.Name, link.RedirectURL.String(), link.CreationTime.Format("2006-01-02 15:04:05"))
if err != nil {
_ = tx.Rollback(ctx)
return err
}
if err = tx.Commit(ctx); err != nil {
return err
}
return nil
}
func (r *PgRepository) FindById(id string) (*Link, error) {
ctx := context.Background()
tx, err := r.pool.Begin(ctx)
if err != nil {
return nil, err
}
sql := `
SELECT id, name, redirect_url, creation_time
FROM links
WHERE id = $1
`
entity, err := mapRowToEntity(tx.QueryRow(ctx, sql, id))
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
} else {
_ = tx.Rollback(ctx)
return nil, err
}
}
if err = tx.Commit(ctx); err != nil {
return nil, err
}
return entity, nil
}
func mapRowToEntity(r pgx.Row) (*Link, error) {
var entity Link
var urlStr string
var t pgtype.Timestamp
if err := r.Scan(&entity.Id, &entity.Name, &urlStr, &t); err != nil {
return nil, err
}
u, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
entity.RedirectURL = *u
entity.CreationTime = t.Time
return &entity, nil
}