We have two breaking changes to announce.
Breaking change to Rdbms Database subclassesThere are no Database subclasses currently known in Codesearch (besides those built-in to core). But, since the class is documented as "stable to extend" in API, an announcement is in order.
First, an explanation on what is happening. Currently, queries flow in the Rdbms library as follows: When Database::select() or similar is called (directly, or via the query builders), the Rdbms library internally builds the SQL text and then calls the general-purpose function Database::query(). Subsequently, ::query() then runs several regexes over the SQL text to figure out information about this query (which tables are affected, whether it’s a write query, what the query “verb” is, and so on). This is taxing and slow. The appservers at WMF, for example, spend 0.34% of CPU on web requests just to extract information from already-formatted SQL queries for logging purposes. This logic drastically reduces readability and maintainability of Rdbms internals.
To fix this, we've internally introduced a new class called Query, to represent the SQL text in a more structured way in the first place. This avoids having to first format structure data into SQL text only to reverse-engineer it right afterwards.
This change requires changing the protected Database::executeQuery() method to no longer accept a string argument and instead require a Query object. Additionally IDatabase::getTempTableWrites() has become a private method. See the patch or the ticket for more information.
The public Database::query() method continues to support a string argument, but now also supports a Query object. When given a string, it falls back to the old regexes to extract and create a Query object. With the newly introduced UnionQueryBuilder, we believe there are no longer cases where MediaWiki extensions have to call Database::query, and can instead adopt query builders for all their queries. Direct calls to Database::query outside of MediaWiki core are now highly discouraged.
Many parts of core typehint to IDatabase, but most times these always return a replica database. For example, ApiBase::getDB(). This means the interface technically allows calling insert(), and this is indeed valid, but would also immediately throw a fatal error once the method is entered. Going forward, most of these will be typehinted to IReadableDatabase instead, which is a narrower interface (34 public methods instead of 83).