package db import ( "errors" "fmt" "strings" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgtype" "github.com/memohai/memoh/internal/config" ) // DSN builds a PostgreSQL connection string from config. func DSN(cfg config.PostgresConfig) string { return fmt.Sprintf( "postgres://%s:%s@%s:%d/%s?sslmode=%s", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Database, cfg.SSLMode, ) } // ParseUUID converts a string UUID to pgtype.UUID. func ParseUUID(id string) (pgtype.UUID, error) { parsed, err := uuid.Parse(strings.TrimSpace(id)) if err != nil { return pgtype.UUID{}, fmt.Errorf("invalid UUID: %w", err) } var pgID pgtype.UUID pgID.Valid = true copy(pgID.Bytes[:], parsed[:]) return pgID, nil } // TimeFromPg converts a pgtype.Timestamptz to time.Time. func TimeFromPg(value pgtype.Timestamptz) time.Time { if value.Valid { return value.Time } return time.Time{} } // TextToString returns the string value of pgtype.Text, or "" when invalid. func TextToString(value pgtype.Text) string { if !value.Valid { return "" } return value.String } // IsUniqueViolation reports whether err is a PostgreSQL unique constraint violation (SQLSTATE 23505). func IsUniqueViolation(err error) bool { var pgErr *pgconn.PgError if !errors.As(err, &pgErr) { return false } return pgErr.Code == "23505" }