108 lines
2.8 KiB
Go
108 lines
2.8 KiB
Go
package pgdb
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"database/sql"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/stdlib"
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
// Интерфейс передается в неэкспортируемые функции
|
|
// нужен для того, чтобы не зависило от того, что передаём
|
|
// транзацию или обычное соединение
|
|
type Driver interface {
|
|
// QueryContext executes a query that returns rows, typically a SELECT.
|
|
// The args are for any placeholder parameters in the query.
|
|
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
|
|
|
|
// QueryRowContext executes a query that is expected to return at most one row.
|
|
// QueryRowContext always returns a non-nil value. Errors are deferred until
|
|
// [Row]'s Scan method is called.
|
|
// If the query selects no rows, the [*Row.Scan] will return [ErrNoRows].
|
|
// Otherwise, [*Row.Scan] scans the first selected row and discards
|
|
// the rest.
|
|
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
|
|
|
|
// ExecContext executes a query without returning any rows.
|
|
// The args are for any placeholder parameters in the query.
|
|
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
|
|
}
|
|
|
|
type PostgresConfig struct {
|
|
Host string
|
|
Port uint16
|
|
Username string
|
|
Password string
|
|
Database string
|
|
Schema string
|
|
SSLMode string
|
|
SSLRootCert string
|
|
}
|
|
|
|
type client struct {
|
|
config PostgresConfig
|
|
db *sqlx.DB
|
|
}
|
|
|
|
func NewClient(cfg PostgresConfig) (*client, error) {
|
|
rootCertPool := x509.NewCertPool()
|
|
|
|
caCert, err := os.ReadFile(cfg.SSLRootCert)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read CA cert: %w", err)
|
|
}
|
|
|
|
if ok := rootCertPool.AppendCertsFromPEM(caCert); !ok {
|
|
return nil, fmt.Errorf("failed to append CA cert to pool")
|
|
}
|
|
|
|
tlsConfig := &tls.Config{
|
|
RootCAs: rootCertPool,
|
|
MinVersion: tls.VersionTLS12,
|
|
//nolint:gosec // TODO: set server name
|
|
InsecureSkipVerify: true,
|
|
}
|
|
|
|
config, err := pgx.ParseConfig("")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse [empty] config: %w", err)
|
|
}
|
|
|
|
config.Host = cfg.Host
|
|
config.Port = cfg.Port
|
|
config.Database = cfg.Database
|
|
config.User = cfg.Username
|
|
config.Password = cfg.Password
|
|
config.TLSConfig = tlsConfig
|
|
config.RuntimeParams = map[string]string{"sslmode": cfg.SSLMode}
|
|
|
|
db := sqlx.NewDb(stdlib.OpenDB(*config), "pgx")
|
|
|
|
if err := db.Ping(); err != nil {
|
|
return nil, fmt.Errorf("failed to ping postgres: %w", err)
|
|
}
|
|
|
|
return &client{
|
|
config: cfg,
|
|
db: db,
|
|
}, nil
|
|
}
|
|
|
|
func countOffset(page, pageSize uint64) uint64 {
|
|
if page == 0 {
|
|
page = 1
|
|
}
|
|
|
|
if pageSize == 0 {
|
|
pageSize = DefaultPaginationPageSize
|
|
}
|
|
|
|
return (page - 1) * pageSize
|
|
}
|