Skip to content

ci(databases): run the suite on mysql and postgres - #4

Merged
danielebarbaro merged 2 commits into
mainfrom
ci/database-matrix
Sep 8, 2026
Merged

ci(databases): run the suite on mysql and postgres#4
danielebarbaro merged 2 commits into
mainfrom
ci/database-matrix

Conversation

@danielebarbaro

Copy link
Copy Markdown
Contributor

The README named MySQL and PostgreSQL as supported while the workflow installed sqlite and pdo_sqlite and nothing else, so no query had ever run against either. The two operators added for this release are the ones most likely to differ: contains_any and contains_all go through whereJsonContains, which the three drivers compile into json_each, json_contains and a jsonb containment, and the contains filter carries an explicit escape clause.

A databases job runs the suite against MySQL 8.4 and PostgreSQL 17 as service containers. TestCase reads DB_DRIVER, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME and DB_PASSWORD and falls back to the in memory SQLite it used before, so nothing changes for a local run.

Both operator families and the escape clause turned out to work on all three. Two real defects did not.

Definitions came back in whatever order the database chose, so getCustomFields() and the generated filter and sort lists were ordered by insertion on SQLite and arbitrarily on a server, and the sort_order column that exists for this was never read. All three definition queries now order by sort_order and then by slug.

A decimal value read back differently per driver. MySQL and PostgreSQL return the full scale of the decimal(20,6) column, so a stored 12.5 came back as 12.500000 while SQLite gave 12.5. DecimalType trims the fraction so the value the consumer wrote is the value it reads.

The host tables the fixtures create are dropped on both ends of a test rather than only created, since a server keeps what the previous test left. The column type assertions accept the name each driver reports for a kind rather than the SQLite one.

Verified locally against mysql:8.4 and postgres:17 in Docker: 115 tests pass on all three drivers.

The README named MySQL and PostgreSQL as supported while the workflow
installed sqlite and pdo_sqlite and nothing else, so no query had ever
run against either. The two operators added for this release are the
ones most likely to differ: contains_any and contains_all go through
whereJsonContains, which the three drivers compile into json_each,
json_contains and a jsonb containment, and the contains filter carries
an explicit escape clause.

A databases job runs the suite against MySQL 8.4 and PostgreSQL 17 as
service containers. TestCase reads DB_DRIVER, DB_HOST, DB_PORT,
DB_DATABASE, DB_USERNAME and DB_PASSWORD and falls back to the in
memory SQLite it used before, so nothing changes for a local run.

Both operator families and the escape clause turned out to work on all
three. Two real defects did not.

Definitions came back in whatever order the database chose, so
getCustomFields() and the generated filter and sort lists were ordered
by insertion on SQLite and arbitrarily on a server, and the sort_order
column that exists for this was never read. All three definition
queries now order by sort_order and then by slug.

A decimal value read back differently per driver. MySQL and PostgreSQL
return the full scale of the decimal(20,6) column, so a stored 12.5
came back as 12.500000 while SQLite gave 12.5. DecimalType trims the
fraction so the value the consumer wrote is the value it reads.

The host tables the fixtures create are dropped on both ends of a test
rather than only created, since a server keeps what the previous test
left. The column type assertions accept the name each driver reports
for a kind rather than the SQLite one.

Verified locally against mysql:8.4 and postgres:17 in Docker: 115 tests
pass on all three drivers.
composer test:unit runs Pest in parallel, and the two processes shared
the one database the service container provides, so they created and
dropped the same tables at the same time:

    SQLSTATE[42S01]: Table 'custom_field_values' already exists

The job now calls Pest directly. Verified by reproducing the failure
with --parallel against mysql:8.4 and confirming the serial run passes.

That crash also exposed something worse: the interrupted run left its
tables behind, and every later run against the same server failed on a
schema it had never created. An in memory database starts empty each
time, a server does not. The test case now drops what a previous run
left before the migrator starts, so a server is usable again without
being recreated by hand. Verified by poisoning both a MySQL and a
PostgreSQL database with a crashed parallel run and watching the next
serial run come back green.
@danielebarbaro
danielebarbaro merged commit 18e900b into main Sep 8, 2026
18 checks passed
@danielebarbaro
danielebarbaro deleted the ci/database-matrix branch September 8, 2026 11:46
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