1
This commit is contained in:
107
internal/database/postgres/client.go
Normal file
107
internal/database/postgres/client.go
Normal file
@@ -0,0 +1,107 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user