Skip to content

DB: the query log is opt-in; a connection failure throws instead of printing - #13

Merged
daedeloth merged 1 commit into
masterfrom
fix/db-query-log-and-connect-errors
Oct 7, 2026
Merged

daedeloth merged 1 commit into
masterfrom
fix/db-query-log-and-connect-errors

Conversation

@daedeloth

Copy link
Copy Markdown
Member

What changes

The query log is opt-in

  • Database::setQueryLogEnabled(true) turns the query log on; it is off by default and the switch applies to every Database instance. Database::isQueryLogEnabled() reads it.
  • When off, no statement is stored: getAllQueries() returns an empty array and getLastQuery() returns null (it also returns null for an empty log, where it used to raise an undefined-offset notice).
  • When on, the log keeps the most recent Database::QUERY_LOG_LIMIT = 5000 statements (the previous limit let it reach 5001).
  • getQueryCounter() and getOriginCounters() work whether the log is on or off. The origin lookup no longer collects call arguments.
  • A logger set with setLogger() still receives every statement; that sink is chosen by the application and is not gated by the switch.

A connection failure throws instead of printing

  • MySQL::connect() throws a DbException with the fixed message DbException::CONNECTION_FAILED ("Database connection failed."). It no longer prints anything and no longer calls exit.
  • DbException::isConnectionError() tells a connection failure apart from a failed statement.
  • What the driver reported is kept for logging: getPrevious() carries its message and code, and getErrorCode() returns the driver's error number. The previous exception is created by the framework, so its stack trace does not hold the arguments of the connect call.
  • The connection charset is set with mysqli::set_charset() instead of a SET names statement, so real_escape_string() uses it too. A charset the server rejects is now a connection failure (it used to be ignored). An empty database.mysql.charset sets nothing.
  • The connect call runs with mysqli in exception mode and restores the previous report mode afterwards, so a failed connect raises no PHP warning in either report mode.
  • A failed attempt does not leave a connection behind; the next connect() tries again.

Compatibility

  • Applications that read getAllQueries() / getLastQuery() (for debug output, or a query-count assertion in a test) get an empty array / null until they call Database::setQueryLogEnabled(true). Add that call where the application decides it is in debug mode, before the queries it wants to see.
  • Applications that relied on the process ending when the database is unreachable now get an uncaught DbException at the first query, which goes to their own exception handling like any other DbException. Code that catches DbException around a query and treats every failure as a statement error can check isConnectionError().
  • A misspelled database.mysql.charset now fails the connection instead of leaving the server default in place.

Tests

DbQueryLogTest (switch, cap, counters, logger), MySQLConnectFailureTest (fixed message, no output, cause kept, retry, charset through the driver, rejected charset) and three cases in DbExceptionTest. They run without the mysqli extension: the connect step is split into openConnection() and applyCharset(), which the tests script.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DqZUi2UiBJP6rZoCSRcdpE

Query log: Database::setQueryLogEnabled(true) turns it on (off by
default, for every instance). When off nothing is stored,
getAllQueries() returns an empty array and getLastQuery() returns null.
When on it keeps the most recent Database::QUERY_LOG_LIMIT (5000)
statements. getQueryCounter() and getOriginCounters() are unaffected,
and a logger set with setLogger() still receives every statement.

Connection: MySQL::connect() throws a DbException with the fixed
message DbException::CONNECTION_FAILED instead of printing the error
and exiting; isConnectionError() tells it apart from a failed
statement. The driver's message and code are kept on the previous
exception. A charset the server rejects is a connection failure too.
The charset is set with mysqli::set_charset().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DqZUi2UiBJP6rZoCSRcdpE
@daedeloth
daedeloth merged commit 22a545e into master Oct 7, 2026
5 checks passed
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