Skip to content

Add the Metadata exception namespace - #191

Merged
simon-mundy merged 2 commits into
php-db:0.6.xfrom
simon-mundy:exception/pr-2-metadata-exception
Sep 29, 2026
Merged

simon-mundy merged 2 commits into
php-db:0.6.xfrom
simon-mundy:exception/pr-2-metadata-exception

Conversation

@simon-mundy

@simon-mundy simon-mundy commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • QA improvement (unit/integration tests, CS fixes, etc.) that does not change code behavior

Checklist:

  • An issue has been created for this pull request.
  • I have added tests for my changes.
  • All new and existing tests passed.
  • Documentation has been updated accordingly.
  • This pull request targets the correct branch.

Description

PR 2 of 6 from #189, and the first worked example of the convention PR 1 documents.

Stacked on #190. GitHub cannot base a cross-fork PR on a fork branch, so this targets 0.6.x and therefore shows both commits. Only the second, 86526bbd, belongs to this PR. Merge #190 first; I will rebase this one after.

PhpDb\Metadata was the only component with no exception namespace at all. Metadata\Source\AbstractSource threw bare \Exception at seven sites, so every Metadata failure was invisible to catch (PhpDb\Exception\ExceptionInterface).

  • Adds Metadata\Exception\ExceptionInterface, InvalidArgumentException and RuntimeException, matching the other components.
  • Replaces the seven bare \Exception throws with named constructors: forUnknownColumn(), forUnknownConstraint(), forUnknownTable(), forUnknownTrigger(), forUnknownView() and forUnsupportedTableType().
  • Repoints the eleven @throws Exception annotations, which resolved to the new namespace rather than a class once the use Exception; import went.
  • Converges a message drift the audit on [RFC]: Named exception constructors and complete per-component exception namespaces #189 missed. AbstractSource reported the same missing table two ways: '"%s" does not exist' in getColumnNames() and 'Table "%s" does not exist' in getTable(). They now share 'Table "%s" does not exist', which matches the Trigger "%s" and View "%s" wording already in the class and names what is actually missing. Verified that no test in phpdb-mysql, phpdb-pgsql or phpdb-sqlite asserts on the old form.

Six named constructors rather than the seven listed on #189, because that convergence removed the need for a separate forUnknownTableName().

Motivation and Context

Refs #189. Depends on #190 for the convention and for the naming guard that this PR's constants have to satisfy.

Message text is otherwise byte-identical, so this is a mechanical change apart from the one converged message. The retype from bare \Exception is not a practical BC break: the new classes extend \RuntimeException, which extends \Exception, so existing catch (\Exception) blocks still match.

How has this been tested?

mago format --check, mago lint and mago analyze all exit 0. Full unit suite passes: 1583 tests, 3459 assertions.

Metadata\Exception\RuntimeException is at 6/6 methods and 7/7 lines covered. Getting there caught a defect worth noting: the first version of the test built its cases by calling the factories inside the data provider, which runs outside the coverage-collected region, so all six recorded zero coverage while every assertion passed. The provider now supplies the factory name, its arguments and its template, and the factory is called in the test body.

Expected messages are rendered from the public templates rather than restated, in the new test and in the eight AbstractSourceTest message assertions. Verified these still fail on a real defect by swapping the two arguments in forUnsupportedTableType(), which produced 2 failures.

Baseline changes are limited to three src/Metadata/Exception/ entries in analyzer-baseline.toml, matching how the sibling components' exception classes are already baselined for class-must-be-final and missing-api-or-internal. lint-baseline.toml is untouched by this commit.

@codecov

codecov Bot commented Sep 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@simon-mundy
simon-mundy force-pushed the exception/pr-2-metadata-exception branch from 86526bb to bf8f4a8 Compare September 28, 2026 06:38
@simon-mundy
simon-mundy force-pushed the exception/pr-2-metadata-exception branch from bf8f4a8 to 1496903 Compare September 28, 2026 22:52
simon-mundy added a commit to simon-mundy/phpdb that referenced this pull request Sep 28, 2026
… constructors

The last 5 throw sites outside the components covered by php-db#191 to php-db#194. Message
text is byte-identical, verified template by template against the originals.

- Add ResultSet\Exception\RuntimeException::forUnbufferedIteration()
- Add forNonAdapterAwareDelegate() to Exception\ContainerException, and give
  the three reasons that AdapterInterfaceFactory and
  AbstractAdapterInterfaceFactory passed as inline strings their own factories:
  forMissingConfigService(), forMissingConfiguration() and forMissingDriver(),
  each composing the reason into the SERVICE template
- Retype the delegator's non-AdapterAware guard from the root
  Exception\RuntimeException to ContainerException, which extends it, so the
  failure carries PSR-11's ContainerExceptionInterface as a container failure
  should
- Own the "not found in container" wording as ContainerException::MISSING_SERVICE
  while still throwing the ServiceManager's own ServiceNotFoundException. Laminas
  annotates that class @Final, so this package cannot own it; the throw site
  renders the template itself, which docs/book/exceptions.md now records as the
  single documented exception to the convention
- Derive the message assertions in the six test files the earlier PRs do not
  touch from the templates rather than restating them

One literal assertion is deliberately left in
test/unit/Container/TableIdentifierFactoryFactoryTest.php: it asserts
Sql\Exception\InvalidArgumentException::EMPTY_SEPARATOR, a constant php-db#192
introduces, so it can only be migrated once that has landed.

Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Metadata was the only component with no exception namespace, so its failures
were invisible to catch (PhpDb\Exception\ExceptionInterface).

- Add Metadata\Exception\InvalidArgumentException and RuntimeException, matching
  the other components. The namespace declares no ExceptionInterface of its own:
  both classes extend their PhpDb\Exception counterparts, where the single marker
  is declared, so they implement it by inheritance
- Register both concrete classes in ExceptionHierarchyTest's EXCEPTION_CLASSES
  map, so they come under the structural guards
- Replace the seven bare \Exception throws in AbstractSource with named
  constructors and repoint the eleven @throws annotations at them
- Converge the two "table does not exist" messages on 'Table "%s" does not
  exist', matching the Trigger and View wording already in the class
- Derive the AbstractSource message assertions from the templates rather than
  restating them, and call the factories in the test body so they record
  coverage, which a data provider does not

Refs php-db#189

Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
@simon-mundy
simon-mundy force-pushed the exception/pr-2-metadata-exception branch from 1496903 to 88b5bf5 Compare September 29, 2026 03:33
simon-mundy added a commit to simon-mundy/phpdb that referenced this pull request Sep 29, 2026
… constructors

The last 5 throw sites outside the components covered by php-db#191 to php-db#194. Message
text is byte-identical, verified template by template against the originals.

- Add ResultSet\Exception\RuntimeException::forUnbufferedIteration()
- Add forNonAdapterAwareDelegate() to Exception\ContainerException, and give
  the three reasons that AdapterInterfaceFactory and
  AbstractAdapterInterfaceFactory passed as inline strings their own factories:
  forMissingConfigService(), forMissingConfiguration() and forMissingDriver(),
  each composing the reason into the SERVICE template
- Retype the delegator's non-AdapterAware guard from the root
  Exception\RuntimeException to ContainerException, which extends it, so the
  failure carries PSR-11's ContainerExceptionInterface as a container failure
  should
- Own the "not found in container" wording as ContainerException::MISSING_SERVICE
  while still throwing the ServiceManager's own ServiceNotFoundException. Laminas
  annotates that class @Final, so this package cannot own it; the throw site
  renders the template itself, which docs/book/exceptions.md now records as the
  single documented exception to the convention
- Derive the message assertions in the six test files the earlier PRs do not
  touch from the templates rather than restating them

One literal assertion is deliberately left in
test/unit/Container/TableIdentifierFactoryFactoryTest.php: it asserts
Sql\Exception\InvalidArgumentException::EMPTY_SEPARATOR, a constant php-db#192
introduces, so it can only be migrated once that has landed.

Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
@simon-mundy
simon-mundy requested a review from tyrsson September 29, 2026 03:42
@simon-mundy simon-mundy self-assigned this Sep 29, 2026
@simon-mundy simon-mundy added this to the 0.6.0 milestone Sep 29, 2026
@github-project-automation github-project-automation Bot moved this to Todo in @phpdb Sep 29, 2026
@simon-mundy simon-mundy added documentation Improvements or additions to documentation qa Improvements in quality assurance of the project RFC RFC issue or PR labels Sep 29, 2026
tyrsson
tyrsson previously approved these changes Sep 29, 2026
@simon-mundy
simon-mundy dismissed tyrsson’s stale review September 29, 2026 03:48

The merge-base changed after approval.

@simon-mundy
simon-mundy requested a review from tyrsson September 29, 2026 03:54
@simon-mundy
simon-mundy merged commit ba3ae91 into php-db:0.6.x Sep 29, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request qa Improvements in quality assurance of the project RFC RFC issue or PR

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants