Fix: PostgreSQL expert review - cluster backup/restore improvements
Critical PostgreSQL-specific fixes identified by database expert review:
1. **Port always passed for localhost** (pg_dump, pg_restore, pg_dumpall, psql)
- Previously, port was only passed for non-localhost connections
- If user has PostgreSQL on non-standard port (e.g., 5433), commands
would connect to wrong instance or fail
- Now always passes -p PORT to all PostgreSQL tools
2. **CREATE DATABASE with encoding/locale preservation**
- Now creates databases with explicit ENCODING 'UTF8'
- Detects server's LC_COLLATE and uses it for new databases
- Prevents encoding mismatch errors during restore
- Falls back to simple CREATE if encoding fails (older PG versions)
3. **DROP DATABASE WITH (FORCE) for PostgreSQL 13+**
- Uses new WITH (FORCE) option to atomically terminate connections
- Prevents race condition where new connections are established
- Falls back to standard DROP for PostgreSQL < 13
- Also revokes CONNECT privilege before drop attempt
4. **Improved globals restore error handling**
- Distinguishes between FATAL errors (real problems) and regular
ERROR messages (like 'role already exists' which is expected)
- Only fails on FATAL errors or psql command failures
- Logs error count summary for visibility
5. **Better error classification in restore logs**
- Separate log levels for FATAL vs ERROR
- Debug-level logging for 'already exists' errors (expected)
- Error count tracking to avoid log spam
These fixes improve reliability for enterprise PostgreSQL deployments
with non-standard configurations and existing data.
This commit is contained in:
@@ -937,11 +937,15 @@ func (e *Engine) createSampleBackup(ctx context.Context, databaseName, outputFil
|
||||
func (e *Engine) backupGlobals(ctx context.Context, tempDir string) error {
|
||||
globalsFile := filepath.Join(tempDir, "globals.sql")
|
||||
|
||||
cmd := exec.CommandContext(ctx, "pg_dumpall", "--globals-only")
|
||||
if e.cfg.Host != "localhost" {
|
||||
cmd.Args = append(cmd.Args, "-h", e.cfg.Host, "-p", fmt.Sprintf("%d", e.cfg.Port))
|
||||
// CRITICAL: Always pass port even for localhost - user may have non-standard port
|
||||
cmd := exec.CommandContext(ctx, "pg_dumpall", "--globals-only",
|
||||
"-p", fmt.Sprintf("%d", e.cfg.Port),
|
||||
"-U", e.cfg.User)
|
||||
|
||||
// Only add -h flag for non-localhost to use Unix socket for peer auth
|
||||
if e.cfg.Host != "localhost" && e.cfg.Host != "127.0.0.1" && e.cfg.Host != "" {
|
||||
cmd.Args = append([]string{cmd.Args[0], "-h", e.cfg.Host}, cmd.Args[1:]...)
|
||||
}
|
||||
cmd.Args = append(cmd.Args, "-U", e.cfg.User)
|
||||
|
||||
cmd.Env = os.Environ()
|
||||
if e.cfg.Password != "" {
|
||||
|
||||
Reference in New Issue
Block a user