Commit graph

71 commits

Author SHA1 Message Date
Fomafix
3ee1560232 No yoda conditions
Replace
  if ( 42 === $foo )
by
  if ( $foo === 42 )

Change-Id: Ice320ef1ae64a59ed035c20134326b35d454f943
2018-11-21 17:54:39 +01:00
Aaron Schulz
633eb437a3 rdbms: clean up return values of IDatabase write methods
Also improved the atomicity and affected row count logic for
insert/replace with sqlite.

Also remove unused "fileHandle" code from insert().

Change-Id: If7b9148fd44f3a958899885753c7c86ba66bf193
2018-10-30 03:34:52 +00:00
Aaron Schulz
fe0af6cad5 rdbms: Database::selectDB() update the domain and handle failure better
LoadBalancer uses Database::getDomainId() for deciding which keys to use
in the foreign connection handle arrays. This method should reflect any
changes made to the DB selection.

If the query fails, then do not change domain field. This is the sort of
approach that LoadBalancer is expects in openForeignConnection(). Also,
throw an exception when selectDB() fails.

The db/schema/prefix fields of Database no longer exist in favor of just
using the newer currentDomain field.

Also:
* Add IDatabase::selectDomain() method and made selectDB() wrap it.
* Extract the DB name from sqlite files if not explicitly provided.
* Fix inconsistent open() return values from Database subclasses.
* Make a relationSchemaQualifier() method to handle the concern of
  omitting schema names in queries. The means that getDomainId() can
  still return the right value, rather than confusingly omitt the schema.
* Make RevisionStore::checkDatabaseWikiId() account for the domain schema.
  Unlike d2a4d614fc, this does not incorrectly assume the storage is
  always for the current wiki domain. Also, LBFactorySingle sets the local
  domain so it is defined even in install.php.
* Make RevisionStoreDbTestBase actually set the LoadBalancer local domain.
* Make RevisionTest::testLoadFromTitle() account for the domain schema.

Bug: T193565
Change-Id: I6e51cd54c6da78830b38906b8c46789c79498ab5
2018-10-10 12:03:30 -07:00
Brian Wolff
528042054f Fix some phan-taint-check false positives
Change-Id: Ic5ccbb3f97722476bee7188b83b80cdc652d2a64
2018-09-21 17:27:44 -07:00
Aaron Schulz
41a37d14fa rdbms: make Database::open() protected
This is not called externally and there is little reason for that to
change. The current caller pattern is to use factory(), possibly with
initConnection() afterwards, or to use a LoadBalancer to begin with.

Change-Id: Ib1fdd5c960f1ed877fcd17bcb99b999d5d894716
2018-08-21 18:34:51 -07:00
Fomafix
0a0d5cb7f7 Fix typos
Bug: T201491
Change-Id: I25a27d11faabe2f5fa02950c7a4fb58b13fb3662
2018-08-14 09:52:19 +00:00
Aaron Schulz
f3a197e49b rdbms: add "maxReadRows" limit to TransactionProfiler
Change-Id: I008fc1857c7aa43d93f43361803d5e52c4ddf089
2018-08-13 13:30:08 -07:00
Bartosz Dziewoński
485f66f174 Use PHP 7 '??' operator instead of '?:' with 'isset()' where convenient
Find: /isset\(\s*([^()]+?)\s*\)\s*\?\s*\1\s*:\s*/
Replace with: '\1 ?? '

(Everywhere except includes/PHPVersionCheck.php)
(Then, manually fix some line length and indentation issues)

Then manually reviewed the replacements for cases where confusing
operator precedence would result in incorrect results
(fixing those in I478db046a1cc162c6767003ce45c9b56270f3372).

Change-Id: I33b421c8cb11cdd4ce896488c9ff5313f03a38cf
2018-05-30 18:06:13 -07:00
Reedy
765370a6db Add @deprecated tags to various class_alias calls
Bug: T195576
Change-Id: I10cd8415891bfe4a278eee06c9cfe905b3e036dc
2018-05-29 13:10:20 -07:00
Brad Jorsch
6318430fc8 PostgreSQL: Set owners for sequences
PostgreSQL allows setting an "owner" column for a sequence, so if that
column is dropped then the sequence will be dropped too. We should
certainly take advantage of that when creating duplicate tables for unit
testing (particularly when $temporary is false), and we may as well do
it for our permanent tables too.

Change-Id: I4822ac33298e3f3ef59f4372a24aa0866a6e66ae
2018-04-09 12:05:29 -04:00
Brad Jorsch
501b1fb7df tests: Reset Postgres sequences when cloning and truncating
This improves the repeatability of the unit tests by making the ID
values generated depend less on what previous tests might have done.

It also prevents tests from using up sequence numbers for the live DB's
tables.

Change-Id: Iaa8ae1e5cef4b9099bd1b4b8fc806f5af372a7ff
2018-04-05 23:57:24 +00:00
Brad Jorsch
43d1f706be rdbms: Allow PostgreSQL schema-check functions to find temporary tables
PostgreSQL puts temporary tables and such in a hidden, per-connection
"schema" that's checked for unqualified table accesses before the normal
search_path. We should check that in all the schema-checking functions.

Change-Id: I1194ac31f31133b177f624138afee19d00e454b9
2018-04-05 22:54:01 +00:00
Brad Jorsch
cc0473766a rdbms: Remove support for PostgreSQL < 9.2, and improve INSERT IGNORE for 9.5
MediaWiki doesn't support PostgreSQL < 9.2, so drop the support for
older versions.

At the same time, since we're messing with the DatabasePostgres::insert()
code anyway, let's start using ON CONFLICT DO NOTHING for PG >= 9.5.

And since we're doing that, let's do the same for
DatabasePostgres::nativeInsertSelect().

Change-Id: I7bf13c3272917ebafeaff11eb116714a099afdf3
2018-04-05 20:52:46 +00:00
Aaron Schulz
3975e04cf4 rdbms: make Database query error handling more strict
Handle all errors in query() that might have caused rollback by
putting the Database handle into an error state that can only be
resolved by cancelAtomic() or rollback(). Other queries will be
rejected until then.

This results in more immediate exceptions in some cases where
atomic section mismatch errors would have been thrown, such as a
an error bubbling up from a child atomic section. Most cases were
a try/catch block assumes that only the statement was rolled back
now result in an error and rollback.

Callers using try/catch to handle key conflicts should instead use
SELECT FOR UPDATE to find conflicts beforehand, or use IGNORE, or
the upsert()/replace() methods. The try/catch pattern is unsafe and
no longer allowed, except for some common errors known to just
rollback the statement. Even then, such statements can come from
child atomic sections, so committing would be unsafe. Luckily, in
such cases, there will be a mismatch detected on endAtomic() or a
dangling section detected in close(), resulting in rollback.

Remove caching from DatabaseMyslBase::getServerVariableSettings
in case some SET query changes the values.

Bug: T189999
Change-Id: I532bc5201681a915d0c8aa7a3b1c143b040b142e
2018-04-04 21:26:11 -07:00
Aaron Schulz
d8732ad042 rdbms: clean up session/transaction loss logic in Database
* Refactor the code to be less cluttered, moving some logic
  to reconnect(), which is now named replaceLostConnection()
* Handle the case of a second connection loss on query retry
* Make canRecoverFromDisconnect() check for temporary tables
* Do not clear session-level variables on deadlock errors
  since only the transaction is lost, not the whole session
* Make sure any empty transaction is destroyed on deadlock
* Attempt reconnection *before* triggering the transaction
  callbacks since some of them  might want to use the database
* Define wasConnectionError() for postgres
* Remove unused return value from handleSessionLoss()

Change-Id: Ic1dcab03f087ce310637210e8e9bc0771e44f045
2018-03-29 20:33:31 +00:00
jenkins-bot
90b02397d0 Merge "rdbms: make selectRowCount() use $var argument to exclude NULLs" 2018-03-21 16:45:33 +00:00
Aaron Schulz
c6ac3d182c rdbms: define wasLockTimeout() for postgres
Change-Id: Ic54530f0b48fb3e3a42c1e6e95a5a75c6b5c061d
2018-03-19 18:08:37 -07:00
Aaron Schulz
d395dfb039 rdbms: make selectRowCount() use $var argument to exclude NULLs
If the $var argument is provided, then it will make the resulting
count exclude rows where the value for that column is NULL.

Also add buildSelectSubquery() method and Subquery
wrapper class for use with select() for calculated tables.

Change-Id: I549d629af99afdf370602de095f7fba6d1546c37
2018-03-18 01:34:33 +00:00
Brad Jorsch
6261b4187a rdbms: Add $join_conds to IDatabase::estimateRowCount()
So queries with joins can be estimated.

Change-Id: I9163cf9005d2c2001a88bb102eb4142f0322b0df
2018-03-12 12:15:14 -04:00
Aaron Schulz
55ab84e17d rdbms: avoid strange uses of empty()
Change-Id: Id1a8d1aae72cdee48e43ddb3227cd697516411e0
2018-03-01 20:30:07 -08:00
Aaron Schulz
60e8d3e16e rdbms: remove "m" member prefix from various classes
Change-Id: Iade8e8f70bb1307b96683d979d7e3650f4107515
2018-02-17 03:58:46 +00: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
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
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
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
Alexander Mashin
c428c2cf36 Ensure only strings are passed to mysql_real_escape_string()
Under some conditions (Semantic MediaWiki, Gadgets), an integer is
passed to DatabaseMysqli::mysqlRealEscapeString (). This integer is, in
turn, passed to mysqli::real_escape_string (), which needs a string.

Under HHVM 3.19.1 (at least) this type mismatch causes an exception.

A typecast should prevent it.

I repeated the patch in other DB drivers where I could find a function
that escaped strings for SQL.

Bug: T163646
Change-Id: I1b7820bc064dc79498cf9f17747f745990c526b7
2017-10-08 03:45:12 +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
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
Brad Jorsch
0a9c55bfd3 Deprecate IDatabase::nextSequenceValue()
It's often forgotten because MySQL and Sqlite don't use it, the only
users are PostgreSQL and Oracle. And when used, if inserts to multiple
tables are being done it's easy to get the ordering wrong.

This patch reimplements DatabasePostgres::insertId() in terms of PG's
lastval() function, and adds triggers to the Oracle schema to make it
work the same as the other databases.

Bug: T164900
Change-Id: Ib308190c52673a9266c8495a589ae644f9fbefce
2017-08-31 11:16:26 -04:00
Brad Jorsch
91b86399b1 Fix various PostgreSQL failures
* Fix schema for image_comment_temp.
* Provide values in CommentStoreTest::provideInsertRoundTrip() for
  columns where the PG schema doesn't have a default value but the MySQL
  schema does.
* Call nextSequenceValue() from CommentStoreTest::testInsertRoundTrip().
* Correctly handle $options being the string 'FOR UPDATE' in
  DatabasePostgres::selectSQLText()
* Correctly handle the initial table in DatabasePostgres::selectSQLText() FOR
  UPDATE mangling.
* Correctly handle aliases in DatabasePostgres::selectSQLText() FOR
  UPDATE mangling.

Tests in PG are still going to be broken thanks to the fact that
nextSequenceValue() and insertId() can't be separated by another
nextSequenceValue()/insertId() pair. That should be taken care of by
T164898/T164900.

Change-Id: Ia770a003ca9170ab8bcc1436d8afe30700e00ada
2017-08-30 17:18:29 -04:00
jenkins-bot
ddf3d27b10 Merge "Make DatabasePostgres::serverIsReadOnly() check default_transaction_read_only" 2017-06-15 21:04:22 +00:00
Aaron Schulz
1ac90c76f4 Make DatabasePostgres::serverIsReadOnly() check default_transaction_read_only
Change-Id: If6088c15271a827fedc6a585e070bab6c1acc371
2017-06-15 01:36:39 -07:00
Aaron Schulz
b7aaa8cdbe Set flush mode in DatabasePostgres::reportQueryError()
Bug: T167927
Change-Id: Ib02608cf33d369939a9e587cebfc736336a1e979
2017-06-15 01:25:17 -07:00
jenkins-bot
7f3d6713e7 Merge "Fix Postgres support" 2017-06-14 08:19:53 +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
6fb5844fec Fix TextPassDumperDatabaseTest::testPrefetchPlain postgres failures
The insertId() method was returning a string, which caused the
returnValueMap not to trigger due to int/string mismatches.

Also add sanity integer cast to WikiPage::insertOn().

Added a few more type docs.

Bug: T75174
Change-Id: Id1090f3e3d0481272a3d13c3af8f2588f06dc912
2017-05-26 21:43:17 +00:00
Aaron Schulz
44577c3962 Make sure unique keys carry over to postgres table duplicates
This fixes BotPasswordTest failures.

Change-Id: I81003187af0c57020f9fc4cbcd2606e71907a903
2017-05-16 19:20:42 -07:00
Aaron Schulz
6793b60eca Fix some postgres test failures
Bug: T75174
Change-Id: If9812ae301f0af84fa012e2e980b92036c1b29b2
2017-05-10 01:59:47 +00:00
mwjames
b5611ce6fa Fix Postgres support
See https://phabricator.wikimedia.org/T149454#3217259

This restores a line mistakenly deleted in
eef8fc45f3.

Bug: T149454
Change-Id: If6463904bb5269a7ccab5ddd69f69dba8104bc49
2017-05-08 21:06:55 +00:00
Aaron Schulz
dd359741cc Move DB errors to Rdbms namespace
Change-Id: I463bd86123501abc68fdb78b4cda6110f7af2549
2017-04-15 10:47:41 -07:00
Aaron Schulz
d735dc562d Move Database and subclasses to Rdbms namespace
Change-Id: I52bef87512f9ddd155d1f4cc0052f6b7a0db5b42
2017-04-12 10:43:57 -07:00
Aaron Schulz
1a1c43bdff Database: clean up lockTables() and add postgres support
A new method is now available to check whether session scope
locks are supported, which callers typically want when using lock().
Its usage can avoid deadlock prone and expensive row-level locks for
some maintenance tasks.

For Postgres, table locks are tied to the transaction. Trigger
startAtomic() in lockTables() and endAtomic() in unlockTables() to
assure that a transaction is present.

Also remove LOW_PRIORITY feature, which is ignored by mysql.

Change-Id: I499061bcc2763afb1ff4a43319064eed4ba3a8fe
2017-04-07 16:28:36 -07:00
Aaron Schulz
e01fd44388 Move ResultWrapper subclasses to Rdbms
Change-Id: I6f3f0e85e268b24c57c537aa6ad8016e0b4cdddb
2017-03-03 00:44:41 +00:00
Kunal Mehta
a57b64436c Use wikimedia/timestamp
Bug: T100924
Depends-On: I0a067367cda6885fa45631ed7c18799d653dc9bf
Change-Id: I69ba64e364df8af089c1c918cdf32f99454e693a
2017-02-28 21:15:38 -08:00
jenkins-bot
b444c2a3df Merge "includes/libs: Replace implicit Bugzilla bug numbers with Phab ones" 2017-02-28 00:50:31 +00:00
Bartosz Dziewoński
0da3d2ff2b Database: Remove weird commented-out block
Commented out in 033b6b9646 (r20329).
After ten years, I think it's safe to bet this won't ever be getting
un-commented.

Change-Id: Ibb1f3e2969b2d81f6f2a17fff57e9b05cc17d58b
2017-02-25 22:55:45 +01:00
James D. Forrester
b715f432f4 includes/libs: Replace implicit Bugzilla bug numbers with Phab ones
It's unreasonable to expect newbies to know that "bug 12345" means "Task T14345"
except where it doesn't, so let's just standardise on the real numbers.

Skipping jsminplus.php as those bug numbers aren't Wikimedia's, nor obviously
someone else's.

Change-Id: I9a2210e17852ee56f11282b980ac66d8c7a95671
2017-02-21 18:13:08 +00:00
Aaron Schulz
8a5d8c0c71 Move Field classes to Rdbms namespace
Update core callers and leave a class alias to \Field.

Change-Id: I4908282301d5de2a20baafe510557bd2c3867de5
2017-02-16 01:14:37 +00:00
Aaron Schulz
019fa7cb9c Move Blob class to Rdbms namespaces
Leave \Blob as an alias. Callers can now use the Rdbms\Blob class
for "extends"/"new" and the Rdbms\IBlob interface for type hints.

Change-Id: I983b76f181ac60c1eb92c350cd27ad77ec90a192
2017-02-13 21:07:00 +00:00