This commit is contained in:
Alex Shevchuk
2025-08-18 17:12:04 +03:00
commit d84487d238
157 changed files with 160686 additions and 0 deletions

View 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
}