Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions bin/postgresql-setup.in
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,87 @@ old_data_in_use()
}


# Detect locale settings from old cluster datadir
# Sets: old_cluster_lc_collate, old_cluster_lc_ctype, old_cluster_locale
detect_old_cluster_locale()
{
local old_datadir="$1"
local old_bindir="$2"
local old_port="$3"

old_cluster_lc_collate=""
old_cluster_lc_ctype=""
old_cluster_locale=""

if old_data_in_use; then
return 1
fi

# If server is not running, try to start it temporarily
debug "old cluster server is not running, attempting temporary start to query locale"

# Create a temporary socket directory
local temp_sockdir=$(mktemp -d 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$temp_sockdir" ]; then
debug "failed to create temporary socket directory"
return 1
fi

local temp_log="$old_datadir/temp_locale_query.log"

# Try to start server with minimal configuration
# Use a different port to avoid conflicts
local temp_port=$((old_port + 10000))

# Start server in background with minimal settings
# Use -m fast to speed up startup
if "$old_bindir/pg_ctl" -D "$old_datadir" -o "-p $temp_port -c listen_addresses='' -c unix_socket_directories='$temp_sockdir' -c max_connections=5 -c shared_buffers=128kB" start -w -l "$temp_log" -m fast >/dev/null 2>&1; then
debug "temporarily started old cluster server on port $temp_port"
# Give it a moment to be ready
sleep 2
else
debug "failed to start old cluster server temporarily (see $temp_log for details)"
rm -rf "$temp_sockdir"
rm -f "$temp_log"
return 1
fi


# Query locale from template1 database
local query="SELECT datcollate, datctype FROM pg_catalog.pg_database WHERE datname = 'template1'"
local result
local query_port="$temp_port"

# Perform query
local psql_exit_code=0
result=$(psql -t -A -h "$temp_sockdir" -p "$query_port" -d template1 -c "$query" 2>/dev/null)
psql_exit_code=$?

# Stop temporary server
"$old_bindir/pg_ctl" -D "$old_datadir" stop >/dev/null 2>&1
rm -rf "$temp_sockdir"
rm -f "$temp_log"

# Parse result
if [ $psql_exit_code -eq 0 ] && [ -n "$result" ]; then
# Parse result: datcollate|datctype
old_cluster_lc_collate=$(echo "$result" | cut -d'|' -f1 | tr -d ' ')
old_cluster_lc_ctype=$(echo "$result" | cut -d'|' -f2 | tr -d ' ')
old_cluster_locale="$old_cluster_lc_collate"

if [ -n "$old_cluster_lc_collate" ] && [ -n "$old_cluster_lc_ctype" ]; then
debug "detected locale from old cluster: collate=$old_cluster_lc_collate, ctype=$old_cluster_lc_ctype"
return 0
fi
fi

# If we couldn't detect it, return failure
warn $"Could not automatically detect locale settings from old cluster."
warn_q $"You may need to set PGSETUP_INITDB_OPTIONS manually with --lc-collate, --lc-ctype, and --locale options."
return 1
}


upgrade()
{
local inplace=false
Expand Down Expand Up @@ -275,6 +356,39 @@ upgrade()

info $"Upgrading database."

# Automatically detect locale settings from old cluster if not already set
# This addresses Bug 1152556: detect --locale from old datadir automatically
local locale_already_set=false
if [ -n "$PGSETUP_INITDB_OPTIONS" ]; then
if echo "$PGSETUP_INITDB_OPTIONS" | grep -qE -- "--lc-collate|--lc-ctype|--locale"; then
locale_already_set=true
fi
fi

if [ "$locale_already_set" != "true" ]; then
debug "attempting to auto-detect locale from old cluster"
if detect_old_cluster_locale "$pgdataold" "$upgradefrom_engine" "$PGPORT"; then
# Build initdb options with detected locale
local detected_opts="--lc-collate=$old_cluster_lc_collate --lc-ctype=$old_cluster_lc_ctype"
if [ -n "$old_cluster_locale" ]; then
detected_opts="$detected_opts --locale=$old_cluster_locale"
fi

# Append to existing PGSETUP_INITDB_OPTIONS if set, otherwise set it
if [ -n "$PGSETUP_INITDB_OPTIONS" ]; then
export PGSETUP_INITDB_OPTIONS="$PGSETUP_INITDB_OPTIONS $detected_opts"
else
export PGSETUP_INITDB_OPTIONS="$detected_opts"
fi

info $"Auto-detected locale settings from old cluster: $detected_opts"
else
debug "locale auto-detection failed, proceeding with system default locale"
fi
else
debug "locale options already set in PGSETUP_INITDB_OPTIONS, skipping auto-detection"
fi

scls_upgrade_hacks=
test -n "$upgradefrom_scls" && {
debug "scls [$upgradefrom_scls] will be enabled"
Expand Down
100 changes: 100 additions & 0 deletions tmt/tests/virtual/sanity/locale-change/locale.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k

. /usr/share/beakerlib/beakerlib.sh || exit 1

rlJournalStart
rlPhaseStartSetup
rlRun "git clone \"$REPO_URL\" repo"
rlRun "pushd repo"
rlRun "git fetch origin \"$PR_HEAD\""
rlRun "git checkout FETCH_HEAD"
rlRun "cat /etc/fedora-release"
rlRun "dnf -y install postgresql16-server"

rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup"
rlRun "./configure --prefix=/usr"
rlRun "make"
rlRun "./bin/postgresql-setup --init" 0 "Initializing database dir"
rlRun "systemctl start postgresql" 0 "Starting service"
rlRun "systemctl is-active postgresql" 0 "Verifying service running"
rlPhaseEnd

rlPhaseStartTest
rlRun "su - postgres -c \"
createdb testdb;
psql -U postgres -d testdb -c \\\"create table users (id serial primary key, name text)\\\";
psql -U postgres -d testdb -c \\\"insert into users (name) values ('Alice'), ('Bob'), ('Celine')\\\"
\""
rlRun "su - postgres -c '
psql -U postgres -d testdb -c \"select * from users\"
' > expected.txt"

echo "Expected:"
cat expected.txt

# change locale (https://wiki.archlinux.org/title/Locale#Make_locale_changes_immediate)
rlRun "localectl set-locale LANG=en_GB.UTF-8" 0 "Changing locale"
rlRun "unset LANG"
rlRun "source /etc/profile.d/lang.sh"
rlRun "locale"

rlRun "dnf -y remove postgresql16*" 0 "Removing postgresql 16"
rlRun "dnf -y install postgresql17-upgrade" 0 "Installing postgresql 17"
rlRun "./bin/postgresql-setup --upgrade" 0 "Running upgrade"

rlRun "systemctl start postgresql" 0 "Starting service again"
rlRun "systemctl is-active postgresql" 0 "Verifying service running"

rlRun "su - postgres -c '
psql -U postgres -d testdb -c \"select * from users\"
' > actual17.txt"

echo "Actual:"
cat actual17.txt

rlAssertNotDiffer expected.txt actual17.txt

rlRun "localectl set-locale LC_COLLATE=en_US.UTF-8" 0 "Changing LC_COLLATE"
rlRun "localectl set-locale LC_CTYPE=en_AU.UTF-8" 0 "Changing LC_CTYPE"
rlRun "unset LANG"
rlRun "source /etc/profile.d/lang.sh"
rlRun "locale"

rlRun "dnf -y remove postgresql17*" 0 "Removing postgresql 17"
rlRun "dnf -y install postgresql18-upgrade" 0 "Installing postgresql 18"
# TODO: remove if functionality added to the script
rlRun "/usr/lib64/pgsql/postgresql-17/bin/pg_checksums -e /var/lib/pgsql/data" 0 "Enabling data checksums for pg18"

rlRun "su - postgres -c '/usr/lib64/pgsql/postgresql-17/bin/pg_ctl -D /var/lib/pgsql/data -l /var/lib/pgsql/logfile start'" 0 "Starting postgres pre-upgrade"
rlRun "su - postgres -c '/usr/lib64/pgsql/postgresql-17/bin/pg_ctl -D /var/lib/pgsql/data status'" 0 "Verifying postgres is running"

rlRun "./bin/postgresql-setup --upgrade --debug" 1 "Trying to run upgrade"
rlRun "su - postgres -c '/usr/lib64/pgsql/postgresql-17/bin/pg_ctl -D /var/lib/pgsql/data stop'" 0 "Stopping old postgres"
rlRun "./bin/postgresql-setup --upgrade --debug" 0 "Upgrading"

rlRun "systemctl start postgresql" 0 "Starting service again"
rlRun "systemctl is-active postgresql" 0 "Verifying service running"

rlRun "su - postgres -c '
psql -U postgres -d testdb -c \"select * from users\"
' > actual18.txt"

echo "Actual:"
cat actual18.txt

rlAssertNotDiffer actual17.txt actual18.txt
rlPhaseEnd

rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -rf repo"
rlRun "echo 'LANG=en_US.UTF-8' > /etc/locale.conf" 0 "Resetting locale"
rlRun "unset LANG"
rlRun "source /etc/profile.d/lang.sh"
rlRun "systemctl stop postgresql" 0 "Stopping postgresql service"
rlRun "rm -rf /var/lib/pgsql" 0 "Removing database folder"
rlRun "dnf -y remove postgresql*" 0 "Uninstalling postgresql"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd
19 changes: 19 additions & 0 deletions tmt/tests/virtual/sanity/locale-change/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
summary: Check if upgrading a database works when using a different locale
name: locale-change
require:
- make
- m4
- docbook-utils
- help2man
- elinks
- coreutils
- autoconf
- automake
- autoconf-archive
- git
framework: beakerlib
contact: pkhartsk@redhat.com
tag:
- fedora-upgrade
test: ./locale.sh

Loading