Commit Graph
2 Commits
Author SHA1 Message Date
e20fb2a792 feat(db): add MySQL 8.4 support (#4048)
Add MySQL 8.4 compatibility, including a utf8mb4 conversion migration,
hardened foreign key handling, and expanded CI database coverage.

Migrations:
- Add Mysql84Utf8mb4Conversion migration using
  sqlscripts/3.4.3_mysql84_utf8mb4_conversion.sql via executeScript()
- Drop ospos_people composite index before conversion, since its
  prefix length exceeds the 3072-byte key limit under utf8mb4
- Add assertNoCollationCollisions() pre-flight check to fail fast on
  unique values that collide under utf8mb4_unicode_520_ci, instead of
  hitting "Duplicate entry" partway through ALTER TABLE
- Wrap the conversion in try/catch so foreign keys are recreated on
  failure; log restore errors separately so they don't mask the
  original exception
- Throw RuntimeException if re-adding the people index fails
- Remove the re-add of the sales_items_taxes FK in down(), which
  MySQL 8.4 rejects without a unique key
- Revert edits to historical migrations; fix FK handling and table
  names

migration_helper:
- Add shared dropAllForeignKeyConstraints() and
  recreateForeignKeyConstraints(); table/column now optional, dropping
  all FKs in the schema when omitted
- Match CONSTRAINT_SCHEMA when joining KEY_COLUMN_USAGE to
  REFERENTIAL_CONSTRAINTS to avoid cross-schema name collisions
- Rebuild FK lookup with the query builder and bound values instead
  of interpolated SQL

CI/tests:
- Add mysql:5.7, mariadb:10.6 and mariadb:10.11 to PHPUnit matrix
- Use master instead of latest image tag; improve CI robustness
- Mock table() in FailedQueryConnectionTrait so query builder chains
  work against the failing connection

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-authored-by: aliworksx08 <57456290+aliworksx08@users.noreply.github.com>
Co-authored-by: jekkos <jeroen.peelaerts@gmail.com>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-19 14:24:51 +04:00
jekkosandobjecttothis 9fef0bd88f fix(models): handle query() returning false in result-consuming methods (#4734)
* fix(models): handle query() returning false in result-consuming methods

As of CI 4.1.2, Connection::query() returns false when a query fails
(previously an empty result object). Guard the model/helper methods that
consume the result so a failed query degrades to an empty result instead
of throwing "Call to member function getResultArray() on false".

- Tax::get_taxes()
- Sale::get_all_suspended()
- Reports\Inventory_low::getData()
- migration_helper: dropAllForeignKeyConstraints(), indexExists(),
  primaryKeyExists()

Adds QueryFalseGuardTest forcing query() to return false. Closes #3634.

* test(query-false): mock concrete driver instead of abstract BaseConnection

onlyMethods() does not stub the 16 abstract methods on BaseConnection, so
mocking it produced an invalid double. Mock the concrete driver class
(resolved from the live test connection) instead.

* fix(3634): fail loudly when migration metadata queries return false

Model read methods degrade to an empty result on a failed query, but the
migration metadata helpers (indexExists, primaryKeyExists,
dropAllForeignKeyConstraints) must not mistake a failed query for 'not
found' and proceed with schema changes. They now throw a DatabaseException
so the migration aborts loudly.

- Add an optional injectable BaseConnection param for testability.
- Add missing docstrings (docstring-coverage check).
- Add regression tests asserting the helpers throw on a failed query.

* fix(3634): use supplied connection for FK drop; stub error() in tests

Address CodeRabbit review: dropAllForeignKeyConstraints now builds its
Forge from the supplied connection (consistent with the lookup) instead of
always the default one. Test mock also stubs error() to avoid a warning on
the constructor-disabled connection.

* fix(3634): revert FK drop to Database::forge() (driver-specific forge)

new Forge($db) creates the base Forge which does not implement
dropForeignKey for the driver ('This feature is not available'), breaking
migrations. Restore Database::forge(), which loads the driver-specific
Forge via the factory. The optional connection param is retained solely
for testing the fail-loud behavior on the lookup path.

* test(3634): add regression test for Inventory_low::getData query-failure guard

Covers the low-stock report's degrade-to-empty behavior on a failed query,
addressing the CodeRabbit note that it lacked a focused test.

* test(3634): adopt test{Method}_{Purpose} naming convention

Align QueryFalseGuardTest method names with the convention from #4730
(testGetTaxes_ReturnsEmptyArrayWhenQueryFails, etc.), per review.

* test: split QueryFalseGuardTest into per-component test files

Apply CodeRabbit review: extract the shared failing-connection helpers
into tests/Support/FailedQueryConnectionTrait.php and move each test to
its component's test file (TaxTest, SaleTest, Inventory_lowTest,
migration_helperTest). Use fresh model instances instead of the shared
model() singleton so the injected failing connection does not leak into
other tests.

* style(tests): remove redundant docblocks from query-failure regression tests

---------

Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-10-08 22:30:16 +02:00