Avoid the call to internal constructor of AndExpressionGroup and
OrExpressionGroup by creating a factory function similiar as the
IReadableDatabase::expr function for Expression objects.
This is also a replacement for calls to ISQLPlatform::makeList with
LIST_AND or LIST_OR argument to reduce passing sql as string to the
query builders.
Created two functions to allow the return type to be set for both
expression group to allow further calls of ->and() or ->or() on the
returned object.
Depending on the length of the array argument to makeList() it is
sometimes hard to see if the list gets converted to AND or OR, having
the operator in the function name makes it easier to read, so two
functions are helpful in this case as well.
Bug: T358961
Change-Id: Ica29689cbd0b111b099bb09b20845f85ae4c3376
And deprecated aliases for the the no namespaced classes.
ReplicatedBagOStuff that already is deprecated isn't moved.
Bug: T353458
Change-Id: Ie01962517e5b53e59b9721e9996d4f1ea95abb51
Previously, DatabaseMySQL and SQLPlatform could fall out of sync in
selectDomain() due the use of setPrefix instead of setCurrentDomain().
The database name would be left unchanged in the SQLPlatform instance.
Change-Id: I571895192052937768d0197c7c99cfe6b774282b
* Instead of quoting any possible input as an identifier, validate the
input and fail if it contains a special character. This allows us to
simplify the implementation of the corresponding unquoting in
SQLPlatform::extractTableNameComponents.
* Add getIdentifierQuoteChar(), and unify the implementations except
for this one detail.
* addIdentifierQuotes() was/is not abstract. Remove the incorrect
comment about this from DatabaseTest. I tried removing the stub from
SQLPlatformTestHelper but there were 170 test failures, so it gets a
TODO for now.
Change-Id: I711968b17b303bbb5efd2882bc676b695d25ef7f
Tracking of "pristine" status in Database supported omission of TRUNCATE
queries for temporary tables that are untouched by unit tests. Since we
now detect the used tables, this is no longer necessary.
Also, make the temp table info into a class.
Change-Id: I57ff5b43cc7551ca32130f6987edd5f7c4f79910
Track the insert ID value in Database, similar to the affected rows.
This makes it possible for subclasses to stash or override the value,
which is useful when emulating a write operation using multiple queries.
This includes the case of internal use of atomic sections, where the
COMMIT/RELEASE can reset the last_insert_id tracked in the PECL driver
itself.
Use separate methods and fields for "last query statement" information
and "last query method" information.
Make insertId() for SQLite and Postgres better match MySQL:
* Return 0 if the last query statement did not change any rows.
This helps protect against callers that fail to check affectedRows().
* Make it return the existing ROWID/SERIAL column when upsert() updates
an existing row. This adds a new getInsertIdColumnForUpsert() helper
function.
Directly use query() in doReplace() and doInsertSelectGeneric() to make
the affected row/ID logic easier to follow.
Improve insertId() and affectedRows() documentation.
Add more integration tests of row insertion methods.
Bug: T314100
Change-Id: I7d43a2e52260e66acb713554bb883f5f4a14d010
Subclasses no longer have to implement fetchAffectedRowCount()
and affectedRows() no longer depends on the driver connection
handle.
Set "port" to $wgDBport in LBFactoryTest/LoadBalancerTest to
avoid postgres failures.
Bug: T314100
Change-Id: Ib31a9d2db18d7ba7dcf61fb110d0fef53f455464
Make rollback() return early and defer to flushSession() when called
on a handle with a critical section error. Trying to send ROLLBACK and
possibly run transaction callbacks will fail at this point. Note that
the normal calling pattern for recovery (e.g. what MWExceptionHandler
ultimately does) is calling LBF::rollbackPrimaryChanges()/DB::rollback()
before LBF::flushPrimarySessions()/DB::flushSession().
Make flushSession() treat critical section errors like disconnects.
The connection will be destroyed and the session state in the Database
handle will be reset, making the handle usable again.
This is useful for things that DeferredUpdates and JobRunner, that
loop through a set of tasks with exception handling meant to maintain
some level of failure isolation.
Bug: T328043
Change-Id: I65e931560757502d192daf84c3df5001266056d5
* Unnecessary regex modifier. I agree with this inspection which flags
/s modifiers on regexes that don't use a dot.
* Property declared dynamically.
* Unused local variable. But it's acceptable for an unused local
variable to take the return value of a method under test, when it is
being tested for its side-effects. And it's acceptable for an unused
local variable to document unused list expansion elements, or the
nature of array keys in a foreach.
Change-Id: I067b5b45dd1138c00e7269b66d3d1385f202fe7f
Just methods where adding "static" to the declaration was enough, I
didn't do anything with providers that used $this.
Initially by search and replace. There were many mistakes which I
found mostly by running the PHPStorm inspection which searches for
$this usage in a static method. Later I used the PHPStorm "make static"
action which avoids the more obvious mistakes.
Bug: T332865
Change-Id: I47ed6692945607dfa5c139d42edbd934fa4f3a36
We'd lose more useful coverage and spend more effort keeping these
accurate through refactors etc than is worth the theoretically "bad"
accidental coverage. Plus, even then we still very often forget to
update these and waste time digging into seemingly uncovered code
and either write duplicate test or discover they are already covered.
Especially for private methods this can be a flawed endavour as
we tend to trust tests when changing those and thus feel we shouldn't
update tests, except it's riddled with private method mentions for
coverage purposes (not in terms of actual called code).
I think the best practice is to write good narrow unit tests,
not to write bad tests and then hide their coverage. Generally
that's what we do. Maybe these are useful when invoking a huge
legacy class, but generally we don't need these I think, at least
in the libs our team maintains.
Change-Id: I4c7d826c7ec654b9efa20778c46c498784661f1c
Notable changes:
* In SqlBagOStuff::getConnectionFromServerInfo, only two loggers were
injected. The rest implicitly got a NullLogger due to being absent.
These are now effectively unsilenced.
* Database::__construct() required almost all parameters, even the
loggers. I've wanted to move some of DatabaseFactory into the ctor
here for a while. In order to make this change not a breaking
change, the new 'logger' parameter is optional with NullLogger as
default. This allowed some of the test cases, which were simply
passing NullLogger, to be fixed by passing nothing instead of
passing the new option name.
The Database class is behind a dozen layers of indirection for
real use, so this will still be injected just fine (DBF, LB, LBF,
MWLBF, etc.).
* In LegacyLogger, the handling for $wgDBerrorLog was previously
limited to DBConnection and DBQuery. This now includes errors
from other (generally, newer) parts of Rdbms as well, which were
previously missing.
This only affects sites (typically CI and dev setup) where
$wgDBerrorLog is used, as opposed to the more common
$wgDebugLogGroups by-channel configuration.
* TransactionProfiler gets its logger injected in a rather odd way,
via entrypoints (MediaWiki.php, ApiMain.php, and MaintenanceRunner)
as opposed to service wiring. This is kept as-is for now.
* In LBFactoryTest, in particular testInvalidSelectDBIndependent2,
there are cases that intentionally produce failures of which
the result is then observed. In CI we assert that dberror.log is
empty so instead of adding the missing logger fields to that
LBFactory instance, the only one set (replLogger) is removed.
The alternative is to set 'logger' now, which would naturally
cause CI failures due to unexpected entries coming through to
non-mocked error log.
Bug: T320873
Change-Id: I7ca996618e41b93f488cb5c4de82000bb36e0dd3
Remove 'insertSelectIsSafe' option, unused.
Remove 'topologicalPrimaryConnRef' option, no longer used as of two
months ago with I41a57247503 (8c9398f7f9).
Remove unneeded DatabaseSqlite::getTopologyBasedServerId
implementation which can inherit null instead of overriding with string
of "0". Only caller is SqlBagOStuff::makeTimestampedModificationToken
which can be used as MainStash DB, where its important that a given
server always has the same unique name within a set of db hosts that
may replicate to each other. By inheriting null as topology server ID,
it SqlBagOStuff will use IDatabase::getServerName instead. That in turn
uses the 'host' connection parameter, which defaults to null in
DatabaseFactory, and then falls back to the string "unknown" which is
as good as "0" for this purpose.
Bug: T299691
Change-Id: Iceb65c28cdd3c4a89b3c8b34c3f95d3285718ec0
We also bring along Database::attributesFromType(), which relied on the
private ::getClass(). This requires us to inject DatabaseFactory through
the LBFactory/LoadBalancer hierarchy.
Database::factory() is now soft deprecated. All callers outside of
includes/installer/ still need migration.
Bug: T299691
Bug: T315270
Change-Id: I7d057a9438f1b097554679975e4e9b2fc99e7c2b
Calling ->onlyMethods( [] ) with an empty array does have an effect.
By default, all methods are mocked, which means the original code is
not called. Calling ->onlyMethods( [] ) turns this around. No methods
are mocked but all call the original code.
This is almost the same as ->enableProxyingToOriginalMethods(). The
difference is that ->enableProxyingToOriginalMethods() also requires
the original constructor to be called, but ->onlyMethods( [] ) does
not.
We can get rid of this confusing setup in tests that don't need it.
All tests in this patch that succeed with a simple ->createMock()
just demonstrated that they don't need it.
Change-Id: I341323a1ca793c039498f80b7f073c124b6b6ae0
We really shouldn't do regex matching on SQL we produced, we are better
then that but until we refactor the code to a better shape, it can move
to the platform.
Bug: T307616
Change-Id: Ie2c84f208dfbed036b14c0a0669e004cc84e0f4b
Add Database::queryMulti(), which will execute an array of
queries as a batch with minimal roundtrips.
SQLite fallbacks to looping through each statement and
invoking doQuery().
Add QueryStatus class to reduce complexity in Database.
Rewrite doQuery() as doSingleStatementQuery().
Change-Id: I3d51083e36ab06fcc1d94558e51b38e106f71bb9
This would simplify the code for its users a lot.
Bug: T255493
Depends-On: I6ab4440a13f4682dd3a6e9cfc6c629222fbeab8a
Change-Id: I6e7544763bde56fc1e19de0358b71ba984a978ca
The first of many changes decoupling SQL building blocks from Database
class.
Bug: T299691
Depends-On: I5d1d5b9b875bced7bda234f45d6d22ed59db4871
Change-Id: I784e78361f5ee629d31c68629d669ee0ddddf929
Rename canRecoverFromDisconnect() in order to better describe
its function. Make it use the transaction ID and query walltime
as arguments and return an ERR_* class constant instead of a bool.
Avoid retries of slow queries that yield lost connection errors.
Track session state errors caused by the loss of named locks or
temp tables (e.g. during connection loss). Such errors will prevent
further queries except for rollback() and flushSession(), which must
be issued to resolve the error.
Add flushPrimarySessions() methods to LBFactory/LoadBalancer
and use it in places where session state loss is meant to be
safely aknowledged.
Change-Id: I60532f86e629c83b357d4832d1963eca17752944
This reverts commit ee3c65d541.
Reason for revert: Blocking the train, going to revert the whole chain.
Change-Id: I553115f310d93f98f7c6a2a77de28c4dda7762da
They are not used in anything deployed to production
These methods are:
- ::getTopologyRootMaster() since 1.37
- ::masterPosWait() since 1.37
- ::dataSeek() soft-deprecated since 1.37
- ::onTransactionIdle() soft-deprecated since 1.32
- ::getMasterPos() since 1.37
Bug: T296960
Change-Id: I1d196172b3f50e1200980c6325beccecac7db903
Make getServer() always return a string, as documented, even with new
Database::NEW_UNCONNECTED handles that have yet to call open(). If the
'host' parameter to __construct() is ''/null, getServer() now returns
'localhost' instead of null. This avoids problems like fatal errors in
calls to TransactionProfiler::recordConnection().
Use Database constants for "connectionParams" field keys for better
static analysis.
Also:
* Add Database::getServerName() method that returns "readable" server
names in the style of LoadBalancer::getServerName(). Note that the
"hostName" field is already passed in from LoadBalancer.
* Migrate most getServer() callers to getServerName() for easier
debugging and more readable logging.
* Also, normalize Database/LoadBalancer SPI logging context to use
"db_server" and reduce logging code duplication in LoadBalancer.
Bug: T277056
Change-Id: I00ed4049ebb45edab1ea07561c47e226a423ea3b
Ended up using
grep -Prl '\->setMethods\(' . | xargs sed -r -i 's/setMethods\(/onlyMethods\(/g'
special-casing setMethods( null ) -> onlyMethods( [] )
and then manual fix of failing test (from PS2 onwards).
Bug: T278010
Change-Id: I012dca7ae774bb430c1c44d50991ba0b633353f1