Skip to content

fix: Add PostgreSQL collation refresh script for glibc updates#1190

Open
SanchitPanchwatikar wants to merge 4 commits into
Epic-Breakfast-Productions:developmentfrom
SanchitPanchwatikar:fix/postgres-collation-refresh
Open

fix: Add PostgreSQL collation refresh script for glibc updates#1190
SanchitPanchwatikar wants to merge 4 commits into
Epic-Breakfast-Productions:developmentfrom
SanchitPanchwatikar:fix/postgres-collation-refresh

Conversation

@SanchitPanchwatikar
Copy link
Copy Markdown

@SanchitPanchwatikar SanchitPanchwatikar commented Apr 8, 2026

Fixes #1138

When PostgreSQL minor patches are applied through container updates, the glibc library may also be updated. This can cause collation version mismatches that break queries. This commit adds an initialization script that automatically refreshes collation versions for all non-template databases when the container restarts.

The script:

  • Only runs on existing databases (not new installations)
  • Checks which databases need collation refresh
  • Runs ALTER DATABASE REFRESH COLLATION VERSION on affected databases
  • Includes proper error handling and logging

The script is mounted in the Docker Compose PostgreSQL service at /docker-entrypoint-initdb.d/

Checklist:

  • Tested

Summary by CodeRabbit

  • Chores
    • Deployment updated to run database collation refresh automatically on container restarts/upgrades, reducing migration-related issues and improving stability.
    • Container startup now ensures initialization scripts are executed on each start (when appropriate), ensuring maintenance tasks run reliably after upgrades.

Fixes Epic-Breakfast-Productions#1138

When PostgreSQL minor patches are applied through container updates, the glibc library may also be updated. This can cause collation version mismatches that break queries. This commit adds an initialization script that automatically refreshes collation versions for all non-template databases when the container restarts.

The script:
- Only runs on existing databases (not new installations)
- Checks which databases need collation refresh
- Runs ALTER DATABASE REFRESH COLLATION VERSION on affected databases
- Includes proper error handling and logging

The script is mounted in the Docker Compose PostgreSQL service at /docker-entrypoint-initdb.d/

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cde45216-3c9d-479a-bccc-ec06f5bef8a6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Avast: Docker Compose now mounts ./setup/init-db and a custom entrypoint into the Postgres service; a new entrypoint runs init scripts on every start and delegates to the official Postgres entrypoint, while a refreshed-collations script detects and issues ALTER DATABASE ... REFRESH COLLATION VERSION for affected DBs on restarts.

Changes

Cohort / File(s) Summary
Compose config
deployment/Compose/compose/compose.yaml
Added bind mounts: ./setup/init-db/docker-entrypoint-initdb.d and ./setup/docker-entrypoint.sh/usr/local/bin/custom-entrypoint.sh; set service entrypoint to ["/usr/local/bin/custom-entrypoint.sh"].
Custom entrypoint
deployment/Compose/compose/setup/docker-entrypoint.sh
New wrapper entrypoint that, on each container start, runs executable .sh files found in /docker-entrypoint-initdb.d/ then execs the official Postgres entrypoint with original args.
Collation refresh script
deployment/Compose/compose/setup/init-db/01-refresh-collations.sh
New script that runs only when Postgres data exists; queries DBs with collation version mismatches and runs ALTER DATABASE "<db>" REFRESH COLLATION VERSION for each. Includes non-fatal failure handling.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Host as Docker Host
  participant Compose as Compose Postgres Service
  participant Entrypoint as /usr/local/bin/custom-entrypoint.sh
  participant InitDir as /docker-entrypoint-initdb.d
  participant DockerEP as /usr/local/bin/docker-entrypoint.sh
  participant Postgres as Postgres Server

  Host->>Compose: start container
  Compose->>Entrypoint: run custom entrypoint
  Entrypoint->>InitDir: list executable *.sh files
  InitDir-->>Entrypoint: script(s) (e.g., 01-refresh-collations.sh)
  Entrypoint->>Entrypoint: execute script(s)
  Entrypoint->>Postgres: (scripts connect as postgres user) run ALTER DATABASE ... REFRESH COLLATION VERSION
  Entrypoint->>DockerEP: exec official docker-entrypoint.sh "$@"
  DockerEP->>Postgres: start postgres process
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

⚓ Hoist the mainsail, mate — a new script takes the wheel,

On every start she checks the collation keel.
If versions drift where old libraries roam,
It mends each database and brings 'em home.
A tidy ship, aye — all set to sail again.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: adding a PostgreSQL collation refresh script to handle glibc updates during container restarts.
Description check ✅ Passed The description provides adequate context linking to issue #1138, explains the problem and solution, and lists key features, though the testing checklist item remains unchecked.
Linked Issues check ✅ Passed The pull request fulfills all primary coding requirements from issue #1138: detects upgrades on existing data, identifies non-template databases needing refresh, executes the ALTER DATABASE command, and provides automated mechanism in /docker-entrypoint-initdb.d/.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the collation refresh requirement: docker-entrypoint.sh wrapper for executing init scripts on restart, 01-refresh-collations.sh for the refresh logic, and compose.yaml configuration to integrate them.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6dd89f09-0fdf-45fb-80f9-8c4e81abd789

📥 Commits

Reviewing files that changed from the base of the PR and between a164f68 and 1261687.

📒 Files selected for processing (2)
  • deployment/Compose/compose/compose.yaml
  • deployment/Compose/compose/setup/init-db/01-refresh-collations.sh
📜 Review details
🔇 Additional comments (1)
deployment/Compose/compose/setup/init-db/01-refresh-collations.sh (1)

1-7: Ahoy, mate! The hull looks seaworthy on first inspection.

Aye, checkin' for PG_VERSION before we set sail be a sound approach—she'll only run on an existing vessel, not when we're first launchin' from the shipyard. The shebang and set -e be proper rigging for this here script.

Comment thread deployment/Compose/compose/compose.yaml
Comment thread deployment/Compose/compose/setup/init-db/01-refresh-collations.sh Outdated
Comment thread deployment/Compose/compose/setup/init-db/01-refresh-collations.sh Outdated
Comment thread deployment/Compose/compose/setup/init-db/01-refresh-collations.sh
- Fix docker-entrypoint-initdb.d limitation: Replace mounting init scripts in entrypoint-initdb.d (which only runs on fresh init) with a custom entrypoint wrapper that runs on every container start
- Fix SQL syntax: pg_collation_actual_version() requires an OID argument, not a COLLATE clause. Use pg_collation_actual_version(oid) and add IS NOT NULL check for collversion
- Improve error logging: Replace suppressed stderr with visible warning messages when collation check fails
- Add proper shell quoting: Quote database name variable in psql commands and ALTER DATABASE statement to prevent injection attacks and handle special characters
- Remove unnecessary su postgres calls: Script runs as postgres user through the entrypoint, so su is redundant

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a46397ca-15ce-4bdd-9a62-918125bca76a

📥 Commits

Reviewing files that changed from the base of the PR and between 1261687 and ed51014.

📒 Files selected for processing (3)
  • deployment/Compose/compose/compose.yaml
  • deployment/Compose/compose/setup/docker-entrypoint.sh
  • deployment/Compose/compose/setup/init-db/01-refresh-collations.sh
✅ Files skipped from review due to trivial changes (1)
  • deployment/Compose/compose/setup/init-db/01-refresh-collations.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • deployment/Compose/compose/compose.yaml
📜 Review details
🔇 Additional comments (1)
deployment/Compose/compose/setup/docker-entrypoint.sh (1)

19-19: ⛵ Good helm on Line 19: exec ... "$@" correctly preserves the original command/args.

Comment on lines +8 to +16
if [ -f /var/lib/postgresql/data/PG_VERSION ]; then
echo "Running custom initialization tasks..."
for script in /docker-entrypoint-initdb.d/*; do
if [ -f "$script" ] && [ -x "$script" ] && [[ "$script" == *.sh ]]; then
echo "Running $script"
"$script"
fi
done
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🚨 Line 8-16 runs DB maintenance before Postgres is up, so psql-based init scripts can fail hard.

The wrapper executes scripts before Line 19 delegates to the official entrypoint. But deployment/Compose/compose/setup/init-db/01-refresh-collations.sh runs psql; without a running server, that path can fail under set -e and break startup.

Safer direction
-# Run our custom initialization scripts
-if [ -f /var/lib/postgresql/data/PG_VERSION ]; then
-    echo "Running custom initialization tasks..."
-    for script in /docker-entrypoint-initdb.d/*; do
-        if [ -f "$script" ] && [ -x "$script" ] && [[ "$script" == *.sh ]]; then
-            echo "Running $script"
-            "$script"
-        fi
-    done
-fi
-
-# Invoke the original postgres entrypoint
-exec /usr/local/bin/docker-entrypoint.sh "$@"
+# NOTE: DB-dependent scripts must run only after postgres is accepting connections.
+# Consider moving collation refresh to:
+# 1) a post-start one-shot job (after healthcheck), or
+# 2) logic that explicitly starts/stops a temporary server before running scripts.
+exec /usr/local/bin/docker-entrypoint.sh "$@"

if [ -f /var/lib/postgresql/data/PG_VERSION ]; then
echo "Running custom initialization tasks..."
for script in /docker-entrypoint-initdb.d/*; do
if [ -f "$script" ] && [ -x "$script" ] && [[ "$script" == *.sh ]]; then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

⚓ Line 11 blocks the refresh script from ever running in this Compose setup.

Ye guard uses -x, but deployment/Compose/compose/compose.yaml Line 43 bind-mounts host files as-is, and deployment/Compose/compose/setup/init-db/01-refresh-collations.sh is non-executable in the provided context. Result: the collation fix is silently skipped.

Proposed patch
-        if [ -f "$script" ] && [ -x "$script" ] && [[ "$script" == *.sh ]]; then
+        if [ -f "$script" ] && [[ "$script" == *.sh ]]; then
             echo "Running $script"
-            "$script"
+            bash "$script"
         fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ -f "$script" ] && [ -x "$script" ] && [[ "$script" == *.sh ]]; then
if [ -f "$script" ] && [[ "$script" == *.sh ]]; then
echo "Running $script"
bash "$script"
fi

@GregJohnStewart
Copy link
Copy Markdown
Contributor

@SanchitPanchwatikar I apologize for the delay in looking at this, had some workflows already in the works. I hope to get to this this weekend.

I will say that the original ticket was meant for the single node deployment as opposed to the compose, but this will still be quite useful and drop-in capable in that setting too, so it is very much appreciated.

@GregJohnStewart GregJohnStewart changed the base branch from main to development May 10, 2026 23:07
@GregJohnStewart
Copy link
Copy Markdown
Contributor

@SanchitPanchwatikar apologies again, time makes fools of us all. This is at the top of my list this week.

@GregJohnStewart
Copy link
Copy Markdown
Contributor

@all-contributors please add @SanchitPanchwatikar for code

@allcontributors
Copy link
Copy Markdown
Contributor

@GregJohnStewart

I've put up a pull request to add @SanchitPanchwatikar! 🎉

@GregJohnStewart
Copy link
Copy Markdown
Contributor

@SanchitPanchwatikar Happen to have tested this? Trying to find a specific conbination of postgres versions but they all seem to have been updated with compatible glibc versions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR]: SNH - Postgres - fix issues with aged data running collation mismatches

3 participants