* Drop unused and likely broken /*$var*/` -> `$var syntax
* Replace {$var} with '{$var}' and `{$var}` handling that uses relevant database independent quoting ({$var} without surrouding quotes are never used)
* Give the generic/mysql class a proper quote_ident implementation
* Fix the unused Oracle and Sqlite quote_ident implementations which are potential sql injections if used
* Split common variable replacemnt code off to a replaceGlobalVars and make the generic and oracle code use it instead of duplicating the same code as each other
Wikis which set $wgServer in their LocalSettings or are in a virtual
host would never be vulnerable.
For sites which show the wiki in the default host, it will depend on how
forgiving is their webserver and php stack for that garbled input, although
some kind of foolable proxy —moreover wrongly caching errors (or the default
output buffering is disabled and something incorrectly sent a previous text)—
would also need to be present in order to make that useful for a
potential attacker.
* Made them all implement one common interface (might add more functions to it later)
* Moved MySQLField to DatabaseMysql.php
* Renamed nullable() to isNullable()
* Removed maxLength() from:
** SQLiteField: makes no sense
** MySQLField: doesn't do what people may think, useless for this class' purpose of assisting querying the DB schema
This means, the user data was innecessarily loaded here just for the debug message.
It also caused bug 24995 - "fallback" key missing from localization cache.
For languages other than English (short-circuitted in Language.php:2800) during
Language load, it gets the fallback from the localization cache, which used the db,
which then loaded here the User object, which called WebRequest caused unstubbing (again)
of ContentLanguage for unicode normalization, which loaded again the Language (a call
to loadItem( 'xx', 'fallback' ) under loadItem( 'xx', 'fallback' ) stack) and then
caused it to finally fail.
It wasn't an unstub loop, but was near.
Backtrace:
LocalisationCache::loadItem phase3/includes/LocalisationCache.php:205 <-- Second load of key fallback
LocalisationCache::getItem phase3/languages/Language.php:2802
Language::getFallbackFor phase3/languages/Language.php:169
Language::newFromCode phase3/languages/Language.php:140
Language::factory phase3/includes/StubObject.php:126
StubContLang::_newObject phase3/includes/StubObject.php:103
StubObject::_unstub phase3/includes/StubObject.php:57
StubObject::_call phase3/includes/StubObject.php:121
StubContLang::__call phase3/includes/WebRequest.php:204 <-- Second unstub
StubContLang::normalize phase3/includes/WebRequest.php:204
WebRequest::normalizeUnicode phase3/includes/WebRequest.php:231
WebRequest::getGPCVal phase3/includes/WebRequest.php:460
WebRequest::getCookie phase3/includes/User.php:835
User::loadFromSession phase3/includes/User.php:221
User::load phase3/includes/User.php:1501
User::getName phase3/includes/db/Database.php:658
DatabaseBase::query phase3/includes/db/DatabaseMysql.php:120
DatabaseMysql::open phase3/includes/db/Database.php:530
DatabaseBase::__construct phase3/includes/db/LoadBalancer.php:651
LoadBalancer::reallyOpenConnection phase3/includes/db/LoadBalancer.php:532
LoadBalancer::openConnection phase3/includes/db/LoadBalancer.php:455
LoadBalancer::getConnection phase3/includes/GlobalFunctions.php:3085
wfGetDB phase3/includes/LocalisationCache.php:772
LCStore_DB::get phase3/includes/LocalisationCache.php:326
LocalisationCache::isExpired phase3/includes/LocalisationCache.php:355
LocalisationCache::initLanguage phase3/includes/LocalisationCache.php:267
LocalisationCache::loadItem phase3/includes/LocalisationCache.php:205 <-- First load of key fallback
LocalisationCache::getItem phase3/languages/Language.php:2802
Language::getFallbackFor phase3/languages/Language.php:169
Language::newFromCode phase3/languages/Language.php:140
Language::factory phase3/includes/StubObject.php:126
StubContLang::_newObject phase3/includes/StubObject.php:103
StubObject::_unstub phase3/includes/StubObject.php:57
StubObject::_call phase3/includes/StubObject.php:121
StubContLang::__call phase3/includes/WebRequest.php:228 <-- First unstub
StubContLang::checkTitleEncoding phase3/includes/WebRequest.php:228
WebRequest::getGPCVal phase3/includes/WebRequest.php:250
WebRequest::getVal phase3/index.php:56
= BacklinkCache.php =
* BacklinkCache class
** Set a few otherwise unset varables ($wgContLang & $wgMemc in
BacklinkCache)
= testHelpers.inc =
* TectRecorder class
** TestRecorder::record() accept and use a recorder object
** change TestFileIterator::setParser use a MediaWikiParserTest instead
of ParserTest
= parserTest.inc =
* ParserTest class
** Make $ParserTest->regex and $ParsaerTest->savedGlobals member
variables available to stop warnings.
** Force ParserTest::$showProgress and $showFailure to false
** Set ParserTest::$uploadDir on time
** Move ParserTest::chomp() and addArticle() to bootstrap for
MediaWikiTestSetup.
** Update ParserTest::runTest so that Success and Failure are reported
via reporter->showsTestResult() or ParserTestSuiteBackend::show*()
as needed.
** Set $ParserTest->uploadDir with setupUploadDir()
** Change ParserTest->setupGlobals() so that $wgDBprefix doesn't get
to set to the “parsertest_” bits.
** Sprinkle $this->teardownGlobals() at exit points in
ParserTest->teardownDatabase()
= bootstrap.php =
* MediaWikiTestSetup class
** Make member variables MediaWikiTestSetup::$suite,
MediaW* Make member variables MediaWikiTestSetup::$suite,
MediaWikiTestSetup::$regex, MediaWikiTestSetup::$runDisabled
available.
* Setup a constructor MediaWikiTestSetup that accepts an optional
PHPUnit_Framework_TestSuite so they can use PHPUnit.
* Change MediaWikiParserTest so that it is derived from
MediaWikiTestSetup instead of PHPUnit_Framework_TestSuite
* Make MediaWikiParserTest create a PHPUnit_Framework_TestSuite for
the parser tests and pass it to the new parent (MediaWikiTestSetup)
as the PHPUnit testsuite.
* Replace MediaWikiParserTest->run() with MediaWikiParserTest::suite()
so that the tests can be loaded into a suite and then run with
PHPUnit's test runner.
= ParserHelpers.php =
* ParserUnitTest class
** Force run() $backend to use ParserTestSuiteBackend instead of
trying to get the backend from the suite member.
** Use ParserTest::runTest() instead of
ParserikiTestSetup::$regex, MediaWikiTestSetup::$runDisabled
available.
** Setup a constructor MediaWikiTestSetup that accepts an optional
PHPUnit_Framework_TestSuite so they can use PHPUnit.
** Change MediaWikiParserTest so that it is derived from
MediaWikiTestSetup instead of PHPUnit_Framework_TestSuite
** Make MediaWikiParserTest create a PHPUnit_Framework_TestSuite for
the parser tests and pass it to the new parent (MediaWikiTestSetup)
as the PHPUnit testsuite.
** Replace MediaWikiParserTest->run() with MediaWikiParserTest::suite()
so that the tests can be loaded into a suite and then run with
PHPUnit's test runner.
= ParserHelpers.php =
* ParserUnitTest class
** Force run() $backend to use ParserTestSuiteBackend instead of
trying to get the backend from the suite member.
** Use ParserTest::runTest() instead of
ParserTestSuiteBackend::runTest()
* ParserTestSuiteBackend class
** extends PHPUnit_FrameWork_TestSuite instead of ParserTest
** Add member variables $recorder, $term, and $usePHPUnit
** Add a constructor that determines if PHPUnit is usewd.
** Add a method showTestResult() that can be used to show success or
failure
** Change showSucess and showFailure() to be static and use identical
arguments and only use PHPUnit_Framework_Assert::assertEquals
when PHPUnit is in use.
= SearchEngineTest.php =
** Fix path in require to bootstrap.php
This way the required method names will show up when grepping
Database.php. I thought we had no affectedRows() method for a minute
there, until G_SabinoMullane corrected me (good thing I think aloud
in #mediawiki).
Avoid one-letter variable names, be descriptive. Name an unused value
variable in foreach "$unused". Add spaces where needed. Wrap comments
at 79 columns, not some arbitrarily-selected number. Remove blank line.
* Fixed fieldInfo() on Postgres not using tableName() and thus failing for table user, for example.
* Made fieldInfo() on MySQL return false instead of throwing a query error if table does not exist. This is consistent with other databases' behaviour.
See report on http://permalink.gmane.org/gmane.org.wikimedia.mediawiki/33902
Fixed several tag nesting problems from setup_database().
Make sourceFile() always use text errors in the installer. It can't handle
exceptions properly (introduced in r36211). But they are appropiate for update.php
thus the ugly branches.
The installer now always handles sourceFile() errors.
Like langlinks, this stores the interwiki prefix (as iwl_prefix) and full page title (as iwl_title), attached to the page doing the liking (as iwl_from -> page_id).
Unlike langlinks, there can be multiple entries stored per interwiki prefix.
Updater to add the table confirmed on MySQL, untested on SQLite but should work.
Someone may still need to add and test a PostgreSQL updater.
Refactored makeWhereFrom2d() out of LinkBatch to Database so it could be re-used for the similar mapping for the interwiki links, which need a string prefix rather than an int namespace key.
Also cleaned it up internally to reuse existing code for building where clauses from arrays. (Tim & Domas -- if the previous more verbose code was there to reduce function call and array processing overhead on very large link lists, feel free to unroll it again if the difference is measurable. Just swap the var names around from the old LinkBatch code and escape the base key value if it's not an integer, it'll be functionally equivalent.)
* Notice: Undefined variable: name in includes/db/Database.php on lines 2209 and 2212
* Fatal error: Call to undefined method DatabaseMysql::fileSource() in maintenance/patchSql.php on line 48
Before this change, there were (? being regex 0 or 1)
"" ===? 1
'' ===? 24
"" !==? 8
'' !==? 32
== "" 14
== '' 344
!= "" 9
!== "" 4
!= '' 151
!== '' 85
Rhs was the much more common, and the preferred style by many developers.. (Was a similar discussion in #mediawiki recently.. After that lolbugreport i think)
Where there is a string (non empty) on the lhs, and variable/method call on the rhs still need normalising
* All manually built LIKE queries in the core are replaced with a wrapper function Database::buildLike()
* This function automatically performs all escaping, so Database::escapeLike() is now almost never used
* In SqlBagOStuff, ignore errors due to a read-only database, per my comments on CR r42796. Same for LocalisationCache.
* Merged SqlBagOStuff and MediaWikiBagOStuff, that proved to be an awkward and unnecessary generalisation. Use the standard quoting wrapper functions instead of $db->query().
* Implemented atomic incr() and decr() functions for SqlBagOStuff.
* Made incr() and decr() generally work roughly the same as it does in memcached, respecting negative steps instead of ignoring such operations. This allows decr() to be implemented in terms of incr().
* Per bug 11533, in MessageCache.php, don't retry 20 times on a cache failure, that's really memcached-specific and won't be useful for other cache types. It's not really very useful for memcached either.
* Moved MySQL-specific implementations of wasDeadlock() and wasErrorReissuable() to DatabaseMysql.
* Briefly tested page views with $wgReadOnly=read_only=1, fixed an error from Article::viewUpdates(). A CentralAuth fix will be in a subsequent commit.
Also make it abstract in DatabaseBase so all subclasses have to implement some human readable name
(also make getSoftwareLink abstract for the same reason) Every current Database class already implements both.
Notably, this will switch conditional() in MySQL from using IF() to
using CASE, like all other DBMSes. Documentation suggests this works
back to 4.0. If it's a problem, it's a matter of a few lines to
override it in DatabaseMysql.php.
Also, some extra explanatory comments have been added to a number of
methods in DatabaseBase.
Specifically freeResult(), selectDB(), close(), and ping(), as suggested
by Tim on code review for r51918. Where these were overridden by stubs
in subclasses, I deleted the stubs.
I moved a number of methods and marked them abstract in DatabaseBase,
namely those that met the following criteria:
1) Used some mysql_* function, so would obviously fail on any other DB.
2) Were already implemented by all five non-MySQL subclasses.
It would be reasonable to revisit these and make the less essential ones
return a dummy value instead of being abstract. And document them. And
move more methods that are MySQL-specific. But one thing at a time.
I also split the classes Database, DatabaseMysql, and MySQLMasterPos to
DatabaseMysql.php.
This should theoretically have no practical changes, but it's a bunch of
changed code, so it will possibly break something by accident.
Followup to r51795.
PHP Catchable fatal error: Argument 1 passed to DBError::__construct() must be an instance of Database, instance of DatabaseMysql given, called in /var/www/w/includes/db/Database.php on line 2736 and defined in /var/www/w/includes/db/Database.php on line 2547
All other databases were changed to extend DatabaseBase instead of
Database. Database was kept as an alias for DatabaseMysql for
compatibility. Existing explicit references to Database that I could
find were changed to DatabaseMysql for the sake of clarity.
Should cause no functional changes.
Replaced hardcoded LIMIT clauses with database function (except in maintenance).
Created unionQueries in Database and overloaded it in DatabaseOracle (not commited yet).
Replaced all UNION clauses with function calls (except in maintenance).
This means that nothing at all should be passing bare result objects/arrays to Database*::fetchObject() anymore. The "instanceof ResultWrapper" logic can be removed in a subsequent commit. It can stay in this one for now for safer backport to 1.15.
* Improvement to ChronologyProtector: only record the master position if a write query was done. This should help to avoid the worst of the ChronologyProtector side-effects, such as having action=raw CSS requests block for a time equivalent to the slave lag on every page view, while maintaining the benefits, like preventing a 404 from being displayed after page creation.
* rename non-PRIMARY indices that were implicitly named before r45764 back to their implicit names
* add the renamed un_user_id and un_user_ip to the indexName() rewrite
* use consistent casing for PRIMARY KEY
* removing the indexName() hack and with it the /*i*/ stuff from tables.sql
* undoing renames of formerly implicitly named indices
* three indices have to be called different in SQLite because of naming conflicts, adding a patch to updaters.inc that does that
* Made the upgrader work with SQLite
* Implemented missing schema info functionality in DatabaseSqlite
* Merged the SQLite and MySQL schemas into the one file with the help of some replaceVars() hacks.
* Moved all primary key definitions to the field definition, moved all indexes to CREATE INDEX statements, for best SQLite compatibility.
* Made all autoincrement fields primary keys, as required by SQLite.
* Removed meaningless buzzword from the category table comment
* tables.sql: s/'0'/0/
* In SQLite the index names have DB scope. Renamed archive.usertext_timestamp, user_newtalk.user_id, user_newtalk.user_ip
* SQLite does not support UPDATE with LIMIT by default. Removed all instances I could find.
* Made query errors work in the installer.
* Fixed DatabaseSqlite::lastErrno(), made SQLITE_SCHEMA errors automatically reissue the query as suggested on sqlite-users. Otherwise upgrade breaks.
* Removed miscellaneous status information from getServerVersion(), that's not the place to put it
* renamed \2types and \3types both to \types (with different number of param), Doxygen doesn't seem to like numbers in aliases
* Added aliases for @private, @protected and @public
* Don't call quickUserCan('edit') unless section edit is enabled
* In DatabasePostgres and DatabaseSqlite: throw an exception on connection error
* In DatabasePostgres: don't send an invalid connection string whenever one of the fields is empty. Use quoting.
* In Database: make the captured PHP error prettier
* Display a descriptive error message when the user navigates to index.php with PHP 4, not a parse error. Check to see if the *.php5 extension works, using file_get_contents().
* The default port number for PostgreSQL is 5432, not blank.
* Better default for $wgDBname
* Fix broken recursion guard in LoadBalancer::reportConnectionError(), which was causing getConnection() to return false on the second and subsequent errors, instead of throwing an exception. Revert incorrect fix r41229/r41230.
* We used to have parameters to ignore errors, but they're obsolete now that we have exceptions. Implemented ES master failover using exceptions instead.
* Changing the number of DB connection attempts from 3 to 2 for some random getConnection() calls is almost pointless, adds lots of ugly formal parameters all of the place, and misses the big picture. It should be 2 by default, based on the original rationale. Any reasonable implementation of failover should have zero timeouts per request, by storing state. Changed the default to 2, or 1 if a long timeout is set.
* On read, spend less time checking on dead slaves
* Add randomInsert() to ES. This does the cluster picking for us
* Make revision text use randomInsert(). On write, fails-over to other clusters as needed instead of throwing db errors
Code was attempting to handle this case by asking the result object for its db so we can ask for the affected row count -- obviously that doesn't do so good when the result is not an object.
Changed Database::sourceStream() to send itself as the second parameter to the result-handling callback, so the callback knows which DB to check.
* Came up with a neater way to micro-optimise local section determination.
* Renamed LBFactory::destroy() to LBFactory::destroyInstance(), and made it close connections since apparently that's not done by default when the connection resources are destroyed.
* Removed Database::$mOut, hasn't been used for a while and it dirties up var_dump($db)
or Database::newFromParams() explicitly at the moment. While that's already bad (breaking PG support etc), I'd rather see those get fixed before we go introducing differences between Database and DatabaseMySql.
* Wrote a tool to check the integrity of the autoloader class list, fixed some issues that came up.
* Start the autoloader before LocalSettings.php, so that when an extension writer thinks an inefficient one-file special page extension is the way to go, they don't have to use explicit includes to make the class inheritance work. Should continue to work with $IP set in LocalSettings.php as long as $IP is set before extensions are included.