func (b *backend) Close() error {
	if err := b.db.Close(); err != nil {
		return fmt.Errorf("pg backend close: %w", err)
	}
	return nil
}
Close closes the underlying database connection.
package eqpg
import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/url"
	"strings"
	"time"
	"github.com/google/uuid"
	"github.com/lib/pq"
	"github.com/shiblon/entroq"
	"github.com/shiblon/entroq/subq"
)
func escp(p string) string {
	return "'" + strings.NewReplacer("\\", "\\\\", "'", "\\'").Replace(p) + "'"
}
type SSLMode string
const (
	SSLDisable    SSLMode = "disable"      
	SSLAllow      SSLMode = "allow"        
	SSLPrefer     SSLMode = "prefer"       
	SSLRequire    SSLMode = "require"      
	SSLVerifyCA   SSLMode = "verify-ca"    
	SSLVerifyFull SSLMode = "verify-full"  
)
type pgOptions struct {
	db       string
	user     string
	password string
	attempts int
	nw       entroq.NotifyWaiter
	sslMode SSLMode
	sslClientKeyFile  string
	sslClientCertFile string
	sslServerCAFile   string
}
type PGOpt func(opts *pgOptions)
func WithUsername(name string) PGOpt {
	return func(opts *pgOptions) {
		opts.user = name
	}
}
func WithPassword(pwd string) PGOpt {
	return func(opts *pgOptions) {
		opts.password = pwd
	}
}
func WithDB(db string) PGOpt {
	return func(opts *pgOptions) {
		opts.db = db
	}
}
func WithSSL(mode SSLMode, sslOpts ...PGOpt) PGOpt {
	return func(opts *pgOptions) {
		opts.sslMode = mode
		for _, o := range sslOpts {
			o(opts)
		}
	}
}
func WithSSLClientFiles(certFile, keyFile string) PGOpt {
	return func(opts *pgOptions) {
		opts.sslClientCertFile = certFile
		opts.sslClientKeyFile = keyFile
	}
}
func WithSSLServerCAFile(caFile string) PGOpt {
	return func(opts *pgOptions) {
		opts.sslServerCAFile = caFile
	}
}
func WithConnectAttempts(num int) PGOpt {
	if num < 1 {
		num = 1
	}
	return func(opts *pgOptions) {
		opts.attempts = num
	}
}
func WithNotifyWaiter(nw entroq.NotifyWaiter) PGOpt {
	return func(opts *pgOptions) {
		opts.nw = nw
	}
}
func Opener(hostPort string, opts ...PGOpt) entroq.BackendOpener {
	options := &pgOptions{
		db:       "postgres",
		user:     "postgres",
		password: "password",
		attempts: 1,
		nw:       subq.New(),
		sslMode: SSLDisable,
	}
	for _, o := range opts {
		o(options)
	}
	return func(ctx context.Context) (entroq.Backend, error) {
		u, err := url.Parse("postgres://" + hostPort)
		if err != nil {
			return nil, fmt.Errorf("failed to parse hostport %q: %w", hostPort, err)
		}
		host := u.Hostname()
		port := u.Port()
		if port != "" && host == "" {
			host = "::"
		}
		if host != "" && port == "" {
			port = "5432"
		}
		params := []string{
			"sslmode=" + string(options.sslMode),
		}
		if options.user != "" {
			params = append(params, fmt.Sprintf("user=%s", escp(options.user)))
		}
		if options.password != "" {
			params = append(params, fmt.Sprintf("password=%s", escp(options.password)))
		}
		if host != "" {
			params = append(params, fmt.Sprintf("host=%s", escp(host)))
		}
		if port != "" {
			params = append(params, fmt.Sprintf("port=%s", port))
		}
		if options.sslClientKeyFile != "" {
			params = append(params, "sslkey="+url.QueryEscape(options.sslClientKeyFile))
		}
		if options.sslClientCertFile != "" {
			params = append(params, "sslcert="+url.QueryEscape(options.sslClientCertFile))
		}
		if options.sslServerCAFile != "" {
			params = append(params, "sslrootcert="+url.QueryEscape(options.sslServerCAFile))
		}
		connStr := strings.Join(params, " ")
		db, err := sql.Open("postgres", connStr)
		if err != nil {
			return nil, fmt.Errorf("failed to open postgres DB: %w", err)
		}
		for i := 0; i < options.attempts; i++ {
			if err = db.PingContext(ctx); err == nil {
				return New(ctx, db, options.nw)
			}
			if i < options.attempts-1 {
				select {
				case <-ctx.Done():
					return nil, fmt.Errorf("pg opener: %w", ctx.Err())
				case <-time.After(5 * time.Second):
				}
			}
		}
		return nil, fmt.Errorf("time out postgres init: %w", err)
	}
}
type backend struct {
	db *sql.DB
	nw entroq.NotifyWaiter
}
func New(ctx context.Context, db *sql.DB, nw entroq.NotifyWaiter) (*backend, error) {
	b := &backend{
		db: db,
		nw: nw,
	}
	err := b.initDB(ctx)
	if err == io.EOF {
		return nil, io.EOF
	}
	if err != nil {
		return nil, fmt.Errorf("failed to initialize database: %w", err)
	}
	return b, nil
}