Skip to content

Add PostgreSQL database driver#428

Draft
adamziel wants to merge 599 commits into
WordPress:trunkfrom
adamziel:codex/postgresql-backend
Draft

Add PostgreSQL database driver#428
adamziel wants to merge 599 commits into
WordPress:trunkfrom
adamziel:codex/postgresql-backend

Conversation

@adamziel

@adamziel adamziel commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Big picture

Adds PostgreSQL backend support alongside the existing SQLite backend.

WordPress core unit tests pass to the same extent as with the SQLite backend.

Implementation checkpoints

  • PostgreSQL UDF rewrite checkpoint: e1b0bacfe9cd7dc12c2ab0927e7e1a7c73c53cb7 (Rewrite MySQL UDF calls for PostgreSQL).

Try it on a fresh WordPress site

Prerequisites: pdo and pdo_pgsql enabled in PHP.

Install the plugin files into the WordPress site:

export REPO=/path/to/sqlite-database-integration
export WP_ROOT=/path/to/wordpress

mkdir -p "$WP_ROOT/wp-content/plugins/sqlite-database-integration"
rsync -a --delete \
  "$REPO/packages/plugin-sqlite-database-integration/" \
  "$WP_ROOT/wp-content/plugins/sqlite-database-integration/"

# Replace the development symlink with a real copy of the shared database package:
rm -rf "$WP_ROOT/wp-content/plugins/sqlite-database-integration/wp-includes/database"
cp -R \
  "$REPO/packages/mysql-on-sqlite/src" \
  "$WP_ROOT/wp-content/plugins/sqlite-database-integration/wp-includes/database"

Install the WordPress database drop-in:

cp \
  "$WP_ROOT/wp-content/plugins/sqlite-database-integration/db.copy" \
  "$WP_ROOT/wp-content/db.php"

php -r '$file = getenv( "WP_ROOT" ) . "/wp-content/db.php"; $contents = file_get_contents( $file ); $contents = str_replace( array( "'{SQLITE_IMPLEMENTATION_FOLDER_PATH}'", "{SQLITE_PLUGIN}" ), array( "__DIR__ . \"/plugins/sqlite-database-integration\"", "sqlite-database-integration/load.php" ), $contents ); file_put_contents( $file, $contents );'

Configure the database access in wp-config.php:

define( 'DB_ENGINE', 'postgresql' );

define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wordpress' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', '127.0.0.1:5432' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );

Then open the site in a browser and run the normal WordPress installer at /wp-admin/install.php. The wp-content/db.php drop-in loads the PostgreSQL wpdb adapter before install, and the PostgreSQL install hooks translate the WordPress schema for PostgreSQL.

After install, a quick smoke test is enough to confirm the site is using the PostgreSQL adapter:

<?php
require __DIR__ . '/wp-load.php';
var_dump( DB_ENGINE );
var_dump( get_class( $GLOBALS['wpdb'] ) );

Expected output includes:

postgresql
WP_PostgreSQL_DB

Repo test environment

The repo still has a supported generated test environment for CI and local parity work:

WP_TEST_DB_BACKEND=postgresql composer run wp-setup
WP_TEST_DB_BACKEND=postgresql composer run wp-test-php
WP_TEST_DB_BACKEND=postgresql composer run wp-test-e2e

Those commands generate the WordPress checkout, Docker override, test configs, drop-in wiring, and node dependencies used by CI. They are useful for repeatable testing, but they are not required to try PostgreSQL on a fresh WordPress site.

@adamziel adamziel force-pushed the codex/postgresql-backend branch from 0565082 to f3b5bd7 Compare June 16, 2026 16:36
@adamziel adamziel changed the title Add PostgreSQL backend scaffolding Add PostgreSQL as a first-class WordPress test backend Jun 16, 2026
@adamziel adamziel changed the title Add PostgreSQL as a first-class WordPress test backend Add PostgreSQL database driver Jun 17, 2026
@adamziel adamziel force-pushed the codex/postgresql-backend branch from c7578b6 to 47915f7 Compare June 17, 2026 15:53
adamziel added 30 commits June 19, 2026 15:16
Fix the simple SELECT LIMIT append path so PostgreSQL rewrites no longer recurse, restore the public MySQL metadata table constants used by install regression guards, and keep the driver PHPCS-clean.

Verified with php -l, git diff --check, PHPCS for the driver, focused PostgreSQL regressions, and the full packages/mysql-on-sqlite PHPUnit suite.
Use the shared MySQL-style numeric coercion expression in the WordPress expired transient DELETE rewrite so serialized option_value text does not raise PostgreSQL bigint cast errors.

Cover the rewrite with serialized nonnumeric option_value rows and assert the unsafe CAST(b.option_value AS BIGINT) form is absent.
Rewrite MySQL single-quoted projection aliases after AS as PostgreSQL identifiers while leaving ordinary string literals untouched.

Add coverage for the WordPress Site Health information_schema query that used AS 'table', AS 'rows', and AS 'bytes'.

Verified with php -l, git diff --check, focused PHPUnit, and the full packages/mysql-on-sqlite PHPUnit suite.
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.

1 participant