Commit graph

108 commits

Author SHA1 Message Date
Aaron Schulz
9429bb8b83 rdbms: remove IDatabase::selectDB()
Change-Id: I0e5f9d82d487a1f74348942609625c58a7b1df32
2023-01-17 02:17:04 +01:00
Timo Tijhof
4ef0891994 rdbms: Consolidate logger channels into one
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
2023-01-03 22:46:38 +00:00
jenkins-bot
bb20303cb6 Merge "Fix whitespaces after comma" 2022-12-15 00:56:34 +00:00
Amir Sarabadani
9b078129d2 rdbms: Moving replication-related code to its own component
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
2022-12-15 00:37:02 +00:00
Umherirrender
fd516a98e1 Fix whitespaces after comma
Change-Id: Ide6de0a53661e6f650099d7b1f274a02699441df
2022-12-15 01:24:14 +01:00
Aaron Schulz
85eb9b3e66 rdbms: simplify getLagFromPtHeartbeat() in DatabaseMysqlBase
Avoid expensive SHOW query for sites that were explicitly configured
to use pt-heartbeat but configured without a row SELECT condition.

Reduce excessive code complexity for configuration edge cases.
Remove getLagDetectionMethod() and just use the field instead.

Change-Id: I0d8592fde65d8a143506c55dccd1972a148bd489
2022-11-01 21:33:05 -07:00
Tim Starling
8983047203 DatabaseSQLTest: remove unused variable
Change-Id: I3087387bb4038df08f0738a756b0608eff8e3133
2022-10-28 13:17:22 +11:00
Aaron Schulz
c1e1512698 rdbms: improve LoadBalancer connection pool reuse (ii)
Make DBConnRef enforce the DB domain selected during its lifetime
and allow more nested and successive use of the same connection handle
via DBConnRef. This can avoid extra connections in some cases where
getConnection()/getConnectionRef() is used.

Also:
* Reduce the number of connection pools arrays from six to two
* Merge getLocalConnection()/getForeignConnection() into one method
* Expand various related code comments

Since LoadBalancer::getReadOnlyReason() no longer user the local domain
but rather DOMAIN_ANY, it should not result in "USE" errors if the local
domain does not have a database on the server.

This version of the patch removes the unused reuseConnectionInternal()
method (the method was previously added back to the patch by mistake).

Bug: T226595
Change-Id: I62502f4de4f86a54f25be1699c4d1a1c1baee60b
2022-10-18 17:23:44 -07:00
Amir Sarabadani
fdc246801e rdbms: Introduce DatabaseFlagsHolder and move some internal logic there
Bug: T299691
Change-Id: If9da21bebf1b233da38ed198f35d3dcd51c356a5
2022-10-11 17:59:47 +02:00
Ladsgroup
4edae94817 Revert "rdbms: improve LoadBalancer connection pool reuse"
This reverts commit 76be4dca81.

Reason for revert: Caused T318904

Bug: T318904
Change-Id: I92f23205b4d62f69c0f27af40f972f104d1a7a7c
2022-09-29 12:12:14 +00:00
Aaron Schulz
76be4dca81 rdbms: improve LoadBalancer connection pool reuse
Make DBConnRef enforce the DB domain selected during its lifetime
and allow more nested and successive use of the same connection handle
via DBConnRef. This can avoid extra connections in some cases where
getConnection()/getConnectionRef() is used.

Also:
* Reduce the number of connection pools arrays from six to two
* Merge getLocalConnection()/getForeignConnection() into one method
* Expand various related code comments

Bug: T226595
Depends-On: If808cbab429d41e1f2289683533e4a781a4bdf5e
Change-Id: I540b08920997c57cad6445ddb09d8e663eaf4714
2022-09-23 10:53:58 +10:00
jenkins-bot
779b83705f Merge "Move unit tests for SQLPlatform to a separate file" 2022-09-13 10:12:52 +00:00
Bartosz Dziewoński
af60bf699c Move unit tests for SQLPlatform to a separate file
Change-Id: I91aec0898d2ae7b348c423f6f31b1596f7f42d91
2022-09-10 04:22:18 +02:00
Timo Tijhof
6f4db32e0c rdbms: Remove unused channelsMatch() from internal MySQLPrimaryPos
Remove it from the interface as well. The interface is marked stable
to implement for (theoretical) database extensions.

This is not a breaking change as any existing implementations of the
method may continue to exist, and continue to be uncalled by core.

The interface is not stable to type or call, and the built-in
implementation is internal/unexposed.

Change-Id: Iced3ab3dfca70dec2958eb9d750e7025b95b7de3
2022-09-07 22:08:04 +00:00
jenkins-bot
5a735e81c1 Merge "rdbms: Remove unused getLogName() from internal MySQLPrimaryPos" 2022-09-05 07:09:31 +00:00
Timo Tijhof
b1c07ad652 rdbms: Remove unused getLogName() from internal MySQLPrimaryPos
Also hoist up the `@covers` annotation for the test class overall,
and widen some of the more specific ones to make up for the fact
that this code has recently been refactored and thus is now part
of different classes.

Change-Id: I67d19502fd191042c902d8b48d8cbd3ff76473d6
2022-09-05 02:16:52 +02:00
Alexander Vorwerk
acb5c2f4e0 Update doctrine/dbal versions
Change-Id: I60b66ff86e4c624570ca0514c28a8b7a803cfcc7
2022-09-04 23:41:34 +00:00
jenkins-bot
2b6e081ff3 Merge "rdbms: log invalid INDEX clauses with multi-table selects" 2022-09-02 02:06:53 +00:00
jenkins-bot
c48a61b247 Merge "rdbms: Move Database::factory() to DatabaseFactory service" 2022-09-02 01:51:38 +00:00
Aaron Schulz
bbd4ae53c2 rdbms: log invalid INDEX clauses with multi-table selects
Previously, invalid SQL would be sent to the database server,
resulting in a SQL syntax error. Log a warning instead.

Move USE/IGNORE INDEX handling out of makeSelectOptions().

Inject the Database error logger callback into SqlPlatform.

Bug: T315195
Change-Id: Ie33faddcd766926f083e4421c6d0508a16b58f71
2022-09-02 01:46:13 +00:00
Aaron Schulz
8c9398f7f9 rdbms: avoid DB_PRIMARY queries in getLagFromPtHeartbeat()
The default mode (using server_ids) will now use SHOW REPLICA STATUS
data instead of connected to the master. If the source server is not
the root source server (e.g. the primary), then lagDetectionOptions
should be configured to either specify the primary server ID or use
custom channel columns (like WMF sites).

Remove getMasterServerInfo() and getPrimaryServerInfo() method.

Clean up some related comments and field names.

Bug: T299691
Change-Id: I41a57247503a69367cd73d365f8aa8af04398e46
2022-08-31 23:45:47 +00:00
Kunal Mehta
499a1fe497 rdbms: Move Database::factory() to DatabaseFactory service
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
2022-08-31 10:53:50 +10:00
jenkins-bot
a75de5ee61 Merge "Remove confusing ->onlyMethods( [] ) with empty array from tests" 2022-08-14 23:45:26 +00:00
Amir Sarabadani
8614e30638 rdbms: Stop accepting live connection in DBConnRef constructor
This just makes the class overly complex and defies the whole point of
having this class in the first place (=delaying getting db connections).

It makes it harder to read and understand and specially polymorphic
arguments are quite confusing.

It also would break the reloading db on the fly (I6c3ffde62f6e), users
of DBConnectionRef should not know about the underlying connection, this
class is trying encpsulate that and accepting connection in constructor
breaks this encapsulation.

Bug: T298485
Depends-On: I951ab99ae766788dbae8bd338aaae114a388b21f
Change-Id: I743c0565504c65c4dedf29f2a36d4c386601fda0
2022-08-08 18:11:31 +02:00
Thiemo Kreuz
02971ace54 Remove confusing ->onlyMethods( [] ) with empty array from tests
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
2022-08-08 15:49:59 +02:00
Amir Sarabadani
2eb242f40a rdbms: Drastically simplify Sqlite db tests
Now that we moved considerable chunk of DatabaseSqlite to
SqlitePlatform, it's easier to mock and test without actually needing a
live db connection.

This allows moving a lot of tests from integration to unit tests making
them much faster.

Change-Id: I8ce7c470abed5144ba456a000c733e5d739c5c4e
2022-08-08 14:38:20 +02:00
daniel
5b0b54599b Allow DB config to be reloaded on the fly
This introduces $wgLBFactoryConf['configCallback'] which can be set to a
function that returns updates to be applied to $wgLBFactoryConf. The new
method LBFactory::autoreConfigure() can be called to check the callabck
and, if the config changed, reconfigure all existing LoadBalancers.

Reconfiguring the LoadBalancers causes all open connections to be
invalidated; however, any DBConnRef instances will remain valid and will
acquire a fresh connection from the LoadBalancer automatically when
appropriate.

As a proof of concept, this patch adds support for config reloding
into WikiExporter.

Bug: T298485
Change-Id: I6c3ffde62f6e038730736abe980befd90ec43e1a
2022-08-05 17:32:12 +02:00
Lucas Werkmeister
ca37410ace rdbms: Fix capitalization of SQLPlatform references
Change-Id: Ie090f73db9ddf5ea101ed1f0287cc61636817f92
2022-07-29 16:44:31 +02:00
Amir Sarabadani
ac3335d1ac rdbms: Migrate several more Database::do* to SqlPlatform
Bug: T307616
Change-Id: Ie275f487e61736d4a02725256783f80ef38c1cb3
2022-07-29 15:28:23 +02:00
Amir Sarabadani
4e39f5535a rdbms: Migrate SQL analysis code pieces to SQLPlatform
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
2022-07-28 20:22:00 +02:00
Amir Sarabadani
a01a85d58c rdbms: Migrate delete and update sql building to SQLPlatform
Part of breaking down the monster class, Database

Bug: T307616
Change-Id: I89ac3e4ce4b82015eba8f4ccd40cb00938042274
2022-07-22 17:05:13 +02:00
jenkins-bot
b07027f575 Merge "Replace trivial usa of mock builder with createMock() shortcut" 2022-07-19 11:41:12 +00:00
Thiemo Kreuz
58ceac8fc0 Tests: Replace trivial willReturnCallback with direct willReturn
Less setup code, easier to read.

I also found something that looks like it should have been an
assertInstanceOf(), so I made it one.

Change-Id: I7ba9b580c270a103feb0f55b910157f93197fa43
2022-07-18 11:40:09 +02:00
Thiemo Kreuz
61ae7504df Replace trivial usa of mock builder with createMock() shortcut
createMock() does the same, but is much easier to read.

A small difference is that some of the replacements made in this
patch didn't use disableOriginalConstructor() before. In case this
was relevant we should see the respective test fail. If not we can
save some CPU cycles and skip these constructors.

Change-Id: Ib98fb06e0fe753b7a53cb087a47e1159515a8ad5
2022-07-15 16:43:48 +00:00
Aaron Schulz
fdfe022ccf rdbms: allow merging IDatabase::upsert() rows with current ones
Rewrite the queries so that the column values of conflicted
proposed rows can be referenced in the SET expressions used to
update existing rows. Add IDatabase::buildExcludedValue() to
derive such references.

Make upsert() only use the first key in the unique key list as
the one to use for finding existing rows and merging them. Any
other key will just cause duplicate key errors/rollback upon
row collisions. For example, suppose a `user` table has unique
keys on both UUID and email address. It would be undesirable
for upsert() to clobber an existing `user` row just because
someone tried to make an account with the same email address.

Using upsert() makes sense when the following hold:
- The table has a single unique key that conveys "identity".
  AUTOINCREMENT and UUID columns are particularly good here.
  If row A existed at time t1, row B existed at time t2, and
  both rows have matching values for this "identity key", then
  they are conceptually the "same" row. It does not matter if
  other columns differ or if the row was deleted and recreated.
- Any other unique keys are just business constraints unrelated
  to the concept of identity. For example, an `accounts` table
  might have ID, name, and email address each as unique keys.
- For each proposed row, upsert() looks for an existing row
  that conflicts along the identity key. If there is one, then
  it gets updated, otherwise, the proposed row is inserted.
  Other unique key collisions result in operation rollback.

Bug: T113916
Change-Id: Iddd9f120ee966c76b3acb35e62ea14ec4c6f925d
2022-06-09 11:45:46 +10:00
Aaron Schulz
da9e4b52a5 rdbms: Add multi-statement query support to Database
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
2022-06-09 11:45:38 +10:00
Amir Sarabadani
dd9b44b167 rdbms: Move selectSQLText to SQLPlatform
Bug: T307616
Change-Id: I5218bca6633ad4d2704267e0c40926ca171fb1f7
2022-06-02 21:35:04 +02:00
Umherirrender
b0398654c5 tests: Do not use class alias in @covers
Also fix case for the XMLTypeCheck test

Change-Id: I809510c8085a36e20fd0eefb5e77d2671b3148f2
2022-05-28 00:37:43 +02:00
Umherirrender
770f905900 tests: Use namespaced IDatabase class
Change-Id: I7171ff26faee00d9eaabc33c2f3d91049ea0b40d
2022-05-28 00:09:55 +02:00
Amir Sarabadani
80ddbf1032 rdbms: Move handling index and table aliases to SQLPlatform
Next step in moving selectSQLText() to SQLPlatform

Bug: T307616
Change-Id: Idd136c17a04e12b1fe91c81ce90677ec42ca0882
2022-05-23 12:08:08 +02:00
Amir Sarabadani
d83cbce70e rdbms: Move four more functions from Database to SQLPlatform
Bug: T307616
Change-Id: I0ff6318bcbca79830f013a16597d04d1e97ccf6d
2022-05-20 17:06:49 +02:00
jenkins-bot
434c333d9b Merge "rdbms: Prepare for moving Database::selectSQLText to SQLPlatform" 2022-05-17 02:20:37 +00:00
Amir Sarabadani
8c833750d0 rdbms: Prepare for moving Database::selectSQLText to SQLPlatform
This moves a lot of methods used in selectSQLText method so the move
would be easier. I tried moving it but the patch basically exploded.

Bug: T307616
Change-Id: Ib8c68b4506055b63c769926d6d7cfd1069d951f4
2022-05-12 07:59:22 +02:00
Amir Sarabadani
a294e715a4 rdbms: Replace getConnection with getLazyConnectionRef
This would simplify the code for its users a lot.

Bug: T255493
Depends-On: I6ab4440a13f4682dd3a6e9cfc6c629222fbeab8a
Change-Id: I6e7544763bde56fc1e19de0358b71ba984a978ca
2022-05-12 07:43:03 +02:00
Amir Sarabadani
332b530e8a rdbms: Move out more functions from Database to SQLPlatform
Bug: T307616
Depends-On: Id1f477f5ca4c837cf50ee5ef450873735b732a42
Change-Id: I63308df985b9d596110718450997565de2b06aca
2022-05-11 16:51:53 +00:00
Amir Sarabadani
ca5b162c23 rdbms: Start using SQLPlatform and move more methods there
The first of many changes decoupling SQL building blocks from Database
class.

Bug: T299691
Depends-On: I5d1d5b9b875bced7bda234f45d6d22ed59db4871
Change-Id: I784e78361f5ee629d31c68629d669ee0ddddf929
2022-05-04 18:34:13 +00:00
Tim Starling
05701ffc40 rdbms: Remove instance ownership concept
Instance ownership is supposed to protect LoadBalancer and Database
against unauthorized calls to internal methods other than by the owning
LoadBalancer/LBFactory. This seems like unnecessary complexity. It was
introduced for T231443 and T217819, but the link was speculative and in
the end it didn't help to fix or isolate those bugs. Since then it has
caused a production error (T303885) and an intermittent CI failure
(T292239).

Instead, split the ILoadBalancer interface, introducing
ILoadBalancerForOwner, which contains the methods which are only safe
to call by LBFactory or by the caller of LBFactory::newMainLB(). This
allows phan to statically detect inappropriate calls to internal
methods.

Ownership was used for convenience for two things unrelated to its
original purpose:

* Suppressing calls to ScopedCallback::newScopedIgnoreUserAbort() when
  the caller has already called it. But nested calls are apparently
  harmless, so I just called it unconditionally.
* Suppressing exceptions from Database::close(). I extended the
  behaviour for owned instances to apply to all instances, so even
  unowned instances will no longer throw on close.

CodeSearch suggests nothing in extensions is calling these methods with
an owner parameter. One extension (Wikibase) overrides a method with an
owner parameter in a test mock class and so needs to be simultaneously
updated.

Depends-On: Ib03aba9d8f5f05b875a321d00b14483633a636a8
Change-Id: I27ba4973d24d759c88b3868c95e7db875801ca0c
2022-04-26 11:48:46 +10:00
Amir Sarabadani
236a0941c0 rdmbs: Start of SQLPlatform to split out of Database
This is the first step to split parts of Database that doesn't require a
connection and are used for query parts.

Bug: T299691
Change-Id: I140aa4328865994499926f898233867ce383908c
2022-04-24 16:07:44 +00:00
Aaron Schulz
db36853718 rdbms: make automatic connection recovery more robust
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
2022-04-14 11:09:31 +10:00
Aaron Schulz
e0a53cba15 rdbms: rename wasKnownStatementRollbackError() to isKnownStatementRollbackError()
Pass the error number as an argument, similar to isConnectionError()

Fix related mysql documentation links

Change-Id: Id32ef2fd27de65376960de3f5138ffdf7654ff71
2022-03-22 22:59:09 +00:00