Commit graph

133 commits

Author SHA1 Message Date
jenkins-bot
6695ce29a0 Merge "rdbms: refactored code into separate Database::getClass method" 2018-03-01 21:49:46 +00:00
Aaron Schulz
ee198b3339 rdbms: refactored code into separate Database::getClass method
Change-Id: Ic09ce2ea541d04f3cb3bc80a4a59c8b525ed8c53
2018-03-01 20:58:42 +00:00
Brad Jorsch
99b65649c0 rdbms: allow callers to hint that native insertSelect() is safe
An INSERT SELECT in MySQL/MariaDB is unsafe for replication if a column
is getting values from auto-increment, statement-based replication is in
use, and the default innodb_autoinc_lock_mode is set.

I9173f655 added checks to force non-native insertSelect for the
statement-based replication and innodb_autoinc_lock_mode != 2 case, but
determining whether a column is getting values from auto-increment is
too hard to do automatically there.

Instead, let's add a flag to let the caller hint that the query isn't
getting any auto-increment values. And use it in MysqlUpdater when
appropriate.

Bug: T160993
Change-Id: If70450a64aa3bcbf763c62838bb21306d124ae3d
2018-02-28 13:58:37 -05:00
Brad Jorsch
aefb143a8e Database: Add batching to non-native insertSelect()
It would be easy for a call to nonNativeInsertSelect() to generate an
INSERT that's too big for the database to actually process. Add batching
to try to avoid that.

Bug: T160993
Change-Id: I1de994208d95926f0d75c0d7cab7b5fe1dd565c3
2018-02-28 13:58:37 -05:00
Aaron Schulz
a9af460c3d rdbms: make sure non-native replace() uses one transaction
This is similar to what upsert() already does

Change-Id: Ide83eefe0d937fb2cdc20aa3c7dc9654c4d34beb
2018-02-20 19:21:38 -08:00
Aaron Schulz
c9ad7037ce rdbms: do not bother making DBO_TRX transactions in IDatabase::lock()
Named locks are session-level constructs and this transaction agnostic.
Also make lockIsFree() a bit more consistent when the thread has the
lock itself.

Change-Id: Ief51196161bbc50c798740f3c738fd0e39880508
2018-02-15 16:32:35 -08:00
jenkins-bot
3ff078137a Merge "rdbms: remove "m" prefix from Database fields" 2018-02-16 00:15:04 +00:00
Aaron Schulz
ec550d4823 rdbms: remove "m" prefix from Database fields
Done using the PhpStorm refactor->rename tool.

Also move "defaultBigSelects" declaration to DatabaseMysqlBase
as no other classes uses that.

Change-Id: I424a2d9815de3a5d4cca2522f3db23a5efe6b592
2018-02-15 23:29:34 +00:00
Aaron Schulz
4c90502371 rdbms: remove leading table name space hack in Database
This was added in r19879 (3de6fd8c8) with no provided use case.
There also appears to be nothing exploiting this.

Change-Id: I1641d4ed16d612ab6f08ee1eeca1580af73888bf
2018-02-15 22:53:50 +00:00
Reedy
39f0f919c5 Update suppressWarning()/restoreWarning() calls
Bug: T182273
Change-Id: I9e1b628fe5949ca54258424c2e45b2fb6d491d0f
2018-02-10 08:50:12 +00:00
Aaron Schulz
6237fd11b6 rdbms: make affectedRows() work more consistently
* Update replace()/upsert() to combine the affected row
  count for the non-native case
* Also make replace() atomic in the non-native case,
  similar to how upsert() already works

Change-Id: I6c9bcba54eca6bcf4a93a9b230aaedf7f36aa877
2018-01-30 20:02:07 -08:00
Aaron Schulz
a3f51001c0 rdbms: clean up non-native Database::replace() code
* Make sure all unique keys specified have all their values
  provided to avoid large bogus DELETEs. Do not ignore them
  in such cases either, as that would cause inconsistencies
  between the native and non-native case. Use an exception.
* Make ChangeTags caller clearer that the list of indexes
  is not a list of fields for a single index. Also, avoid
  mentioning indexes for values not defined in the new
  records, as this causes errors or inconsistencies with
  the native vs non-native case.
* This also fixes the "Undefined index: ts_log_id" error
  when running unit tests on postgres.

Change-Id: I30263df22066bd6d4836202b1bcad5d1aa1e7383
2018-01-30 03:19:28 +00:00
Timo Tijhof
76e8d97625 rdbms: Simplify Database::factory()
Follows-up 0ff2b7a776 (T120333) which removed support for the
deprecated php 'mysql' extension.

It surprised me that the 'DatabaseMysql' entry could safely be removed
from $classAliases. This was because the key is not direct input,
but based on $canonicalDBTypes, which maps mysql to mysqli.

Take this further by removing the indirection between type, driver
and class name.

* Map built-in db types directly to their class and driver.
* Change fallback to assign $class directly from $dbType, without
  indirection of a $driver variable.
* Remove unused $classAliases.

Change-Id: I1200b07f66f23624410d848b6f382cb2dafa5c59
2018-01-25 17:35:55 +00:00
Seb35
0ff2b7a776 Remove support for PHP extension 'mysql' (not mysqli!)
This PHP extension was deprecated in PHP 5.5 and removed in PHP 7.0.
The newer MySQL driver 'mysqli' is the default driver since MediaWiki
1.22 and 'mysql' was deprecated in MediaWiki 1.30.

Bug: T120333
Change-Id: Icff7a63ab47ae1483de87ba6486945974699362b
2018-01-17 10:48:47 -08:00
jenkins-bot
bdf062a8e9 Merge "Treat phpdbg as run from the command line when checking PHP_SAPI" 2018-01-08 23:03:41 +00:00
daniel
047151c692 Introduce DB schema overrides for unit tests.
This introduces MediaWikiTestCase::getSchemaOverrides,  which can be overwritten
to return information about which tables are going to be altered, and which SQL
files should be used to set up the target schema. This allows tests for a class
that interacts with the database can have a subclass for each supported database
schema.

NOTE: this has only been tested with MySQL.

Bug: T180705
Change-Id: I7a4071072d802a82ecf7d16fbf8882ff8c79287f
2018-01-05 16:23:55 +00:00
addshore
c8a852fd34 Set a default delimiter in Database::sourceStream
Discovered while debugging I7a4071072d802a82ecf7d16fbf8882ff8c79287f

DatabaseIntegration test alters the delimiter for the database instance
and it never gets set back.
Simply set the delimiter back to a default value at the start of
sourceSteam (for each new file pointer) which could have a new
delimiter.

Change-Id: Ib829b1c8d87271526fa6826910d40c304c778b32
2018-01-05 16:23:43 +00:00
Kunal Mehta
251a0b97e5 Treat phpdbg as run from the command line when checking PHP_SAPI
phpdbg is a gdb-style debugger for PHP that is run from the command
line. However, it has a different PHP_SAPI value, so it was impossible
to run maintenance scripts with it (until now).

To avoid having to check both PHP_SAPI values in a bunch of places,
introduce wfIsCLI() to easily check whether running from the
command-line or not.

We're (CI team) interested in generating code coverage with phpdbg
instead of xdebug, hence this patch.

Bug: T184043
Change-Id: Id1f994ca146d7858cd8bb6ab6cdbb7718ff524fb
2018-01-03 23:00:37 -08:00
Aaron Schulz
60e8a35c2d Simplify logic to prevent writes on replica DB connections
This reverts most of 36f4daf32c.

Change-Id: Ie8205749b14be186e80296b168c32310c10ce875
2017-12-20 21:45:07 +00:00
Roan Kattouw
4ddb207a32 Follow-up 36f4daf32c: allow no-write database connections to use transactions
After 36f4daf32c was merged, Aaron pointed out on Gerrit that:

    Transaction can be used on replicas for REPEATABLE-READ mode, so
    queries in that transaction see the same version of the DB. Those
    do not involve writes and things would probably break sometimes
    without it (like reads following foreign keys and reference in
    separate queries).

So allow no-write connections to call begin() and commit(), and only
throw an exception when a write query is attempted.

Bug: T183265
Change-Id: I138677a714df13ead08061c3e9ef794c3befbe9d
2017-12-20 15:25:35 +01:00
daniel
36f4daf32c Prevent write operations to database replicas.
Bug: T183265
Change-Id: I8e17644d1b447416adee18e42cf0122b52a80b22
2017-12-19 17:11:08 +01:00
jenkins-bot
b063a5bce2 Merge "Add missing @throw tags to IDatabase/Database" 2017-11-30 22:44:38 +00:00
Aaron Schulz
8503692309 Add missing @throw tags to IDatabase/Database
Change-Id: I235c5beacce38e9121fb1db94ce410d010356fcf
2017-11-30 22:17:16 +00:00
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
Chad Horohoe
720b08b291 Improve connection logging a little more
Don't include the trace in the actual message, that keeps us from
grouping these messages by type. Instead inject the trace as an
extra parameter we'll pick up in logstash

Change-Id: I48184c1af2560827ef50baff4fc0443f00697504
2017-11-01 21:09:47 +00:00
Chad Horohoe
0f32266543 rdbms: Group disconnect/reconnect errors by DB server name
Still allow varying on stacktrace, as those are interesting

Change-Id: I62bc3f68fcbe43532dce849d515a5e0620fba6f2
2017-10-27 20:09:45 +00: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
Aaron Schulz
95e9115858 Make Database::rollback() also suppress callback errors
This is consistent with query error suppression, let the
listener callbacks have a chance to run. This also makes
LoadBalancer::rollbackMasterChanges move on to the other
connections.

Change-Id: Ic8b9dd4b868bfe69b04fb20f7be5fce11d864fc4
2017-10-04 11:24:14 -07:00
jenkins-bot
d75a576e26 Merge "build: Updating mediawiki/mediawiki-codesniffer to 13.0.0" 2017-09-30 23:44:57 +00:00
Brad Jorsch
d98a666d38 Fix insertSelect() with IGNORE in PostgreSQL
I0e6a9e6d overlooked the special handling PG needs (prior to 9.5 anyway)
to properly emulate MySQL's IGNORE option when delegating to the parent
implementation.

For now, then, don't use the native implementation in PG when IGNORE is
specified. Instead, fall back to the non-native implementation that does
a select() then an insert() where PG can handle the IGNORE properly.

In the future we might use the ON CONFLICT DO NOTHING clause added in PG
9.5 to be able to do native insertSelect() with IGNORE (and to better
handle multi-row insert() with IGNORE, and we could use the related ON
CONFLICT DO UPDATE to implement upsert()). All that is left for a future
patch.

Change-Id: I7987d59580543de03d5c6a5ed7fa3ce551ac12f3
2017-09-26 01:32:27 +00:00
Umherirrender
bd741b83bc build: Updating mediawiki/mediawiki-codesniffer to 13.0.0
Change-Id: Ia24dbf015f2b4781683ca980a460d0ac3e85674e
2017-09-25 17:31:56 +02:00
Matthew Flaschen
3638695419 Detect query timeouts and throw a specific exception
Throw DBQueryTimeoutError if a database query error is detected
to be a timeout.

Only DatabaseMysqlBase has been updated here.

This is a subclass of DBQueryError, so existing catch'es will work.

Bug: T175775
Change-Id: I4749dc33ad530d9b22504f02106b1ca49e8eb167
2017-09-20 08:47:09 +00:00
Umherirrender
86463f3df6 build: Updating mediawiki/mediawiki-codesniffer to 0.12.0
Change-Id: Iefaae5043fa77d5d556c31079549dab8f61bd3ef
2017-09-10 21:11:37 +02:00
Umherirrender
f739a8f368 Improve some parameter docs
Add missing @return and @param to function docs and fixed some @param

Change-Id: I810727961057cfdcc274428b239af5975c57468d
2017-09-10 20:32:31 +02:00
jenkins-bot
9404f8a589 Merge "Soft deprecation of DatabaseMysql" 2017-08-22 10:51:24 +00:00
Umherirrender
3f1a52805e Use short type bool/int in param documentation
Enable the phpcs sniffs for this and used phpcbf

Change-Id: Iaa36687154ddd2bf663b9dd519f5c99409d37925
2017-08-20 13:20:59 +02:00
Aaron Schulz
a619be8163 database: make close() sanity check mTrxPreCommitCallbacks
The other callback types are already checked too.

Change-Id: Ibdc82110c0a0e74bb07ed92ee667bdf0d9f69f90
2017-08-16 21:25:29 -07:00
Umherirrender
5544cef16b Add missing type to @param documentation
Change-Id: I6b2c9c7af9a281fe457099cc3a336a60a25e74aa
2017-08-11 20:37:35 +02:00
Umherirrender
ace44e2064 Use correct variable name in @param documentation
For some varargs a variable name is added with suffix ,... as seen for
many other varargs

Some @param are swapped, because there are in the wrong order

Enable Sniff MediaWiki.Commenting.FunctionComment.ParamNameNoMatch

Change-Id: I60fec6025bce824d5c67563ab7b65ad6cd628ad8
2017-08-11 19:27:19 +02:00
Seb35
7739276026 Soft deprecation of DatabaseMysql
This class is the driver for MySQL databases corresponding to the PHP
extension 'mysql'. This PHP extension was deprecated in PHP 5.5 and
removed in PHP 7.0. It was replaced by the PHP extension 'mysqli',
which is supported and the default MySQL driver since MediaWiki 1.22.

Bug: T120333
Change-Id: Id1478f73e348cdd1ad1f560b1d8ddefe56c52767
2017-08-05 20:38:16 +02: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
jenkins-bot
1abc89fc76 Merge "Add Database::unionConditionPermutations()" 2017-07-07 18:37:09 +00:00
Aaron Schulz
0352fe44f1 Avoid checking double-prefixed table names in mysql tableExists()
Change-Id: I9d91a5305227171d0776ffa443d4e538fbe1b15f
2017-06-27 18:41:32 +00:00
Aaron Schulz
0b51d17dbc Factor out new qualifiedTableComponents() Database method
Change-Id: Ib453a5a8e0cf8bb1b77e65eb6f9569819d4eb5b2
2017-06-20 16:29:56 -07:00
Brad Jorsch
a0ad0569bd Add Database::unionConditionPermutations()
Constructs a query for the union of permutations of a set of fields, for
use in situations where the database otherwise makes poor plans due to
inability to use indexes effectively (e.g. T149077 and T168010).

Change-Id: I20980dcada664486c09198b8c45896620bd83e81
2017-06-16 19:39:05 +00:00
Brad Jorsch
31cb62dd2d DB: Add join conditions to selectField, selectFieldValues, and insertSelect
selectField() and selectFieldValues() are trivial, they just need to
pass it through to select(). In fact, selectFieldValues() was already
doing it, just no one ever updated IDatabase.

insertSelect() is a little more work. nativeInsertSelect() was
originally written as largely a copy-paste of select() and has since
gotten well out of sync. Now that we have selectSQLText(), we should be
able to just use that. DatabasePostgres's implementation can wrap the
parent implementation instead of being another copy-paste, but
DatabaseOracle seems to still need to be special.

Change-Id: I0e6a9e6daa510639d3212641606047a5db96c500
2017-06-14 05:07:42 +00:00
Aaron Schulz
8f297550d2 Log when transactions affect many rows in TransactionProfiler
This augments the logging which detect single large write queries

Bug: T95501
Change-Id: I4eac35c56a472e5ba64270ea10c48bf33138417b
2017-05-26 18:46:49 +00:00
Kaldari
b2a2a50a66 Make sure all functions in Database.php are documented
Will add @inheritdoc in a follow-up commit for functions
documented in the parent classes.

Part of 2017 MediaWiki Documentation Day

Change-Id: I002a1f6451940ecbcacea7b3ca2fc6ad0f4eba47
2017-05-19 18:19:48 +02:00