Skip to content

Conversation

@JanJakes
Copy link
Member

@JanJakes JanJakes commented Dec 5, 2025

WIP

@JanJakes JanJakes force-pushed the pdo-api branch 8 times, most recently from fd4cc59 to c02c987 Compare December 10, 2025 19:48
@JanJakes JanJakes force-pushed the pdo-api branch 9 times, most recently from 12df654 to 9e8e453 Compare December 17, 2025 12:54
adamziel added a commit that referenced this pull request Dec 18, 2025
Extracting smaller chunks from
#291 so we
can review and merge them independently.

This PR includes the following changes:
- Removed support for nested transactions. MySQL doesn't support them.
- Implemented PDO-like APIs for start transaction, commit, and rollback.
- The PDO-like APIs differ from an equivalent SQL command in that they
always throw an exception in scenarios when a transaction was already
started or not yet started (depending on the method), irrespective of
the `ATTR_ERRMODE` setting.
- Polyfill `PDO::inTransaction()` on PHP < 8.4, where it is not reliable
([issue](https://bugs.php.net/bug.php?id=81227),
[PR](php/php-src#14268)).
}

public function test_connection(): void {
$driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=WordPress;' );
Copy link
Collaborator

Choose a reason for hiding this comment

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

nice ❤️

*
* The driver requires PDO with the SQLite driver, and the PCRE engine.
*/
class WP_PDO_MySQL_On_SQLite extends PDO {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, so the connection driver is just this now and the other class only wraps it and translates PDO output into WordPress information. Really nice!

Copy link
Collaborator

@adamziel adamziel Dec 18, 2025

Choose a reason for hiding this comment

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

Can we intentionally split this into two PRs where one would make this change directly in the class-wp-sqlite-connection.php and move the actual WP SQLite connection class to another file? Just so that we get to review what changes in the driver logic. Right now this file is 6,5k new lines and I'm not sure which ones overlap exactly with the previous driver and which ones were modified or added. Once such a PR is merged, we could swap the file names in a follow-up PR to end up with the useful naming scheme this PR proposes. That's a bit of GitHub hacking, but it should support us here.

Copy link
Member Author

@JanJakes JanJakes Dec 18, 2025

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

@adamziel Extracted into #297.

Copy link
Collaborator

@adamziel adamziel Dec 18, 2025

Choose a reason for hiding this comment

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

I'm still getting some reasonably recent search results when I google for "PHP Fatal error: Class 'PDO' not found". We might want to polyfill the core PDO class when it's missing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's not the blocker here by the way, we could follow up with this. I don't think we'll get any problem reports early on but let's still take this into consideration

adamziel added a commit that referenced this pull request Dec 18, 2025
Extracting smaller chunks from
#291 so we
can review and merge them independently.

This PR adds `Table` column to `SHOW CREATE TABLE` statements, [as per
MySQL behavior](https://onecompiler.com/mysql/447x6gea7).
adamziel added a commit that referenced this pull request Dec 18, 2025
Extracting smaller chunks from
#291 so we
can review and merge them independently.

This PR renames the current `WP_SQLite_Driver` to
`WP_PDO_MySQL_On_SQLite` and reintroduces the `WP_SQLite_Driver` as a
simple proxy over the new renamed class. It's done in these two steps
(first rename, then reintroduce) so that Git understands the rename and
presents history (hopefully) accurately.

The changes are better understood in a commit-by-commit view.

#### `WP_PDO_MySQL_On_SQLite` vs `WP_SQLite_Driver`
The "reintroduced" `WP_SQLite_Driver` is not meant to be permanent. It
is a temporary proxy so we can gradually modify `WP_PDO_MySQL_On_SQLite`
to support PDO APIs while not touching the driver API just yet. Once the
basics of PDO API are in place, we can make all dependencies use the new
class directly and then remove the `WP_SQLite_Driver`.

That is, in the future, the `WP_SQLite_DB extends wpdb` will use
directly the new `WP_PDO_MySQL_On_SQLite` class.
*/

/**
* Some PDOStatement methods are not compatible across different PHP versions.
Copy link
Collaborator

Choose a reason for hiding this comment

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

oh wow

) {
$this->pdo = $pdo;
$this->sqlite_column_meta = $sqlite_column_metadata;
$this->rows = $rows;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This implies we're always loading the full result set into memory. Do we have to do that? I worry we could blow up memory on some large queries.

Copy link
Member Author

@JanJakes JanJakes Dec 18, 2025

Choose a reason for hiding this comment

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

Do we have to do that?

@adamziel In most cases, fortunately not. But in some, when we construct the result in PHP (things like SHOW GRANTS, etc.), we need to have a "synthetic" statement that is implementing the PDO API on top of PHP arrays.

For all statements where a MySQL statement corresponds to an SQLite statement, it will be better to use a "proxy" statement. We can't use the SQLite statement directly because some things like column metadata formats differ, but we can use a proxy to avoid loading all results into memory. I actually have a class-wp-pdo-proxy-statement.php‎ in a WIP commit, but I'll probably extract it to a follow-up PR. Here's why I think it's fine:

In the first step, we can use the synthetic statement for everything because 1) the current driver already stores everything in memory ($this->last_result, etc.), and 2) $wpdb loads everything in memory as well. So I think I can complete this PR with the "synthetic" statement, and then in the next PR, I would replace all the $this->last_something props with a single $this->last_result_statement that we would use as the proxy target.

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.

3 participants