Commit graph

20 commits

Author SHA1 Message Date
jenkins-bot
b419ffba19 Merge "Database: Fix degenerate parenthesized joins" 2017-11-30 04:30:28 +00:00
Aaron Schulz
e0805d32e4 Disallow setting DBO_IGNORE in Database for sanity
In the off chance something called this, it would break all
sorts of code that expects that either query result functions
either succeed or throw an error.

Callers are not expected to have to check if the result of
a query is meaningful or false due to an error.

Change-Id: I0b4fe1403f55a399ffd40817ed12f857087d6f83
2017-11-29 21:31:03 +00:00
Brad Jorsch
2b2f9e229d Database: Fix degenerate parenthesized joins
The SQL standard supports parenthesized joins like

    a JOIN (b JOIN c ON (...)) ON (...)

But it doesn't support parenthesizing a single table name, i.e. a
one-table "join", like

    a JOIN (b) ON (...)

Detect the degenerate single-table case and omit the parentheses.

Bug: T181674
Change-Id: I82cacd80465092aa67ff19bdcfd6682001bf12ab
2017-11-29 15:42:27 -05:00
Brad Jorsch
4bd3e80e7a Database: Support parenthesized JOINs
SQL supports parentheses for grouping in the FROM clause.[1] This is
useful when you want to left-join against a join of other tables.

For example, say you have tables 'a', 'b', and 'c'. You want all rows
from 'a', along with rows from 'b' + 'c' only where both of those
exist.

 SELECT * FROM a LEFT JOIN b ON (a_b = b_id) JOIN c ON (b_c = c_id)

doesn't work, it'll only give you the rows where 'c' exists.

 SELECT * FROM a LEFT JOIN b ON (a_b = b_id) LEFT JOIN c ON (b_c = c_id)

doesn't work either, it'll give you rows from 'b' without a
corresponding row in 'c'. What you need to do is

 SELECT * FROM a LEFT JOIN (b JOIN c ON (b_c = c_id)) ON (a_b = b_id)

This patch implements this by extending the syntax for the $table
parameter to IDatabase::select(). When passing an array of tables, if a
value in the array is itself an array that is interpreted as a request
for a parenthesized join. To produce the example above, you'd do
something like

 $db->select(
     [ 'a', 'nest' => [ 'b', 'c' ] ],
     '*',
     [],
     __METHOD__,
     [],
     [
         'c' => [ 'JOIN', 'b_c = c_id ],
         'nest' => [ 'LEFT JOIN', 'a_b = b_id' ],
     ]
 );

[1]: In standards as far back as SQL-1992 (I couldn't find an earlier
 version), and it seems to be supported by at least MySQL 5.6, MariaDB
 10.1.28, PostgreSQL 9.3, PostgreSQL 10.0, Oracle 11g R2, SQLite 3.20.1,
 and MSSQL 2014 (from local testing and sqlfiddle.com).

Change-Id: I1e0a77381e06d885650a94f53847fb82f01c2694
2017-10-13 19:12:16 +00:00
Umherirrender
86463f3df6 build: Updating mediawiki/mediawiki-codesniffer to 0.12.0
Change-Id: Iefaae5043fa77d5d556c31079549dab8f61bd3ef
2017-09-10 21:11:37 +02:00
Timo Tijhof
9491b74d00 rdbms: Complete coverage for Database::selectSQLText()
Only missing cases where 'USE INDEX' and 'IGNORE INDEX'.
The test doesn't do much since the underlying methods are no-ops
by default, but at least it ensures there are no PHP errors from
these branches.

We can later re-use some of these test cases in tests specific
to one backend.

Change-Id: Id004a2ae41efaa7a367f964013e25d98ecc591ff
2017-07-27 21:30:07 -07:00
Aaron Schulz
f4e0c720a8 rdbms: Ensure onTransactionPreCommitOrIdle() callbacks don't lead transactions
If no writes started a transaction yet, the callback would run
but not commit (by design, joining the request round). Later
writes will then pile on top of it.

The point of this method is to avoid such cases, so this edge
case has been fixed.

Change-Id: I9b44b19261d679de4aff6e44a9cfeb4f684ce02e
2017-07-26 14:28:48 -07:00
Timo Tijhof
f357c5194c rdbms: Increase coverage for Database::selectSQLText()
* Add case for `$tables[0] == ' '`.
* Add case for `$tables == ''`.
* Add case for 'DISTINCT' option.
* Add case for 'FOR UPDATE' option.
* Add case for 'LOCK IN SHARE MODE' option.
* Add case for 'EXPLAIN' option.

Change-Id: I4a5f4754bc30d31ec35a085f39321fd358b6aa49
2017-07-24 19:49:17 -07:00
Timo Tijhof
b70a3bb821 rdbms: Add more @covers to DatabaseSQLTest
Many of the main methods here have, over the years, been split up
into several protected/private methods.

Change-Id: I1b8489b1c61c0294288442a0a0cd28c9fa77f82e
2017-07-24 19:44:06 -07:00
Timo Tijhof
7928eca292 rdbms: Complete DatabaseDomain code coverage
Add missing coverage for:
* DatabaseDomain::equals()
* DatabaseDomain::newUnspecified()
* DatabaseDomain::__toString()

Change-Id: I38863c5652ec395e7194bfb85b3485e3343a3b7e
2017-07-21 20:21:39 -07:00
Timo Tijhof
ddb7575e4e rdbms: Refactor DatabaseTest
* Move DatabaseTest and DatabaseSQLTest to libs,
  and remove MediaWikiTestCase dependency.

* Refactor DatabaseTest to be a test of the Database abstract class,
  not of whatever current DB backend is configured by LocalSettings.

  - Remove most switches/conditionals and other tests for specific
    database backends. Move those to individual test classes for
    those backends instead.
  - Some tests appear to have been integration tests for the PHP driver
    and/or the db backend itself. Moved to a new DatabaseIntegrationTest.
  - Now that only the abstract Database is invoked, the test runs a bit
    faster (no real connections/queries).

* Add missing @covers tags, and remove or fix broken ones
  (follows-up 26e52f0c49).

Change-Id: I9dc4a558e701d00e95789e7eb8e02926783b65ad
2017-07-20 18:23:37 -07:00
Timo Tijhof
b857284f71 rdbms: Move DatabaseMysqlBaseTest to libs tests
* Remove MediaWikiTestCase dependency.
* Add missing @covers tags.
* Add missing visibility/static declarations.

Change-Id: I2d81a9265016174e7b4ff810f140f7d031ce9f14
2017-07-20 17:15:25 -07:00
Aaron Schulz
e447f90896 Record TransactionProfiler violations beyond the first-by-type
Beyond giving a more complete picture, this can be used to adjust
the PostSend criteria to log master queries under the restInPeace()
entry point.

Bug: T166199
Change-Id: If5cf704ba10291d0eba63e66b388666fde3ca649
2017-06-27 16:44:33 -07:00
Timo Tijhof
447ce7e39a phpunit: Avoid use of deprecated getMock for PHPUnit 5 compat
The default will remain PHPUnit 4.x due to PHP 5.5 support.

But, we should allow developers to run tests with newer PHPUnit
versions which are noticably faster (especially for code coverage
reports).

* <https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-5.4.0>
  PHPUnit 5 deprecates the getMock() shortcut for getMockBuilder()->getMock().
  It instead introduces the shortcut createMock() which has better defaults
  than getMockBuilder(). For example, it sets 'disableArgumentCloning' and
  other things by default.

  Going forward, code should either use getMockBuilder directly and configure
  it using the setter methods (instead of the confusing variadic arguments
  of getMock) or simply use the new minimalistic createMock method. This patch
  backports the createMock method to MediaWikiTestCase so that we can start
  using it.

Change-Id: I091c0289b21d2b1c876adba89529dc3e72b99af2
2017-04-06 00:44:32 +00:00
Aaron Schulz
64df456b39 Move remaining LoadBalancer classes to Rdbms
The old names are left as aliases.

Change-Id: I52a327f2463a2ba7437324047b5b00d28cd1d758
2017-02-23 20:38:31 -08:00
Aaron Schulz
38b31bc8db Move DatabaseDomain to Rdbms namespace
Change-Id: Ifb06e792a36b5123ec3596933d0d394711ee5d08
2017-02-07 13:21:40 -08:00
addshore
05ab20fcc6 Remove Atomic methods from ConnectionManagers
Change-Id: I697f63f45975b13af52bc22fced6e4d07e35115f
Depends-On: I4341a1b4ff6a67e4c1770faae38e9b126f1bf0bf
2016-12-02 04:50:29 +00:00
addshore
a4bd573142 Fix SessionConsistentConnectionManagerTest class and file name
Change-Id: If60f081946b8f3bb564f2bb17fd1261af0cb7e3a
2016-12-01 00:15:57 +00:00
addshore
c3c3cf9696 Add DB ConnectionManagers
This moves and refactors the ConsistentReadConnectionManager
from Wikibase into the core rdbms lib.
The refactoring also creates a generic ConnectionManager.

This relates to Iff20a22f9f2bc7ceefd6defc0ed9a494a6fe62c0
which introduced a DB factory / connection manager in
an extension revealing the need for this in multiple places.

Change-Id: I0c58e15aed5bed88323d18cb95e5008f8d3381c5
2016-11-30 11:43:22 +00:00
Aaron Schulz
847b91bf1f Make database classes handle hyphens in $wgDBname
* Add DatabaseDomain class to handle passing domains around.
It also can be cast to and from strings, which are of the same
format as wfWikiId() except with hyphens escaped.
* Make IDatabase::getDomainID() use these IDs so they can be
passed into LoadBalancer::getConnection() and friends without
breaking on sites with a hyphen in the DB name.
* Add more LBFactory unit tests for domains.

Bug: T145840
Change-Id: Icfed62b251af8cef706a899197c3ccdb730ef4d1
2016-09-17 15:29:21 -07:00