Skip to content

Fix migrate:status when migrations table is absent#58

Open
davidwyly wants to merge 2 commits into
masterfrom
codex/fix-migrate-status-error-handling-f1r32i
Open

Fix migrate:status when migrations table is absent#58
davidwyly wants to merge 2 commits into
masterfrom
codex/fix-migrate-status-error-handling-f1r32i

Conversation

@davidwyly

Copy link
Copy Markdown
Owner

Motivation

  • migrate:status now constructs Migration with ensureTable=false, so the rxn_migrations table may not exist on fresh schemas and must be handled gracefully.
  • The framework Query layer wraps PDO errors in QueryException, so Migration::applied() catching only \PDOException could miss the real exception and crash instead of returning an empty applied list.
  • The change restores the previous behavior of showing pending migrations on a fresh database by recognizing missing-table errors regardless of the exception wrapper.

Description

  • Import QueryException in src/Rxn/Framework/Data/Migration.php and extend the catch in applied() to \PDOException | QueryException so both error types are handled.
  • Add a private helper isMissingMigrationsTable() that detects missing-table conditions by checking the SQLSTATE 42S02, MySQL driver message text 1146, or SQLite-style no such table in the exception message or code.
  • Return an empty applied list when the helper detects a missing migrations table and rethrow the exception for all other failures, preserving existing behavior for non-missing-table errors.

Testing

  • Ran a PHP syntax check with php -l src/Rxn/Framework/Data/Migration.php, which succeeded (no syntax errors).

Codex Task

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to restore bin/rxn migrate:status on fresh databases by making Migration::applied() tolerate a missing rxn_migrations table even when the Data layer surfaces the failure as a wrapped QueryException. It fits the framework’s migration tooling by keeping status inspection usable before any migration has been applied.

Changes:

  • Import QueryException and widen the exception handling in Migration::applied().
  • Add a private helper to recognize missing-table errors from SQLSTATE/message patterns.
  • Return an empty applied-migrations list for missing-table cases while rethrowing unrelated failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +87
$message = $exception->getMessage();
$code = (string)$exception->getCode();

return strpos($code, '42S02') !== false
|| strpos($message, '1146') !== false
|| stripos($message, 'no such table') !== false;
Comment on lines +71 to 75
} catch (\PDOException | QueryException $exception) {
if ($this->isMissingMigrationsTable($exception)) {
return [];
}
throw $exception;
@davidwyly

Copy link
Copy Markdown
Owner Author

@copilot apply changes based on the comments in this thread

…us; add MigrationAppliedTest

Agent-Logs-Url: https://github.com/davidwyly/rxn/sessions/7f9ef037-8704-4f4e-af3b-03c3e40feb82

Co-authored-by: davidwyly <13552783+davidwyly@users.noreply.github.com>

Copilot AI commented May 3, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Both review points are addressed in commit 822bcf3:

  1. isMissingMigrationsTable() false negative on prepare-time failures: Split the helper into isMissingMigrationsTable() (which now also walks getPrevious()) and a new exceptionIndicatesMissingTable() that adds strpos($message, '42S02') !== false. This means a QueryException("PDO Exception (code 42S02)", 500, $prev) produced by Query::prepare() is now correctly detected via the message, and its original \PDOException with SQLSTATE code 42S02 is also checked via getPrevious().

  2. Missing regression tests: Added MigrationAppliedTest covering four paths: SQLite in-memory execute-path (QueryException with no such table in message), prepare-style wrapped QueryException (message contains 42S02), direct \PDOException with SQLSTATE code 42S02 (via getPrevious() check), and an unrelated QueryException that must be rethrown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants