101 lines
2.2 KiB
Go
101 lines
2.2 KiB
Go
// Package postgres provides GL's PostgreSQL adapters.
|
|
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
|
|
"gl/infrastructure/config"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgconn"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
type Row interface {
|
|
Scan(dest ...any) error
|
|
}
|
|
|
|
type Rows interface {
|
|
Next() bool
|
|
Scan(dest ...any) error
|
|
Err() error
|
|
Close()
|
|
}
|
|
|
|
type Tx interface {
|
|
Exec(context.Context, string, ...any) (pgconn.CommandTag, error)
|
|
QueryRow(context.Context, string, ...any) Row
|
|
Commit(context.Context) error
|
|
Rollback(context.Context) error
|
|
}
|
|
|
|
type Database interface {
|
|
Begin(context.Context) (Tx, error)
|
|
Exec(context.Context, string, ...any) (pgconn.CommandTag, error)
|
|
QueryRow(context.Context, string, ...any) Row
|
|
Query(context.Context, string, ...any) (Rows, error)
|
|
Ping(context.Context) error
|
|
Close()
|
|
}
|
|
|
|
type Pool struct {
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func Open(ctx context.Context, cfg config.DatabaseConfig) (*Pool, error) {
|
|
connectionURL := &url.URL{
|
|
Scheme: "postgres",
|
|
User: url.UserPassword(cfg.User, cfg.Password),
|
|
Host: cfg.Host + ":" + strconv.Itoa(cfg.Port),
|
|
Path: cfg.Name,
|
|
}
|
|
query := connectionURL.Query()
|
|
query.Set("sslmode", cfg.SSLMode)
|
|
connectionURL.RawQuery = query.Encode()
|
|
|
|
pool, err := pgxpool.New(ctx, connectionURL.String())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create postgres pool: %w", err)
|
|
}
|
|
return &Pool{pool: pool}, nil
|
|
}
|
|
|
|
func (p *Pool) Begin(ctx context.Context) (Tx, error) {
|
|
tx, err := p.pool.BeginTx(ctx, pgx.TxOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return txAdapter{Tx: tx}, nil
|
|
}
|
|
|
|
func (p *Pool) Ping(ctx context.Context) error {
|
|
return p.pool.Ping(ctx)
|
|
}
|
|
|
|
func (p *Pool) QueryRow(ctx context.Context, sql string, args ...any) Row {
|
|
return p.pool.QueryRow(ctx, sql, args...)
|
|
}
|
|
|
|
func (p *Pool) Query(ctx context.Context, sql string, args ...any) (Rows, error) {
|
|
return p.pool.Query(ctx, sql, args...)
|
|
}
|
|
|
|
func (p *Pool) Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error) {
|
|
return p.pool.Exec(ctx, sql, args...)
|
|
}
|
|
|
|
func (p *Pool) Close() {
|
|
p.pool.Close()
|
|
}
|
|
|
|
type txAdapter struct {
|
|
pgx.Tx
|
|
}
|
|
|
|
func (t txAdapter) QueryRow(ctx context.Context, sql string, args ...any) Row {
|
|
return t.Tx.QueryRow(ctx, sql, args...)
|
|
}
|