Files
pgm/pgm.go

109 lines
2.1 KiB
Go
Raw Permalink Normal View History

// pgm
//
2025-10-18 14:43:42 +05:30
// A simple PG string query builder
//
// Author: Ankit Patial
2025-07-26 18:34:56 +05:30
package pgm
import (
2025-10-18 14:43:42 +05:30
"context"
"errors"
2025-10-18 14:43:42 +05:30
"log/slog"
"sync/atomic"
2025-07-26 18:34:56 +05:30
"time"
2025-10-18 14:43:42 +05:30
"github.com/jackc/pgx/v5"
2025-07-26 18:34:56 +05:30
"github.com/jackc/pgx/v5/pgtype"
2025-10-18 14:43:42 +05:30
"github.com/jackc/pgx/v5/pgxpool"
2025-07-26 18:34:56 +05:30
)
2025-10-18 14:43:42 +05:30
var (
poolPGX atomic.Pointer[pgxpool.Pool]
ErrConnStringMissing = errors.New("connection string is empty")
)
2025-07-29 21:45:32 +05:30
// Errors
var (
ErrInitTX = errors.New("failed to init db.tx")
ErrCommitTX = errors.New("failed to commit db.tx")
ErrNoRows = errors.New("no data found")
)
2025-08-11 22:37:25 +05:30
2025-10-18 14:43:42 +05:30
type Config struct {
ConnString string
MaxConns int32
MinConns int32
MaxConnLifetime time.Duration
MaxConnIdleTime time.Duration
2025-07-26 18:34:56 +05:30
}
2025-10-18 14:43:42 +05:30
// InitPool will create new pgxpool.Pool and will keep it for its working
func InitPool(conf Config) {
if conf.ConnString == "" {
panic(ErrConnStringMissing)
}
cfg, err := pgxpool.ParseConfig(conf.ConnString)
if err != nil {
panic(err)
}
if conf.MaxConns > 0 {
cfg.MaxConns = conf.MaxConns // 100
}
if conf.MinConns > 0 {
cfg.MinConns = conf.MaxConns // 5
}
if conf.MaxConnLifetime > 0 {
cfg.MaxConnLifetime = conf.MaxConnLifetime // time.Minute * 10
}
if conf.MaxConnIdleTime > 0 {
cfg.MaxConnIdleTime = conf.MaxConnIdleTime // time.Minute * 5
}
p, err := pgxpool.NewWithConfig(context.Background(), cfg)
if err != nil {
panic(err)
}
if err = p.Ping(context.Background()); err != nil {
panic(err)
}
poolPGX.Store(p)
2025-07-26 18:34:56 +05:30
}
2025-10-18 14:43:42 +05:30
// GetPool instance
func GetPool() *pgxpool.Pool {
return poolPGX.Load()
2025-07-26 18:34:56 +05:30
}
2025-10-18 14:43:42 +05:30
// BeginTx begins a pgx poll transaction
func BeginTx(ctx context.Context) (pgx.Tx, error) {
tx, err := poolPGX.Load().Begin(ctx)
if err != nil {
slog.Error(err.Error())
return nil, errors.New("failed to open db tx")
}
return tx, err
2025-07-26 18:34:56 +05:30
}
2025-10-18 14:43:42 +05:30
// IsNotFound error check
func IsNotFound(err error) bool {
return errors.Is(err, pgx.ErrNoRows)
2025-07-26 18:34:56 +05:30
}
2025-10-18 14:43:42 +05:30
// PgTime as in UTC
func PgTime(t time.Time) pgtype.Timestamptz {
return pgtype.Timestamptz{Time: t, Valid: true}
2025-07-26 18:34:56 +05:30
}
2025-10-18 14:43:42 +05:30
func PgTimeNow() pgtype.Timestamptz {
return pgtype.Timestamptz{Time: time.Now(), Valid: true}
2025-07-26 18:34:56 +05:30
}