summaryrefslogtreecommitdiff
path: root/includes/db
diff options
context:
space:
mode:
Diffstat (limited to 'includes/db')
-rw-r--r--includes/db/CloneDatabase.php6
-rw-r--r--includes/db/Database.php401
-rw-r--r--includes/db/DatabaseError.php54
-rw-r--r--includes/db/DatabaseIbm_db2.php225
-rw-r--r--includes/db/DatabaseMssql.php2
-rw-r--r--includes/db/DatabaseMysql.php329
-rw-r--r--includes/db/DatabaseOracle.php31
-rw-r--r--includes/db/DatabasePostgres.php57
-rw-r--r--includes/db/DatabaseSqlite.php8
-rw-r--r--includes/db/DatabaseUtility.php15
-rw-r--r--includes/db/LBFactory.php11
-rw-r--r--includes/db/LBFactory_Multi.php27
-rw-r--r--includes/db/LBFactory_Single.php8
-rw-r--r--includes/db/LoadBalancer.php85
-rw-r--r--includes/db/LoadMonitor.php6
15 files changed, 994 insertions, 271 deletions
diff --git a/includes/db/CloneDatabase.php b/includes/db/CloneDatabase.php
index 3357268d..bd0895cf 100644
--- a/includes/db/CloneDatabase.php
+++ b/includes/db/CloneDatabase.php
@@ -93,12 +93,12 @@ class CloneDatabase {
# fix back and forth so tableName() works right.
self::changePrefix( $this->oldTablePrefix );
- $oldTableName = $this->db->tableName( $tbl, false );
+ $oldTableName = $this->db->tableName( $tbl, 'raw' );
self::changePrefix( $this->newTablePrefix );
- $newTableName = $this->db->tableName( $tbl, false );
+ $newTableName = $this->db->tableName( $tbl, 'raw' );
- if( $this->dropCurrentTables && !in_array( $this->db->getType(), array( 'postgres' ) ) ) {
+ if( $this->dropCurrentTables && !in_array( $this->db->getType(), array( 'postgres', 'oracle' ) ) ) {
$this->db->dropTable( $tbl, __METHOD__ );
wfDebug( __METHOD__." dropping {$newTableName}\n", true);
//Dropping the oldTable because the prefix was changed
diff --git a/includes/db/Database.php b/includes/db/Database.php
index d1a3b2bd..9f34f812 100644
--- a/includes/db/Database.php
+++ b/includes/db/Database.php
@@ -224,6 +224,12 @@ abstract class DatabaseBase implements DatabaseType {
protected $mDefaultBigSelects = null;
protected $mSchemaVars = false;
+ protected $preparedArgs;
+
+ protected $htmlErrors;
+
+ protected $delimiter = ';';
+
# ------------------------------------------------------------------------------
# Accessors
# ------------------------------------------------------------------------------
@@ -242,7 +248,7 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Boolean, controls output of large amounts of debug information.
- * @param $debug:
+ * @param $debug bool|null
* - true to enable debugging
* - false to disable debugging
* - omitted or null to do nothing
@@ -290,7 +296,9 @@ abstract class DatabaseBase implements DatabaseType {
* code should use lastErrno() and lastError() to handle the
* situation as appropriate.
*
- * @return The previous value of the flag.
+ * @param $ignoreErrors bool|null
+ *
+ * @return bool The previous value of the flag.
*/
function ignoreErrors( $ignoreErrors = null ) {
return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors );
@@ -324,15 +332,17 @@ abstract class DatabaseBase implements DatabaseType {
* @return The previous table prefix.
*/
function tablePrefix( $prefix = null ) {
- return wfSetVar( $this->mTablePrefix, $prefix, true );
+ return wfSetVar( $this->mTablePrefix, $prefix );
}
/**
* Get properties passed down from the server info array of the load
* balancer.
*
- * @param $name The entry of the info array to get, or null to get the
+ * @param $name string The entry of the info array to get, or null to get the
* whole array
+ *
+ * @return LoadBalancer|null
*/
function getLBInfo( $name = null ) {
if ( is_null( $name ) ) {
@@ -353,7 +363,6 @@ abstract class DatabaseBase implements DatabaseType {
*
* @param $name
* @param $value
- * @return void
*/
function setLBInfo( $name, $value = null ) {
if ( is_null( $value ) ) {
@@ -365,6 +374,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Set lag time in seconds for a fake slave
+ *
+ * @param $lag int
*/
function setFakeSlaveLag( $lag ) {
$this->mFakeSlaveLag = $lag;
@@ -372,6 +383,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Make this connection a fake master
+ *
+ * @param $enabled bool
*/
function setFakeMaster( $enabled = true ) {
$this->mFakeMaster = $enabled;
@@ -379,6 +392,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database supports (and uses) cascading deletes
+ *
+ * @return bool
*/
function cascadingDeletes() {
return false;
@@ -386,6 +401,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database supports (and uses) triggers (e.g. on the page table)
+ *
+ * @return bool
*/
function cleanupTriggers() {
return false;
@@ -394,6 +411,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database is strict about what can be put into an IP field.
* Specifically, it uses a NULL value instead of an empty string.
+ *
+ * @return bool
*/
function strictIPs() {
return false;
@@ -401,6 +420,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database uses timestamps rather than integers
+ *
+ * @return bool
*/
function realTimestamps() {
return false;
@@ -408,6 +429,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database does an implicit sort when doing GROUP BY
+ *
+ * @return bool
*/
function implicitGroupby() {
return true;
@@ -416,6 +439,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database does an implicit order by when the column has an index
* For example: SELECT page_title FROM page LIMIT 1
+ *
+ * @return bool
*/
function implicitOrderby() {
return true;
@@ -424,6 +449,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database requires that SELECT DISTINCT queries require that all
ORDER BY expressions occur in the SELECT list per the SQL92 standard
+ *
+ * @return bool
*/
function standardSelectDistinct() {
return true;
@@ -432,6 +459,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database can do a native search on IP columns
* e.g. this works as expected: .. WHERE rc_ip = '127.42.12.102/32';
+ *
+ * @return bool
*/
function searchableIPs() {
return false;
@@ -439,6 +468,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns true if this database can use functional indexes
+ *
+ * @return bool
*/
function functionalIndexes() {
return false;
@@ -452,7 +483,6 @@ abstract class DatabaseBase implements DatabaseType {
return $this->mLastQuery;
}
-
/**
* Returns true if the connection may have been used for write queries.
* Should return true if unsure.
@@ -508,6 +538,10 @@ abstract class DatabaseBase implements DatabaseType {
/**
* General read-only accessor
+ *
+ * @param $name string
+ *
+ * @return string
*/
function getProperty( $name ) {
return $this->$name;
@@ -579,13 +613,27 @@ abstract class DatabaseBase implements DatabaseType {
}
/**
+ * Called by serialize. Throw an exception when DB connection is serialized.
+ * This causes problems on some database engines because the connection is
+ * not restored on unserialize.
+ */
+ public function __sleep() {
+ throw new MWException( 'Database serialization may cause problems, since the connection is not restored on wakeup.' );
+ }
+
+ /**
* Same as new DatabaseMysql( ... ), kept for backward compatibility
* @deprecated since 1.17
*
+ * @param $server
+ * @param $user
+ * @param $password
+ * @param $dbName
+ * @param $flags int
* @return DatabaseMysql
*/
static function newFromParams( $server, $user, $password, $dbName, $flags = 0 ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.17' );
return new DatabaseMysql( $server, $user, $password, $dbName, $flags );
}
@@ -595,7 +643,7 @@ abstract class DatabaseBase implements DatabaseType {
* @see Database::factory()
*/
public final static function newFromType( $dbType, $p = array() ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.18' );
if ( isset( $p['tableprefix'] ) ) {
$p['tablePrefix'] = $p['tableprefix'];
}
@@ -627,9 +675,9 @@ abstract class DatabaseBase implements DatabaseType {
'mysql', 'postgres', 'sqlite', 'oracle', 'mssql', 'ibm_db2'
);
$dbType = strtolower( $dbType );
+ $class = 'Database' . ucfirst( $dbType );
- if( in_array( $dbType, $canonicalDBTypes ) ) {
- $class = 'Database' . ucfirst( $dbType );
+ if( in_array( $dbType, $canonicalDBTypes ) || ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) ) {
return new $class(
isset( $p['host'] ) ? $p['host'] : false,
isset( $p['user'] ) ? $p['user'] : false,
@@ -649,6 +697,9 @@ abstract class DatabaseBase implements DatabaseType {
set_error_handler( array( $this, 'connectionErrorHandler' ) );
}
+ /**
+ * @return bool|string
+ */
protected function restoreErrorHandler() {
restore_error_handler();
if ( $this->htmlErrors !== false ) {
@@ -663,6 +714,10 @@ abstract class DatabaseBase implements DatabaseType {
}
}
+ /**
+ * @param $errno
+ * @param $errstr
+ */
protected function connectionErrorHandler( $errno, $errstr ) {
$this->mPHPError = $errstr;
}
@@ -695,7 +750,7 @@ abstract class DatabaseBase implements DatabaseType {
* The DBMS-dependent part of query()
*
* @param $sql String: SQL query.
- * @return Result object to feed to fetchObject, fetchRow, ...; or false on failure
+ * @return ResultWrapper Result object to feed to fetchObject, fetchRow, ...; or false on failure
*/
protected abstract function doQuery( $sql );
@@ -703,6 +758,8 @@ abstract class DatabaseBase implements DatabaseType {
* Determine whether a query writes to the DB.
* Should return true if unsure.
*
+ * @param $sql string
+ *
* @return bool
*/
function isWriteQuery( $sql ) {
@@ -776,8 +833,8 @@ abstract class DatabaseBase implements DatabaseType {
# that would delay transaction initializations to once connection
# is really used by application
$sqlstart = substr( $sql, 0, 10 ); // very much worth it, benchmark certified(tm)
- if ( strpos( $sqlstart, "SHOW " ) !== 0 and strpos( $sqlstart, "SET " ) !== 0 )
- $this->begin();
+ if ( strpos( $sqlstart, "SHOW " ) !== 0 && strpos( $sqlstart, "SET " ) !== 0 )
+ $this->begin( __METHOD__ . " ($fname)" );
}
if ( $this->debug() ) {
@@ -787,20 +844,21 @@ abstract class DatabaseBase implements DatabaseType {
$sqlx = substr( $commentedSql, 0, 500 );
$sqlx = strtr( $sqlx, "\t\n", ' ' );
- if ( $isMaster ) {
- wfDebug( "Query $cnt (master): $sqlx\n" );
- } else {
- wfDebug( "Query $cnt (slave): $sqlx\n" );
- }
+ $master = $isMaster ? 'master' : 'slave';
+ wfDebug( "Query {$this->mDBname} ($cnt) ($master): $sqlx\n" );
}
if ( istainted( $sql ) & TC_MYSQL ) {
throw new MWException( 'Tainted query found' );
}
+ $queryId = MWDebug::query( $sql, $fname, $isMaster );
+
# Do the query and handle errors
$ret = $this->doQuery( $commentedSql );
+ MWDebug::queryTime( $queryId );
+
# Try reconnecting if the connection was lost
if ( false === $ret && $this->wasErrorReissuable() ) {
# Transaction is gone, like it or not
@@ -874,6 +932,9 @@ abstract class DatabaseBase implements DatabaseType {
* database classes. The query wrapper functions (select() etc.) should be
* used instead.
*
+ * @param $sql string
+ * @param $func string
+ *
* @return array
*/
function prepare( $sql, $func = 'DatabaseBase::prepare' ) {
@@ -885,6 +946,7 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Free a prepared query, generated by prepare().
+ * @param $prepared
*/
function freePrepared( $prepared ) {
/* No-op by default */
@@ -959,7 +1021,6 @@ abstract class DatabaseBase implements DatabaseType {
*
* @param $matches Array
* @return String
- * @private
*/
function fillPreparedArg( $matches ) {
switch( $matches[1] ) {
@@ -999,6 +1060,12 @@ abstract class DatabaseBase implements DatabaseType {
* This function exists for historical reasons, DatabaseBase::update() has a more standard
* calling convention and feature set
*
+ * @param $table string
+ * @param $var
+ * @param $value
+ * @param $cond
+ * @param $fname string
+ *
* @return bool
*/
function set( $table, $var, $value, $cond, $fname = 'DatabaseBase::set' ) {
@@ -1160,7 +1227,6 @@ abstract class DatabaseBase implements DatabaseType {
* @param $options Array Query options
* @param $join_conds Array Join conditions
*
- *
* @param $table string|array
*
* May be either an array of table names, or a single string holding a table
@@ -1324,7 +1390,7 @@ abstract class DatabaseBase implements DatabaseType {
$from = ' FROM ' . implode( ',', $this->tableNamesWithAlias( $table ) );
}
} elseif ( $table != '' ) {
- if ( $table { 0 } == ' ' ) {
+ if ( $table[0] == ' ' ) {
$from = ' FROM ' . $table;
} else {
$from = ' FROM ' . $this->tableName( $table );
@@ -1364,7 +1430,7 @@ abstract class DatabaseBase implements DatabaseType {
*
* @param $table string|array Table name
* @param $vars string|array Field names
- * @param $conds|array Conditions
+ * @param $conds array Conditions
* @param $fname string Caller function name
* @param $options string|array Query options
* @param $join_conds array|string Join conditions
@@ -1404,8 +1470,8 @@ abstract class DatabaseBase implements DatabaseType {
* Takes the same arguments as DatabaseBase::select().
*
* @param $table String: table name
- * @param $vars Array: unused
- * @param $conds Array: filters on the table
+ * @param Array|string $vars : unused
+ * @param Array|string $conds : filters on the table
* @param $fname String: function name for profiling
* @param $options Array: options for select
* @return Integer: row count
@@ -1428,7 +1494,9 @@ abstract class DatabaseBase implements DatabaseType {
* Removes most variables from an SQL query and replaces them with X or N for numbers.
* It's only slightly flawed. Don't use for anything important.
*
- * @param $sql String: A SQL Query
+ * @param $sql String A SQL Query
+ *
+ * @return string
*/
static function generalizeSQL( $sql ) {
# This does the same as the regexp below would do, but in such a way
@@ -1469,6 +1537,10 @@ abstract class DatabaseBase implements DatabaseType {
* Usually throws a DBQueryError on failure
* If errors are explicitly ignored, returns NULL on failure
*
+ * @param $table
+ * @param $index
+ * @param $fname string
+ *
* @return bool|null
*/
function indexExists( $table, $index, $fname = 'DatabaseBase::indexExists' ) {
@@ -1483,14 +1555,15 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Query whether a given table exists
*
- * @string table
+ * @param $table string
+ * @param $fname string
*
* @return bool
*/
- function tableExists( $table ) {
+ function tableExists( $table, $fname = __METHOD__ ) {
$table = $this->tableName( $table );
$old = $this->ignoreErrors( true );
- $res = $this->query( "SELECT 1 FROM $table LIMIT 1", __METHOD__ );
+ $res = $this->query( "SELECT 1 FROM $table LIMIT 1", $fname );
$this->ignoreErrors( $old );
return (bool)$res;
@@ -1498,6 +1571,9 @@ abstract class DatabaseBase implements DatabaseType {
/**
* mysql_field_type() wrapper
+ * @param $res
+ * @param $index
+ * @return string
*/
function fieldType( $res, $index ) {
if ( $res instanceof ResultWrapper ) {
@@ -1562,7 +1638,7 @@ abstract class DatabaseBase implements DatabaseType {
*
* @param $table String Table name. This will be passed through
* DatabaseBase::tableName().
- * @param $a Array of rows to insert
+ * @param $a Array of rows to insert
* @param $fname String Calling function name (use __METHOD__) for logs/profiling
* @param $options Array of options
*
@@ -1662,7 +1738,7 @@ abstract class DatabaseBase implements DatabaseType {
$opts = $this->makeUpdateOptions( $options );
$sql = "UPDATE $opts $table SET " . $this->makeList( $values, LIST_SET );
- if ( $conds != '*' ) {
+ if ( $conds !== array() && $conds !== '*' ) {
$sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
}
@@ -1672,7 +1748,7 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Makes an encoded list of strings from an array
* @param $a Array containing the data
- * @param $mode:
+ * @param $mode int Constant
* - LIST_COMMA: comma separated, no field names
* - LIST_AND: ANDed WHERE clause (without the WHERE). See
* the documentation for $conds in DatabaseBase::select().
@@ -1800,6 +1876,9 @@ abstract class DatabaseBase implements DatabaseType {
* Change the current database
*
* @todo Explain what exactly will fail if this is not overridden.
+ *
+ * @param $db
+ *
* @return bool Success or failure
*/
function selectDB( $db ) {
@@ -1835,11 +1914,13 @@ abstract class DatabaseBase implements DatabaseType {
* when calling query() directly.
*
* @param $name String: database table name
- * @param $quoted Boolean: Automatically pass the table name through
- * addIdentifierQuotes() so that it can be used in a query.
+ * @param $format String One of:
+ * quoted - Automatically pass the table name through addIdentifierQuotes()
+ * so that it can be used in a query.
+ * raw - Do not add identifier quotes to the table name
* @return String: full database name
*/
- function tableName( $name, $quoted = true ) {
+ function tableName( $name, $format = 'quoted' ) {
global $wgSharedDB, $wgSharedPrefix, $wgSharedTables;
# Skip the entire process when we have a string quoted on both ends.
# Note that we check the end so that we will still quote any use of
@@ -1871,7 +1952,7 @@ abstract class DatabaseBase implements DatabaseType {
}
$prefix = $this->mTablePrefix; # Default prefix
- # A database name has been specified in input. We don't want any
+ # A database name has been specified in input. We don't want any
# prefixes added.
if ( isset( $database ) ) {
$prefix = '';
@@ -1891,11 +1972,11 @@ abstract class DatabaseBase implements DatabaseType {
# Quote the $database and $table and apply the prefix if not quoted.
if ( isset( $database ) ) {
- $database = ( !$quoted || $this->isQuotedIdentifier( $database ) ? $database : $this->addIdentifierQuotes( $database ) );
+ $database = ( $format == 'quoted' || $this->isQuotedIdentifier( $database ) ? $database : $this->addIdentifierQuotes( $database ) );
}
$table = "{$prefix}{$table}";
- if ( $quoted && !$this->isQuotedIdentifier( $table ) ) {
+ if ( $format == 'quoted' && !$this->isQuotedIdentifier( $table ) ) {
$table = $this->addIdentifierQuotes( "{$table}" );
}
@@ -1913,6 +1994,8 @@ abstract class DatabaseBase implements DatabaseType {
* extract($dbr->tableNames('user','watchlist'));
* $sql = "SELECT wl_namespace,wl_title FROM $watchlist,$user
* WHERE wl_user=user_id AND wl_user=$nameWithQuotes";
+ *
+ * @return array
*/
public function tableNames() {
$inArray = func_get_args();
@@ -1933,6 +2016,8 @@ abstract class DatabaseBase implements DatabaseType {
* list( $user, $watchlist ) = $dbr->tableNamesN('user','watchlist');
* $sql = "SELECT wl_namespace,wl_title FROM $watchlist,$user
* WHERE wl_user=user_id AND wl_user=$nameWithQuotes";
+ *
+ * @return array
*/
public function tableNamesN() {
$inArray = func_get_args();
@@ -1950,7 +2035,7 @@ abstract class DatabaseBase implements DatabaseType {
* e.g. tableName AS newTableName
*
* @param $name string Table name, see tableName()
- * @param $alias string Alias (optional)
+ * @param $alias string|bool Alias (optional)
* @return string SQL name for aliased table. Will not alias a table to its own name
*/
public function tableNameWithAlias( $name, $alias = false ) {
@@ -1982,9 +2067,9 @@ abstract class DatabaseBase implements DatabaseType {
* Get the aliased table name clause for a FROM clause
* which might have a JOIN and/or USE INDEX clause
*
- * @param $tables array( [alias] => table )
- * @param $use_index array() Same as for select()
- * @param $join_conds array() Same as for select()
+ * @param $tables array ( [alias] => table )
+ * @param $use_index array Same as for select()
+ * @param $join_conds array Same as for select()
* @return string
*/
protected function tableNamesWithUseIndexOrJOIN(
@@ -2087,6 +2172,8 @@ abstract class DatabaseBase implements DatabaseType {
* Since MySQL is the odd one out here the double quotes are our generic
* and we implement backticks in DatabaseMysql.
*
+ * @param $s string
+ *
* @return string
*/
public function addIdentifierQuotes( $s ) {
@@ -2111,10 +2198,12 @@ abstract class DatabaseBase implements DatabaseType {
* was renamed to addIdentifierQuotes.
* @deprecated since 1.18 use addIdentifierQuotes
*
+ * @param $s string
+ *
* @return string
*/
function quote_ident( $s ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.18' );
return $this->addIdentifierQuotes( $s );
}
@@ -2123,12 +2212,20 @@ abstract class DatabaseBase implements DatabaseType {
* WARNING: you should almost never use this function directly,
* instead use buildLike() that escapes everything automatically
* @deprecated since 1.17, warnings in 1.17, removed in ???
+ *
+ * @param $s string
+ *
+ * @return string
*/
public function escapeLike( $s ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.17' );
return $this->escapeLikeInternal( $s );
}
+ /**
+ * @param $s string
+ * @return string
+ */
protected function escapeLikeInternal( $s ) {
$s = str_replace( '\\', '\\\\', $s );
$s = $this->strencode( $s );
@@ -2181,7 +2278,7 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns a token for buildLike() that denotes a '%' to be used in a LIKE query
*
- * @rerturn LikeMatch
+ * @return LikeMatch
*/
function anyString() {
return new LikeMatch( '%' );
@@ -2191,6 +2288,12 @@ abstract class DatabaseBase implements DatabaseType {
* Returns an appropriately quoted sequence value for inserting a new row.
* MySQL has autoincrement fields, so this is just NULL. But the PostgreSQL
* subclass will return an integer, and save the value for insertId()
+ *
+ * Any implementation of this function should *not* involve reusing
+ * sequence numbers created for rolled-back transactions.
+ * See http://bugs.mysql.com/bug.php?id=30767 for details.
+ * @param $seqName string
+ * @return null
*/
function nextSequenceValue( $seqName ) {
return null;
@@ -2203,6 +2306,8 @@ abstract class DatabaseBase implements DatabaseType {
* which index to pick. Anyway, other databases might have different
* indexes on a given table. So don't bother overriding this unless you're
* MySQL.
+ * @param $index
+ * @return string
*/
function useIndexClause( $index ) {
return '';
@@ -2223,14 +2328,11 @@ abstract class DatabaseBase implements DatabaseType {
* to collide. However if you do this, you run the risk of encountering
* errors which wouldn't have occurred in MySQL.
*
- * @param $rows Can be either a single row to insert, or multiple rows,
+ * @param $table String: The table to replace the row(s) in.
+ * @param $rows array Can be either a single row to insert, or multiple rows,
* in the same format as for DatabaseBase::insert()
- * @param $uniqueIndexes is an array of indexes. Each element may be either
+ * @param $uniqueIndexes array is an array of indexes. Each element may be either
* a field name or an array of field names
- *
- * @param $table String: The table to replace the row(s) in.
- * @param $uniqueIndexes Array: An associative array of indexes
- * @param $rows Array: Array of rows to replace
* @param $fname String: Calling function name (use __METHOD__) for logs/profiling
*/
function replace( $table, $uniqueIndexes, $rows, $fname = 'DatabaseBase::replace' ) {
@@ -2284,9 +2386,11 @@ abstract class DatabaseBase implements DatabaseType {
* REPLACE query wrapper for MySQL and SQLite, which have a native REPLACE
* statement.
*
- * @param $table Table name
- * @param $rows Rows to insert
- * @param $fname Caller function name
+ * @param $table string Table name
+ * @param $rows array Rows to insert
+ * @param $fname string Caller function name
+ *
+ * @return ResultWrapper
*/
protected function nativeReplace( $table, $rows, $fname ) {
$table = $this->tableName( $table );
@@ -2353,6 +2457,11 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Returns the size of a text field, or -1 for "unlimited"
+ *
+ * @param $table string
+ * @param $field string
+ *
+ * @return int
*/
function textFieldSize( $table, $field ) {
$table = $this->tableName( $table );
@@ -2412,24 +2521,24 @@ abstract class DatabaseBase implements DatabaseType {
* INSERT SELECT wrapper. Takes data from a SELECT query and inserts it
* into another table.
*
- * @param $destTable The table name to insert into
- * @param $srcTable May be either a table name, or an array of table names
+ * @param $destTable string The table name to insert into
+ * @param $srcTable string|array May be either a table name, or an array of table names
* to include in a join.
*
- * @param $varMap must be an associative array of the form
+ * @param $varMap array must be an associative array of the form
* array( 'dest1' => 'source1', ...). Source items may be literals
* rather than field names, but strings should be quoted with
* DatabaseBase::addQuotes()
*
- * @param $conds Condition array. See $conds in DatabaseBase::select() for
+ * @param $conds array Condition array. See $conds in DatabaseBase::select() for
* the details of the format of condition arrays. May be "*" to copy the
* whole table.
*
- * @param $fname The function name of the caller, from __METHOD__
+ * @param $fname string The function name of the caller, from __METHOD__
*
- * @param $insertOptions Options for the INSERT part of the query, see
+ * @param $insertOptions array Options for the INSERT part of the query, see
* DatabaseBase::insert() for details.
- * @param $selectOptions Options for the SELECT part of the query, see
+ * @param $selectOptions array Options for the SELECT part of the query, see
* DatabaseBase::select() for details.
*
* @return ResultWrapper
@@ -2461,7 +2570,10 @@ abstract class DatabaseBase implements DatabaseType {
" FROM $srcTable $useIndex ";
if ( $conds != '*' ) {
- $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
+ if ( is_array( $conds ) ) {
+ $conds = $this->makeList( $conds, LIST_AND );
+ }
+ $sql .= " WHERE $conds";
}
$sql .= " $tailOpts";
@@ -2483,9 +2595,9 @@ abstract class DatabaseBase implements DatabaseType {
* The version provided by default works in MySQL and SQLite. It will very
* likely need to be overridden for most other DBMSes.
*
- * @param $sql String: SQL query we will append the limit too
- * @param $limit Integer: the SQL limit
- * @param $offset Integer the SQL offset (default false)
+ * @param $sql String SQL query we will append the limit too
+ * @param $limit Integer the SQL limit
+ * @param $offset Integer|false the SQL offset (default false)
*
* @return string
*/
@@ -2499,6 +2611,11 @@ abstract class DatabaseBase implements DatabaseType {
. "{$limit} ";
}
+ /**
+ * @param $sql
+ * @param $num
+ * @return string
+ */
function limitResultForUpdate( $sql, $num ) {
return $this->limitResult( $sql, $num, 0 );
}
@@ -2553,6 +2670,16 @@ abstract class DatabaseBase implements DatabaseType {
}
/**
+ * Determines how long the server has been up
+ * STUB
+ *
+ * @return int
+ */
+ function getServerUptime() {
+ return 0;
+ }
+
+ /**
* Determines if the last failure was due to a deadlock
* STUB
*
@@ -2563,6 +2690,16 @@ abstract class DatabaseBase implements DatabaseType {
}
/**
+ * Determines if the last failure was due to a lock timeout
+ * STUB
+ *
+ * @return bool
+ */
+ function wasLockTimeout() {
+ return false;
+ }
+
+ /**
* Determines if the last query error was something that should be dealt
* with by pinging the connection and reissuing the query.
* STUB
@@ -2598,11 +2735,12 @@ abstract class DatabaseBase implements DatabaseType {
* Returns whatever the callback function returned on its successful,
* iteration, or false on error, for example if the retry limit was
* reached.
+ *
+ * @return bool
*/
function deadlockLoop() {
- $myFname = 'DatabaseBase::deadlockLoop';
- $this->begin();
+ $this->begin( __METHOD__ );
$args = func_get_args();
$function = array_shift( $args );
$oldIgnore = $this->ignoreErrors( true );
@@ -2633,11 +2771,11 @@ abstract class DatabaseBase implements DatabaseType {
$this->ignoreErrors( $oldIgnore );
if ( $tries <= 0 ) {
- $this->rollback( $myFname );
+ $this->rollback( __METHOD__ );
$this->reportQueryError( $error, $errno, $sql, $fname );
return false;
} else {
- $this->commit( $myFname );
+ $this->commit( __METHOD__ );
return $retVal;
}
}
@@ -2654,29 +2792,28 @@ abstract class DatabaseBase implements DatabaseType {
* zero if we timed out.
*/
function masterPosWait( DBMasterPos $pos, $timeout ) {
- $fname = 'DatabaseBase::masterPosWait';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );
if ( !is_null( $this->mFakeSlaveLag ) ) {
$wait = intval( ( $pos->pos - microtime( true ) + $this->mFakeSlaveLag ) * 1e6 );
if ( $wait > $timeout * 1e6 ) {
wfDebug( "Fake slave timed out waiting for $pos ($wait us)\n" );
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return -1;
} elseif ( $wait > 0 ) {
wfDebug( "Fake slave waiting $wait us\n" );
usleep( $wait );
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return 1;
} else {
wfDebug( "Fake slave up to date ($wait us)\n" );
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return 0;
}
}
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
# Real waits are implemented in the subclass.
return 0;
@@ -2713,6 +2850,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Begin a transaction, committing any previously open transaction
+ *
+ * @param $fname string
*/
function begin( $fname = 'DatabaseBase::begin' ) {
$this->query( 'BEGIN', $fname );
@@ -2721,6 +2860,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* End a transaction
+ *
+ * @param $fname string
*/
function commit( $fname = 'DatabaseBase::commit' ) {
if ( $this->mTrxLevel ) {
@@ -2732,6 +2873,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Rollback a transaction.
* No-op on non-transactional databases.
+ *
+ * @param $fname string
*/
function rollback( $fname = 'DatabaseBase::rollback' ) {
if ( $this->mTrxLevel ) {
@@ -2778,6 +2921,8 @@ abstract class DatabaseBase implements DatabaseType {
* The result is unquoted, and needs to be passed through addQuotes()
* before it can be included in raw SQL.
*
+ * @param $ts string|int
+ *
* @return string
*/
function timestamp( $ts = 0 ) {
@@ -2793,6 +2938,8 @@ abstract class DatabaseBase implements DatabaseType {
* The result is unquoted, and needs to be passed through addQuotes()
* before it can be included in raw SQL.
*
+ * @param $ts string|int
+ *
* @return string
*/
function timestampOrNull( $ts = null ) {
@@ -2813,6 +2960,10 @@ abstract class DatabaseBase implements DatabaseType {
* a wrapper. Nowadays, raw database objects are never exposed to external
* callers, so this is unnecessary in external code. For compatibility with
* old code, ResultWrapper objects are passed through unaltered.
+ *
+ * @param $result bool|ResultWrapper
+ *
+ * @return bool|ResultWrapper
*/
function resultObject( $result ) {
if ( empty( $result ) ) {
@@ -2829,6 +2980,11 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Return aggregated value alias
+ *
+ * @param $valuedata
+ * @param $valuename string
+ *
+ * @return string
*/
function aggregateValue ( $valuedata, $valuename = 'value' ) {
return $valuename;
@@ -2860,7 +3016,7 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Return the maximum number of items allowed in a list, or 0 for unlimited.
*
- * return int
+ * @return int
*/
function maxListLen() {
return 0;
@@ -2871,6 +3027,8 @@ abstract class DatabaseBase implements DatabaseType {
* don't allow simple quoted strings to be inserted. To insert into such
* a field, pass the data through this function before passing it to
* DatabaseBase::insert().
+ * @param $b string
+ * @return string
*/
function encodeBlob( $b ) {
return $b;
@@ -2880,20 +3038,36 @@ abstract class DatabaseBase implements DatabaseType {
* Some DBMSs return a special placeholder object representing blob fields
* in result objects. Pass the object through this function to return the
* original string.
+ * @param $b string
+ * @return string
*/
function decodeBlob( $b ) {
return $b;
}
/**
- * Override database's default connection timeout. May be useful for very
- * long batch queries such as full-wiki dumps, where a single query reads
- * out over hours or days. May or may not be necessary for non-MySQL
- * databases. For most purposes, leaving it as a no-op should be fine.
+ * Override database's default connection timeout
*
* @param $timeout Integer in seconds
+ * @return void
+ * @deprecated since 1.19; use setSessionOptions()
+ */
+ public function setTimeout( $timeout ) {
+ wfDeprecated( __METHOD__, '1.19' );
+ $this->setSessionOptions( array( 'connTimeout' => $timeout ) );
+ }
+
+ /**
+ * Override database's default behavior. $options include:
+ * 'connTimeout' : Set the connection timeout value in seconds.
+ * May be useful for very long batch queries such as
+ * full-wiki dumps, where a single query reads out over
+ * hours or days.
+ *
+ * @param $options Array
+ * @return void
*/
- public function setTimeout( $timeout ) {}
+ public function setSessionOptions( array $options ) {}
/**
* Read and execute SQL commands from a file.
@@ -2906,6 +3080,7 @@ abstract class DatabaseBase implements DatabaseType {
* @param $resultCallback Callback: Optional function called for each MySQL result
* @param $fname String: Calling function name or false if name should be
* generated dynamically using $filename
+ * @return bool|string
*/
function sourceFile( $filename, $lineCallback = false, $resultCallback = false, $fname = false ) {
wfSuppressWarnings();
@@ -2973,56 +3148,42 @@ abstract class DatabaseBase implements DatabaseType {
* @param $lineCallback Callback: Optional function called before reading each line
* @param $resultCallback Callback: Optional function called for each MySQL result
* @param $fname String: Calling function name
+ * @param $inputCallback Callback: Optional function called for each complete line (ended with ;) sent
+ * @return bool|string
*/
- function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
- $fname = 'DatabaseBase::sourceStream' )
+ public function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
+ $fname = 'DatabaseBase::sourceStream', $inputCallback = false )
{
- $cmd = "";
- $done = false;
- $dollarquote = false;
+ $cmd = '';
- while ( ! feof( $fp ) ) {
+ while ( !feof( $fp ) ) {
if ( $lineCallback ) {
call_user_func( $lineCallback );
}
$line = trim( fgets( $fp ) );
- $sl = strlen( $line ) - 1;
- if ( $sl < 0 ) {
+ if ( $line == '' ) {
continue;
}
- if ( '-' == $line { 0 } && '-' == $line { 1 } ) {
+ if ( '-' == $line[0] && '-' == $line[1] ) {
continue;
}
- # # Allow dollar quoting for function declarations
- if ( substr( $line, 0, 4 ) == '$mw$' ) {
- if ( $dollarquote ) {
- $dollarquote = false;
- $done = true;
- }
- else {
- $dollarquote = true;
- }
- }
- elseif ( !$dollarquote ) {
- if ( ';' == $line { $sl } && ( $sl < 2 || ';' != $line { $sl - 1 } ) ) {
- $done = true;
- $line = substr( $line, 0, $sl );
- }
- }
-
if ( $cmd != '' ) {
$cmd .= ' ';
}
+ $done = $this->streamStatementEnd( $cmd, $line );
+
$cmd .= "$line\n";
- if ( $done ) {
- $cmd = str_replace( ';;', ";", $cmd );
+ if ( $done || feof( $fp ) ) {
$cmd = $this->replaceVars( $cmd );
+ if ( $inputCallback ) {
+ call_user_func( $inputCallback, $cmd );
+ }
$res = $this->query( $cmd, $fname );
if ( $resultCallback ) {
@@ -3035,7 +3196,6 @@ abstract class DatabaseBase implements DatabaseType {
}
$cmd = '';
- $done = false;
}
}
@@ -3043,6 +3203,24 @@ abstract class DatabaseBase implements DatabaseType {
}
/**
+ * Called by sourceStream() to check if we've reached a statement end
+ *
+ * @param $sql String SQL assembled so far
+ * @param $newLine String New line about to be added to $sql
+ * @return Bool Whether $newLine contains end of the statement
+ */
+ public function streamStatementEnd( &$sql, &$newLine ) {
+ if ( $this->delimiter ) {
+ $prev = $newLine;
+ $newLine = preg_replace( '/' . preg_quote( $this->delimiter, '/' ) . '$/', '', $newLine );
+ if ( $newLine != $prev ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Database independent variable replacement. Replaces a set of variables
* in an SQL statement with their contents as given by $this->getSchemaVars().
*
@@ -3096,6 +3274,8 @@ abstract class DatabaseBase implements DatabaseType {
/**
* Get schema variables. If none have been set via setSchemaVars(), then
* use some defaults from the current object.
+ *
+ * @return array
*/
protected function getSchemaVars() {
if ( $this->mSchemaVars ) {
@@ -3207,9 +3387,10 @@ abstract class DatabaseBase implements DatabaseType {
* @param $tableName string
* @param $fName string
* @return bool|ResultWrapper
+ * @since 1.18
*/
public function dropTable( $tableName, $fName = 'DatabaseBase::dropTable' ) {
- if( !$this->tableExists( $tableName ) ) {
+ if( !$this->tableExists( $tableName, $fName ) ) {
return false;
}
$sql = "DROP TABLE " . $this->tableName( $tableName );
diff --git a/includes/db/DatabaseError.php b/includes/db/DatabaseError.php
index b7fb1b22..836d7814 100644
--- a/includes/db/DatabaseError.php
+++ b/includes/db/DatabaseError.php
@@ -82,11 +82,19 @@ class DBConnectionError extends DBError {
parent::__construct( $db, $msg );
}
+ /**
+ * @return bool
+ */
function useOutputPage() {
// Not likely to work
return false;
}
+ /**
+ * @param $key
+ * @param $fallback
+ * @return string
+ */
function msg( $key, $fallback /*[, params...] */ ) {
global $wgLang;
@@ -100,6 +108,9 @@ class DBConnectionError extends DBError {
return wfMsgReplaceArgs( $message, $args );
}
+ /**
+ * @return bool
+ */
function getLogMessage() {
# Don't send to the exception log
return false;
@@ -171,7 +182,7 @@ class DBConnectionError extends DBError {
}
# We can't, cough and die in the usual fashion
- return parent::reportHTML();
+ parent::reportHTML();
}
/**
@@ -193,7 +204,7 @@ class DBConnectionError extends DBError {
<div style="margin: 1.5em">$usegoogle<br />
<small>$outofdate</small></div>
<!-- SiteSearch Google -->
-<form method="get" action="http://www.google.com/search" id="googlesearch">
+<form method="get" action="//www.google.com/search" id="googlesearch">
<input type="hidden" name="domains" value="$server" />
<input type="hidden" name="num" value="50" />
<input type="hidden" name="ie" value="UTF-8" />
@@ -215,21 +226,28 @@ EOT;
* @return string
*/
private function fileCachedPage() {
- global $wgTitle, $wgOut;
+ global $wgTitle, $wgOut, $wgRequest;
if ( $wgOut->isDisabled() ) {
- return; // Done already?
+ return ''; // Done already?
}
- if ( $wgTitle ) {
- $t =& $wgTitle;
+ if ( $wgTitle ) { // use $wgTitle if we managed to set it
+ $t = $wgTitle->getPrefixedDBkey();
} else {
- $t = Title::newFromText( $this->msg( 'mainpage', 'Main Page' ) );
+ # Fallback to the raw title URL param. We can't use the Title
+ # class is it may hit the interwiki table and give a DB error.
+ # We may get a cache miss due to not sanitizing the title though.
+ $t = str_replace( ' ', '_', $wgRequest->getVal( 'title' ) );
+ if ( $t == '' ) { // fallback to main page
+ $t = Title::newFromText(
+ $this->msg( 'mainpage', 'Main Page' ) )->getPrefixedDBkey();
+ }
}
- $cache = new HTMLFileCache( $t );
- if ( $cache->isFileCached() ) {
- return $cache->fetchPageText();
+ $cache = HTMLFileCache::newFromTitle( $t, 'view' );
+ if ( $cache->isCached() ) {
+ return $cache->fetchText();
} else {
return '';
}
@@ -242,15 +260,18 @@ EOT;
class DBQueryError extends DBError {
public $error, $errno, $sql, $fname;
+ /**
+ * @param $db DatabaseBase
+ * @param $error string
+ * @param $errno int|string
+ * @param $sql string
+ * @param $fname string
+ */
function __construct( DatabaseBase &$db, $error, $errno, $sql, $fname ) {
- $message = "A database error has occurred. Did you forget to run maintenance/update.php after upgrading? See: http://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" .
+ $message = "A database error has occurred. Did you forget to run maintenance/update.php after upgrading? See: https://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" .
"Query: $sql\n" .
"Function: $fname\n" .
"Error: $errno $error\n";
- global $wgShowDBErrorBacktrace;
- if( $wgShowDBErrorBacktrace ) {
- $message .= $this->getTraceAsString();
- }
parent::__construct( $db, $message );
$this->error = $error;
@@ -295,6 +316,9 @@ class DBQueryError extends DBError {
}
}
+ /**
+ * @return bool
+ */
function getLogMessage() {
# Don't send to the exception log
return false;
diff --git a/includes/db/DatabaseIbm_db2.php b/includes/db/DatabaseIbm_db2.php
index 147b9d59..fed3b12e 100644
--- a/includes/db/DatabaseIbm_db2.php
+++ b/includes/db/DatabaseIbm_db2.php
@@ -104,6 +104,147 @@ class IBM_DB2Blob {
}
/**
+ * Wrapper to address lack of certain operations in the DB2 driver
+ * ( seek, num_rows )
+ * @ingroup Database
+ * @since 1.19
+ */
+class IBM_DB2Result{
+ private $db;
+ private $result;
+ private $num_rows;
+ private $current_pos;
+ private $columns = array();
+ private $sql;
+
+ private $resultSet = array();
+ private $loadedLines = 0;
+
+ /**
+ * Construct and initialize a wrapper for DB2 query results
+ * @param $db Database
+ * @param $result Object
+ * @param $num_rows Integer
+ * @param $sql String
+ * @param $columns Array
+ */
+ public function __construct( $db, $result, $num_rows, $sql, $columns ){
+ $this->db = $db;
+
+ if( $result instanceof ResultWrapper ){
+ $this->result = $result->result;
+ }
+ else{
+ $this->result = $result;
+ }
+
+ $this->num_rows = $num_rows;
+ $this->current_pos = 0;
+ if ( $this->num_rows > 0 ) {
+ // Make a lower-case list of the column names
+ // By default, DB2 column names are capitalized
+ // while MySQL column names are lowercase
+
+ // Is there a reasonable maximum value for $i?
+ // Setting to 2048 to prevent an infinite loop
+ for( $i = 0; $i < 2048; $i++ ) {
+ $name = db2_field_name( $this->result, $i );
+ if ( $name != false ) {
+ continue;
+ }
+ else {
+ return false;
+ }
+
+ $this->columns[$i] = strtolower( $name );
+ }
+ }
+
+ $this->sql = $sql;
+ }
+
+ /**
+ * Unwrap the DB2 query results
+ * @return mixed Object on success, false on failure
+ */
+ public function getResult() {
+ if ( $this->result ) {
+ return $this->result;
+ }
+ else return false;
+ }
+
+ /**
+ * Get the number of rows in the result set
+ * @return integer
+ */
+ public function getNum_rows() {
+ return $this->num_rows;
+ }
+
+ /**
+ * Return a row from the result set in object format
+ * @return mixed Object on success, false on failure.
+ */
+ public function fetchObject() {
+ if ( $this->result
+ && $this->num_rows > 0
+ && $this->current_pos >= 0
+ && $this->current_pos < $this->num_rows )
+ {
+ $row = $this->fetchRow();
+ $ret = new stdClass();
+
+ foreach ( $row as $k => $v ) {
+ $lc = $this->columns[$k];
+ $ret->$lc = $v;
+ }
+ return $ret;
+ }
+ return false;
+ }
+
+ /**
+ * Return a row form the result set in array format
+ * @return mixed Array on success, false on failure
+ * @throws DBUnexpectedError
+ */
+ public function fetchRow(){
+ if ( $this->result
+ && $this->num_rows > 0
+ && $this->current_pos >= 0
+ && $this->current_pos < $this->num_rows )
+ {
+ if ( $this->loadedLines <= $this->current_pos ) {
+ $row = db2_fetch_array( $this->result );
+ $this->resultSet[$this->loadedLines++] = $row;
+ if ( $this->db->lastErrno() ) {
+ throw new DBUnexpectedError( $this->db, 'Error in fetchRow(): '
+ . htmlspecialchars( $this->db->lastError() ) );
+ }
+ }
+
+ if ( $this->loadedLines > $this->current_pos ){
+ return $this->resultSet[$this->current_pos++];
+ }
+
+ }
+ return false;
+ }
+
+ /**
+ * Free a DB2 result object
+ * @throws DBUnexpectedError
+ */
+ public function freeResult(){
+ unset( $this->resultSet );
+ if ( !@db2_free_result( $this->result ) ) {
+ throw new DBUnexpectedError( $this, "Unable to free DB2 result\n" );
+ }
+ }
+}
+
+/**
* Primary database interface
* @ingroup Database
*/
@@ -137,6 +278,8 @@ class DatabaseIbm_db2 extends DatabaseBase {
protected $mAffectedRows = null;
/** Number of rows returned by last SELECT */
protected $mNumRows = null;
+ /** Current row number on the cursor of the last SELECT */
+ protected $currentRow = 0;
/** Connection config options - see constructor */
public $mConnOptions = array();
@@ -233,7 +376,7 @@ class DatabaseIbm_db2 extends DatabaseBase {
/**
* Returns a unique string representing the wiki on the server
*/
- function getWikiID() {
+ public function getWikiID() {
if( $this->mSchema ) {
return "{$this->mDBname}-{$this->mSchema}";
} else {
@@ -241,10 +384,22 @@ class DatabaseIbm_db2 extends DatabaseBase {
}
}
- function getType() {
+ /**
+ * Returns the database software identifieir
+ * @return string
+ */
+ public function getType() {
return 'ibm_db2';
}
+ /**
+ * Returns the database connection object
+ * @return Object
+ */
+ public function getDb(){
+ return $this->mConn;
+ }
+
/**
*
* @param $server String: hostname of database server
@@ -268,17 +423,12 @@ class DatabaseIbm_db2 extends DatabaseBase {
}
// configure the connection and statement objects
- /*
- $this->setDB2Option( 'cursor', 'DB2_SCROLLABLE',
- self::CONN_OPTION | self::STMT_OPTION );
- */
$this->setDB2Option( 'db2_attr_case', 'DB2_CASE_LOWER',
self::CONN_OPTION | self::STMT_OPTION );
$this->setDB2Option( 'deferred_prepare', 'DB2_DEFERRED_PREPARE_ON',
self::STMT_OPTION );
$this->setDB2Option( 'rowcount', 'DB2_ROWCOUNT_PREFETCH_ON',
self::STMT_OPTION );
-
parent::__construct( $server, $user, $password, $dbName, DBO_TRX | $flags );
}
@@ -361,8 +511,6 @@ class DatabaseIbm_db2 extends DatabaseBase {
throw new DBConnectionError( $this, $this->lastError() );
}
- // Apply connection config
- db2_set_option( $this->mConn, $this->mConnOptions, 1 );
// Some MediaWiki code is still transaction-less (?).
// The strategy is to keep AutoCommit on for that code
// but switch it off whenever a transaction is begun.
@@ -391,7 +539,7 @@ class DatabaseIbm_db2 extends DatabaseBase {
{
$dsn = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=$dbName;CHARSET=UTF-8;HOSTNAME=$server;PORT=$port;PROTOCOL=TCPIP;UID=$user;PWD=$password;";
wfSuppressWarnings();
- $this->mConn = db2_pconnect($dsn, "", "", array());
+ $this->mConn = db2_pconnect( $dsn, "", "", array() );
wfRestoreWarnings();
}
@@ -460,16 +608,16 @@ class DatabaseIbm_db2 extends DatabaseBase {
*/
protected function doQuery( $sql ) {
$this->applySchema();
-
+
// Needed to handle any UTF-8 encoding issues in the raw sql
// Note that we fully support prepared statements for DB2
// prepare() and execute() should be used instead of doQuery() whenever possible
- $sql = utf8_decode($sql);
-
+ $sql = utf8_decode( $sql );
+
$ret = db2_exec( $this->mConn, $sql, $this->mStmtOptions );
if( $ret == false ) {
$error = db2_stmt_errormsg();
-
+
$this->installPrint( "<pre>$sql</pre>" );
$this->installPrint( $error );
throw new DBUnexpectedError( $this, 'SQL error: '
@@ -492,10 +640,10 @@ class DatabaseIbm_db2 extends DatabaseBase {
* Queries whether a given table exists
* @return boolean
*/
- public function tableExists( $table ) {
+ public function tableExists( $table, $fname = __METHOD__ ) {
$schema = $this->mSchema;
-
- $sql = "SELECT COUNT( * ) FROM SYSIBM.SYSTABLES ST WHERE ST.NAME = '" .
+
+ $sql = "SELECT COUNT( * ) FROM SYSIBM.SYSTABLES ST WHERE ST.NAME = '" .
strtoupper( $table ) .
"' AND ST.CREATOR = '" .
strtoupper( $schema ) . "'";
@@ -745,10 +893,10 @@ class DatabaseIbm_db2 extends DatabaseBase {
* Handle reserved keyword replacement in table names
*
* @param $name Object
- * @param $name Boolean
+ * @param $format String Ignored parameter Default 'quoted'Boolean
* @return String
*/
- public function tableName( $name, $quoted = true ) {
+ public function tableName( $name, $format = 'quoted' ) {
// we want maximum compatibility with MySQL schema
return $name;
}
@@ -939,14 +1087,14 @@ class DatabaseIbm_db2 extends DatabaseBase {
*/
private function removeNullPrimaryKeys( $table, $args ) {
$schema = $this->mSchema;
-
+
// find out the primary keys
- $keyres = $this->doQuery( "SELECT NAME FROM SYSIBM.SYSCOLUMNS WHERE TBNAME = '"
- . strtoupper( $table )
- . "' AND TBCREATOR = '"
- . strtoupper( $schema )
+ $keyres = $this->doQuery( "SELECT NAME FROM SYSIBM.SYSCOLUMNS WHERE TBNAME = '"
+ . strtoupper( $table )
+ . "' AND TBCREATOR = '"
+ . strtoupper( $schema )
. "' AND KEYSEQ > 0" );
-
+
$keys = array();
for (
$row = $this->fetchRow( $keyres );
@@ -1046,7 +1194,7 @@ class DatabaseIbm_db2 extends DatabaseBase {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
-
+
if ( $this->mNumRows ) {
return $this->mNumRows;
} else {
@@ -1062,9 +1210,13 @@ class DatabaseIbm_db2 extends DatabaseBase {
*/
public function dataSeek( $res, $row ) {
if ( $res instanceof ResultWrapper ) {
- $res = $res->result;
+ return $res = $res->result;
+ }
+ if ( $res instanceof IBM_DB2Result ) {
+ return $res->dataSeek( $row );
}
- return db2_fetch_row( $res, $row );
+ wfDebug( "dataSeek operation in DB2 database\n" );
+ return false;
}
###
@@ -1097,6 +1249,9 @@ class DatabaseIbm_db2 extends DatabaseBase {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
+ if ( $res instanceof IBM_DB2Result ) {
+ $res = $res->getResult();
+ }
return db2_num_fields( $res );
}
@@ -1110,6 +1265,9 @@ class DatabaseIbm_db2 extends DatabaseBase {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
+ if ( $res instanceof IBM_DB2Result ) {
+ $res = $res->getResult();
+ }
return db2_field_name( $res, $n );
}
@@ -1122,7 +1280,7 @@ class DatabaseIbm_db2 extends DatabaseBase {
* @param $fname String: calling function name (use __METHOD__)
* for logs/profiling
* @param $options Associative array of options
- * (e.g. array('GROUP BY' => 'page_title')),
+ * (e.g. array( 'GROUP BY' => 'page_title' )),
* see Database::makeSelectOptions code for list of
* supported stuff
* @param $join_conds Associative array of table join conditions (optional)
@@ -1135,6 +1293,7 @@ class DatabaseIbm_db2 extends DatabaseBase {
{
$res = parent::select( $table, $vars, $conds, $fname, $options,
$join_conds );
+ $sql = $this->selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
// We must adjust for offset
if ( isset( $options['LIMIT'] ) && isset ( $options['OFFSET'] ) ) {
@@ -1161,10 +1320,11 @@ class DatabaseIbm_db2 extends DatabaseBase {
$res2 = parent::select( $table, $vars2, $conds, $fname, $options2,
$join_conds );
+
$obj = $this->fetchObject( $res2 );
$this->mNumRows = $obj->num_rows;
-
- return $res;
+
+ return new ResultWrapper( $this, new IBM_DB2Result( $this, $res, $obj->num_rows, $vars, $sql ) );
}
/**
@@ -1332,6 +1492,9 @@ SQL;
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
+ if ( $res instanceof IBM_DB2Result ) {
+ $res = $res->getResult();
+ }
return db2_field_type( $res, $index );
}
diff --git a/includes/db/DatabaseMssql.php b/includes/db/DatabaseMssql.php
index cbdf89ca..38be4cbb 100644
--- a/includes/db/DatabaseMssql.php
+++ b/includes/db/DatabaseMssql.php
@@ -631,7 +631,7 @@ class DatabaseMssql extends DatabaseBase {
return $version;
}
- function tableExists ( $table, $schema = false ) {
+ function tableExists ( $table, $fname = __METHOD__, $schema = false ) {
$res = sqlsrv_query( $this->mConn, "SELECT * FROM information_schema.tables
WHERE table_type='BASE TABLE' AND table_name = '$table'" );
if ( $res === false ) {
diff --git a/includes/db/DatabaseMysql.php b/includes/db/DatabaseMysql.php
index 6a81f234..c179b724 100644
--- a/includes/db/DatabaseMysql.php
+++ b/includes/db/DatabaseMysql.php
@@ -14,10 +14,18 @@
* @see Database
*/
class DatabaseMysql extends DatabaseBase {
+
+ /**
+ * @return string
+ */
function getType() {
return 'mysql';
}
+ /**
+ * @param $sql string
+ * @return resource
+ */
protected function doQuery( $sql ) {
if( $this->bufferResults() ) {
$ret = mysql_query( $sql, $this->mConn );
@@ -27,6 +35,14 @@ class DatabaseMysql extends DatabaseBase {
return $ret;
}
+ /**
+ * @param $server string
+ * @param $user string
+ * @param $password string
+ * @param $dbName string
+ * @return bool
+ * @throws DBConnectionError
+ */
function open( $server, $user, $password, $dbName ) {
global $wgAllDBsAreLocalhost;
wfProfileIn( __METHOD__ );
@@ -110,22 +126,19 @@ class DatabaseMysql extends DatabaseBase {
}
if ( $success ) {
- $version = $this->getServerVersion();
- if ( version_compare( $version, '4.1' ) >= 0 ) {
- // Tell the server we're communicating with it in UTF-8.
- // This may engage various charset conversions.
- global $wgDBmysql5;
- if( $wgDBmysql5 ) {
- $this->query( 'SET NAMES utf8', __METHOD__ );
- } else {
- $this->query( 'SET NAMES binary', __METHOD__ );
- }
- // Set SQL mode, default is turning them all off, can be overridden or skipped with null
- global $wgSQLMode;
- if ( is_string( $wgSQLMode ) ) {
- $mode = $this->addQuotes( $wgSQLMode );
- $this->query( "SET sql_mode = $mode", __METHOD__ );
- }
+ // Tell the server we're communicating with it in UTF-8.
+ // This may engage various charset conversions.
+ global $wgDBmysql5;
+ if( $wgDBmysql5 ) {
+ $this->query( 'SET NAMES utf8', __METHOD__ );
+ } else {
+ $this->query( 'SET NAMES binary', __METHOD__ );
+ }
+ // Set SQL mode, default is turning them all off, can be overridden or skipped with null
+ global $wgSQLMode;
+ if ( is_string( $wgSQLMode ) ) {
+ $mode = $this->addQuotes( $wgSQLMode );
+ $this->query( "SET sql_mode = $mode", __METHOD__ );
}
// Turn off strict mode if it is on
@@ -138,6 +151,9 @@ class DatabaseMysql extends DatabaseBase {
return $success;
}
+ /**
+ * @return bool
+ */
function close() {
$this->mOpened = false;
if ( $this->mConn ) {
@@ -150,6 +166,10 @@ class DatabaseMysql extends DatabaseBase {
}
}
+ /**
+ * @param $res ResultWrapper
+ * @throws DBUnexpectedError
+ */
function freeResult( $res ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
@@ -162,6 +182,11 @@ class DatabaseMysql extends DatabaseBase {
}
}
+ /**
+ * @param $res ResultWrapper
+ * @return object|stdClass
+ * @throws DBUnexpectedError
+ */
function fetchObject( $res ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
@@ -175,7 +200,12 @@ class DatabaseMysql extends DatabaseBase {
return $row;
}
- function fetchRow( $res ) {
+ /**
+ * @param $res ResultWrapper
+ * @return array
+ * @throws DBUnexpectedError
+ */
+ function fetchRow( $res ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
@@ -188,6 +218,11 @@ class DatabaseMysql extends DatabaseBase {
return $row;
}
+ /**
+ * @throws DBUnexpectedError
+ * @param $res ResultWrapper
+ * @return int
+ */
function numRows( $res ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
@@ -201,6 +236,10 @@ class DatabaseMysql extends DatabaseBase {
return $n;
}
+ /**
+ * @param $res ResultWrapper
+ * @return int
+ */
function numFields( $res ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
@@ -208,6 +247,11 @@ class DatabaseMysql extends DatabaseBase {
return mysql_num_fields( $res );
}
+ /**
+ * @param $res ResultWrapper
+ * @param $n string
+ * @return string
+ */
function fieldName( $res, $n ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
@@ -215,8 +259,18 @@ class DatabaseMysql extends DatabaseBase {
return mysql_field_name( $res, $n );
}
- function insertId() { return mysql_insert_id( $this->mConn ); }
+ /**
+ * @return int
+ */
+ function insertId() {
+ return mysql_insert_id( $this->mConn );
+ }
+ /**
+ * @param $res ResultWrapper
+ * @param $row
+ * @return bool
+ */
function dataSeek( $res, $row ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
@@ -224,6 +278,9 @@ class DatabaseMysql extends DatabaseBase {
return mysql_data_seek( $res, $row );
}
+ /**
+ * @return int
+ */
function lastErrno() {
if ( $this->mConn ) {
return mysql_errno( $this->mConn );
@@ -232,6 +289,9 @@ class DatabaseMysql extends DatabaseBase {
}
}
+ /**
+ * @return string
+ */
function lastError() {
if ( $this->mConn ) {
# Even if it's non-zero, it can still be invalid
@@ -250,8 +310,20 @@ class DatabaseMysql extends DatabaseBase {
return $error;
}
- function affectedRows() { return mysql_affected_rows( $this->mConn ); }
+ /**
+ * @return int
+ */
+ function affectedRows() {
+ return mysql_affected_rows( $this->mConn );
+ }
+ /**
+ * @param $table string
+ * @param $uniqueIndexes
+ * @param $rows array
+ * @param $fname string
+ * @return ResultWrapper
+ */
function replace( $table, $uniqueIndexes, $rows, $fname = 'DatabaseMysql::replace' ) {
return $this->nativeReplace( $table, $rows, $fname );
}
@@ -260,6 +332,13 @@ class DatabaseMysql extends DatabaseBase {
* Estimate rows in dataset
* Returns estimated count, based on EXPLAIN output
* Takes same arguments as Database::select()
+ *
+ * @param $table string|array
+ * @param $vars string|array
+ * @param $conds string|array
+ * @param $fname string
+ * @param $options string|array
+ * @return int
*/
public function estimateRowCount( $table, $vars='*', $conds='', $fname = 'DatabaseMysql::estimateRowCount', $options = array() ) {
$options['EXPLAIN'] = true;
@@ -278,6 +357,11 @@ class DatabaseMysql extends DatabaseBase {
return $rows;
}
+ /**
+ * @param $table string
+ * @param $field string
+ * @return bool|MySQLField
+ */
function fieldInfo( $table, $field ) {
$table = $this->tableName( $table );
$res = $this->query( "SELECT * FROM $table LIMIT 1", __METHOD__, true );
@@ -297,6 +381,11 @@ class DatabaseMysql extends DatabaseBase {
/**
* Get information about an index into an object
* Returns false if the index does not exist
+ *
+ * @param $table string
+ * @param $index string
+ * @param $fname string
+ * @return false|array
*/
function indexInfo( $table, $index, $fname = 'DatabaseMysql::indexInfo' ) {
# SHOW INDEX works in MySQL 3.23.58, but SHOW INDEXES does not.
@@ -322,11 +411,20 @@ class DatabaseMysql extends DatabaseBase {
return empty( $result ) ? false : $result;
}
+ /**
+ * @param $db
+ * @return bool
+ */
function selectDB( $db ) {
$this->mDBname = $db;
return mysql_select_db( $db, $this->mConn );
}
+ /**
+ * @param $s string
+ *
+ * @return string
+ */
function strencode( $s ) {
$sQuoted = mysql_real_escape_string( $s, $this->mConn );
@@ -339,15 +437,26 @@ class DatabaseMysql extends DatabaseBase {
/**
* MySQL uses `backticks` for identifier quoting instead of the sql standard "double quotes".
+ *
+ * @param $s string
+ *
+ * @return string
*/
public function addIdentifierQuotes( $s ) {
return "`" . $this->strencode( $s ) . "`";
}
+ /**
+ * @param $name string
+ * @return bool
+ */
public function isQuotedIdentifier( $name ) {
- return strlen($name) && $name[0] == '`' && substr( $name, -1, 1 ) == '`';
+ return strlen( $name ) && $name[0] == '`' && substr( $name, -1, 1 ) == '`';
}
+ /**
+ * @return bool
+ */
function ping() {
$ping = mysql_ping( $this->mConn );
if ( $ping ) {
@@ -364,11 +473,9 @@ class DatabaseMysql extends DatabaseBase {
/**
* Returns slave lag.
*
- * On MySQL 4.1.9 and later, this will do a SHOW SLAVE STATUS. On earlier
- * versions of MySQL, it uses SHOW PROCESSLIST, which requires the PROCESS
- * privilege.
+ * This will do a SHOW SLAVE STATUS
*
- * @result int
+ * @return int
*/
function getLag() {
if ( !is_null( $this->mFakeSlaveLag ) ) {
@@ -376,13 +483,12 @@ class DatabaseMysql extends DatabaseBase {
return $this->mFakeSlaveLag;
}
- if ( version_compare( $this->getServerVersion(), '4.1.9', '>=' ) ) {
- return $this->getLagFromSlaveStatus();
- } else {
- return $this->getLagFromProcesslist();
- }
+ return $this->getLagFromSlaveStatus();
}
+ /**
+ * @return bool|int
+ */
function getLagFromSlaveStatus() {
$res = $this->query( 'SHOW SLAVE STATUS', __METHOD__ );
if ( !$res ) {
@@ -399,7 +505,13 @@ class DatabaseMysql extends DatabaseBase {
}
}
+ /**
+ * @deprecated in 1.19, use getLagFromSlaveStatus
+ *
+ * @return bool|int
+ */
function getLagFromProcesslist() {
+ wfDeprecated( __METHOD__, '1.19' );
$res = $this->query( 'SHOW PROCESSLIST', __METHOD__ );
if( !$res ) {
return false;
@@ -432,12 +544,13 @@ class DatabaseMysql extends DatabaseBase {
}
return false;
}
-
+
/**
* Wait for the slave to catch up to a given master position.
*
* @param $pos DBMasterPos object
* @param $timeout Integer: the maximum number of seconds to wait for synchronisation
+ * @return bool|string
*/
function masterPosWait( DBMasterPos $pos, $timeout ) {
$fname = 'DatabaseBase::masterPosWait';
@@ -510,31 +623,68 @@ class DatabaseMysql extends DatabaseBase {
}
}
+ /**
+ * @return string
+ */
function getServerVersion() {
return mysql_get_server_info( $this->mConn );
}
+ /**
+ * @param $index
+ * @return string
+ */
function useIndexClause( $index ) {
return "FORCE INDEX (" . $this->indexName( $index ) . ")";
}
+ /**
+ * @return string
+ */
function lowPriorityOption() {
return 'LOW_PRIORITY';
}
+ /**
+ * @return string
+ */
public static function getSoftwareLink() {
return '[http://www.mysql.com/ MySQL]';
}
+ /**
+ * @return bool
+ */
function standardSelectDistinct() {
return false;
}
- public function setTimeout( $timeout ) {
- $this->query( "SET net_read_timeout=$timeout" );
- $this->query( "SET net_write_timeout=$timeout" );
+ /**
+ * @param $options array
+ */
+ public function setSessionOptions( array $options ) {
+ if ( isset( $options['connTimeout'] ) ) {
+ $timeout = (int)$options['connTimeout'];
+ $this->query( "SET net_read_timeout=$timeout" );
+ $this->query( "SET net_write_timeout=$timeout" );
+ }
}
+ public function streamStatementEnd( &$sql, &$newLine ) {
+ if ( strtoupper( substr( $newLine, 0, 9 ) ) == 'DELIMITER' ) {
+ preg_match( '/^DELIMITER\s+(\S+)/' , $newLine, $m );
+ $this->delimiter = $m[1];
+ $newLine = '';
+ }
+ return parent::streamStatementEnd( $sql, $newLine );
+ }
+
+ /**
+ * @param $lockName string
+ * @param $method string
+ * @param $timeout int
+ * @return bool
+ */
public function lock( $lockName, $method, $timeout = 5 ) {
$lockName = $this->addQuotes( $lockName );
$result = $this->query( "SELECT GET_LOCK($lockName, $timeout) AS lockstatus", $method );
@@ -550,6 +700,9 @@ class DatabaseMysql extends DatabaseBase {
/**
* FROM MYSQL DOCS: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock
+ * @param $lockName string
+ * @param $method string
+ * @return bool
*/
public function unlock( $lockName, $method ) {
$lockName = $this->addQuotes( $lockName );
@@ -558,6 +711,12 @@ class DatabaseMysql extends DatabaseBase {
return $row->lockstatus;
}
+ /**
+ * @param $read array
+ * @param $write array
+ * @param $method string
+ * @param $lowPriority bool
+ */
public function lockTables( $read, $write, $method, $lowPriority = true ) {
$items = array();
@@ -574,6 +733,9 @@ class DatabaseMysql extends DatabaseBase {
$this->query( $sql, $method );
}
+ /**
+ * @param $method string
+ */
public function unlockTables( $method ) {
$this->query( "UNLOCK TABLES", $method );
}
@@ -588,6 +750,10 @@ class DatabaseMysql extends DatabaseBase {
return 'SearchMySQL';
}
+ /**
+ * @param bool $value
+ * @return mixed
+ */
public function setBigSelects( $value = true ) {
if ( $value === 'default' ) {
if ( $this->mDefaultBigSelects === null ) {
@@ -605,6 +771,13 @@ class DatabaseMysql extends DatabaseBase {
/**
* DELETE where the condition is a join. MySql uses multi-table deletes.
+ * @param $delTable string
+ * @param $joinTable string
+ * @param $delVar string
+ * @param $joinVar string
+ * @param $conds array|string
+ * @param $fname bool
+ * @return bool|ResultWrapper
*/
function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = 'DatabaseBase::deleteJoin' ) {
if ( !$conds ) {
@@ -623,15 +796,38 @@ class DatabaseMysql extends DatabaseBase {
}
/**
+ * Determines how long the server has been up
+ *
+ * @return int
+ */
+ function getServerUptime() {
+ $vars = $this->getMysqlStatus( 'Uptime' );
+ return (int)$vars['Uptime'];
+ }
+
+ /**
* Determines if the last failure was due to a deadlock
+ *
+ * @return bool
*/
function wasDeadlock() {
return $this->lastErrno() == 1213;
}
/**
+ * Determines if the last failure was due to a lock timeout
+ *
+ * @return bool
+ */
+ function wasLockTimeout() {
+ return $this->lastErrno() == 1205;
+ }
+
+ /**
* Determines if the last query error was something that should be dealt
* with by pinging the connection and reissuing the query
+ *
+ * @return bool
*/
function wasErrorReissuable() {
return $this->lastErrno() == 2013 || $this->lastErrno() == 2006;
@@ -639,45 +835,34 @@ class DatabaseMysql extends DatabaseBase {
/**
* Determines if the last failure was due to the database being read-only.
+ *
+ * @return bool
*/
function wasReadOnlyError() {
return $this->lastErrno() == 1223 ||
( $this->lastErrno() == 1290 && strpos( $this->lastError(), '--read-only' ) !== false );
}
+ /**
+ * @param $oldName
+ * @param $newName
+ * @param $temporary bool
+ * @param $fname string
+ */
function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseMysql::duplicateTableStructure' ) {
$tmp = $temporary ? 'TEMPORARY ' : '';
- if ( strcmp( $this->getServerVersion(), '4.1' ) < 0 ) {
- # Hack for MySQL versions < 4.1, which don't support
- # "CREATE TABLE ... LIKE". Note that
- # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0"
- # would not create the indexes we need....
- #
- # Note that we don't bother changing around the prefixes here be-
- # cause we know we're using MySQL anyway.
-
- $res = $this->query( 'SHOW CREATE TABLE ' . $this->addIdentifierQuotes( $oldName ) );
- $row = $this->fetchRow( $res );
- $oldQuery = $row[1];
- $query = preg_replace( '/CREATE TABLE `(.*?)`/',
- "CREATE $tmp TABLE " . $this->addIdentifierQuotes( $newName ), $oldQuery );
- if ($oldQuery === $query) {
- # Couldn't do replacement
- throw new MWException( "could not create temporary table $newName" );
- }
- } else {
- $newName = $this->addIdentifierQuotes( $newName );
- $oldName = $this->addIdentifierQuotes( $oldName );
- $query = "CREATE $tmp TABLE $newName (LIKE $oldName)";
- }
+ $newName = $this->addIdentifierQuotes( $newName );
+ $oldName = $this->addIdentifierQuotes( $oldName );
+ $query = "CREATE $tmp TABLE $newName (LIKE $oldName)";
$this->query( $query, $fname );
}
-
+
/**
* List all tables on the database
*
* @param $prefix Only show tables with this prefix, e.g. mw_
* @param $fname String: calling function name
+ * @return array
*/
function listTables( $prefix = null, $fname = 'DatabaseMysql::listTables' ) {
$result = $this->query( "SHOW TABLES", $fname);
@@ -692,12 +877,17 @@ class DatabaseMysql extends DatabaseBase {
$endArray[] = $table;
}
}
-
+
return $endArray;
}
+ /**
+ * @param $tableName
+ * @param $fName string
+ * @return bool|ResultWrapper
+ */
public function dropTable( $tableName, $fName = 'DatabaseMysql::dropTable' ) {
- if( !$this->tableExists( $tableName ) ) {
+ if( !$this->tableExists( $tableName, $fName ) ) {
return false;
}
return $this->query( "DROP TABLE IF EXISTS " . $this->tableName( $tableName ), $fName );
@@ -716,6 +906,7 @@ class DatabaseMysql extends DatabaseBase {
/**
* Get status information from SHOW STATUS in an associative array
*
+ * @param $which string
* @return array
*/
function getMysqlStatus( $which = "%" ) {
@@ -733,6 +924,8 @@ class DatabaseMysql extends DatabaseBase {
/**
* Legacy support: Database == DatabaseMysql
+ *
+ * @deprecated in 1.16
*/
class Database extends DatabaseMysql {}
@@ -757,18 +950,30 @@ class MySQLField implements Field {
$this->type = $info->type;
}
+ /**
+ * @return string
+ */
function name() {
return $this->name;
}
+ /**
+ * @return string
+ */
function tableName() {
return $this->tableName;
}
+ /**
+ * @return string
+ */
function type() {
return $this->type;
}
+ /**
+ * @return bool
+ */
function isNullable() {
return $this->nullable;
}
@@ -777,10 +982,16 @@ class MySQLField implements Field {
return $this->default;
}
+ /**
+ * @return bool
+ */
function isKey() {
return $this->is_key;
}
+ /**
+ * @return bool
+ */
function isMultipleKey() {
return $this->is_multiple;
}
diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php
index 9d51cf07..855fc831 100644
--- a/includes/db/DatabaseOracle.php
+++ b/includes/db/DatabaseOracle.php
@@ -548,8 +548,9 @@ class DatabaseOracle extends DatabaseBase {
$val = $val->fetch();
}
+ // backward compatibility
if ( preg_match( '/^timestamp.*/i', $col_type ) == 1 && strtolower( $val ) == 'infinity' ) {
- $val = '31-12-2030 12:00:00.000000';
+ $val = $this->getInfinity();
}
$val = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
@@ -654,7 +655,7 @@ class DatabaseOracle extends DatabaseBase {
return $retval;
}
- function tableName( $name, $quoted = true ) {
+ function tableName( $name, $format = 'quoted' ) {
/*
Replace reserved words with better ones
Using uppercase because that's the only way Oracle can handle
@@ -669,7 +670,7 @@ class DatabaseOracle extends DatabaseBase {
break;
}
- return parent::tableName( strtoupper( $name ), $quoted );
+ return parent::tableName( strtoupper( $name ), $format );
}
function tableNameInternal( $name ) {
@@ -768,9 +769,9 @@ class DatabaseOracle extends DatabaseBase {
// dirty code ... i know
$endArray = array();
- $endArray[] = $prefix.'MWUSER';
- $endArray[] = $prefix.'PAGE';
- $endArray[] = $prefix.'IMAGE';
+ $endArray[] = strtoupper($prefix.'MWUSER');
+ $endArray[] = strtoupper($prefix.'PAGE');
+ $endArray[] = strtoupper($prefix.'IMAGE');
$fixedOrderTabs = $endArray;
while (($row = $result->fetchRow()) !== false) {
if (!in_array($row['table_name'], $fixedOrderTabs))
@@ -855,7 +856,7 @@ class DatabaseOracle extends DatabaseBase {
/**
* Query whether a given table exists (in the given schema, or the default mw one if not given)
*/
- function tableExists( $table ) {
+ function tableExists( $table, $fname = __METHOD__ ) {
$table = $this->tableName( $table );
$table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
$owner = $this->addQuotes( strtoupper( $this->mDBname ) );
@@ -969,7 +970,8 @@ class DatabaseOracle extends DatabaseBase {
}
/* defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}'; */
- function sourceStream( $fp, $lineCallback = false, $resultCallback = false, $fname = 'DatabaseOracle::sourceStream' ) {
+ function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
+ $fname = 'DatabaseOracle::sourceStream', $inputCallback = false ) {
$cmd = '';
$done = false;
$dollarquote = false;
@@ -1023,6 +1025,9 @@ class DatabaseOracle extends DatabaseBase {
}
$cmd = $this->replaceVars( $cmd );
+ if ( $inputCallback ) {
+ call_user_func( $inputCallback, $cmd );
+ }
$res = $this->doQuery( $cmd );
if ( $resultCallback ) {
call_user_func( $resultCallback, $res, $this );
@@ -1210,7 +1215,7 @@ class DatabaseOracle extends DatabaseBase {
$sql .= $sqlSet;
}
- if ( $conds != '*' ) {
+ if ( $conds !== array() && $conds !== '*' ) {
$conds = $this->wrapConditionsForWhere( $table, $conds );
$sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
}
@@ -1299,7 +1304,8 @@ class DatabaseOracle extends DatabaseBase {
return 'BITOR(' . $fieldLeft . ', ' . $fieldRight . ')';
}
- function setFakeMaster( $enabled = true ) { }
+ function setFakeMaster( $enabled = true ) {
+ }
function getDBname() {
return $this->mDBname;
@@ -1312,4 +1318,9 @@ class DatabaseOracle extends DatabaseBase {
public function getSearchEngine() {
return 'SearchOracle';
}
+
+ public function getInfinity() {
+ return '31-12-2030 12:00:00.000000';
+ }
+
} // end DatabaseOracle class
diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php
index 742a8b51..98cf3c75 100644
--- a/includes/db/DatabasePostgres.php
+++ b/includes/db/DatabasePostgres.php
@@ -39,7 +39,7 @@ AND relname=%s
AND attname=%s;
SQL;
- $table = $db->tableName( $table, false );
+ $table = $db->tableName( $table, 'raw' );
$res = $db->query(
sprintf( $q,
$db->addQuotes( $wgDBmwschema ),
@@ -200,6 +200,7 @@ class DatabasePostgres extends DatabaseBase {
$this->query( "SET client_encoding='UTF8'", __METHOD__ );
$this->query( "SET datestyle = 'ISO, YMD'", __METHOD__ );
$this->query( "SET timezone = 'GMT'", __METHOD__ );
+ $this->query( "SET standard_conforming_strings = on", __METHOD__ );
global $wgDBmwschema;
if ( $this->schemaExists( $wgDBmwschema ) ) {
@@ -564,7 +565,7 @@ class DatabasePostgres extends DatabaseBase {
$ignore = in_array( 'IGNORE', $insertOptions ) ? 'mw' : '';
if( is_array( $insertOptions ) ) {
- $insertOptions = implode( ' ', $insertOptions );
+ $insertOptions = implode( ' ', $insertOptions ); // FIXME: This is unused
}
if( !is_array( $selectOptions ) ) {
$selectOptions = array( $selectOptions );
@@ -622,18 +623,23 @@ class DatabasePostgres extends DatabaseBase {
return $res;
}
- function tableName( $name, $quoted = true ) {
+ function tableName( $name, $format = 'quoted' ) {
# Replace reserved words with better ones
switch( $name ) {
case 'user':
- return 'mwuser';
+ return $this->realTableName( 'mwuser', $format );
case 'text':
- return 'pagecontent';
+ return $this->realTableName( 'pagecontent', $format );
default:
- return parent::tableName( $name, $quoted );
+ return $this->realTableName( $name, $format );
}
}
+ /* Don't cheat on installer */
+ function realTableName( $name, $format = 'quoted' ) {
+ return parent::tableName( $name, $format );
+ }
+
/**
* Return the next in a sequence, save the value for retrieval via insertId()
*/
@@ -687,6 +693,24 @@ class DatabasePostgres extends DatabaseBase {
return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName (LIKE $oldName INCLUDING DEFAULTS)", $fname );
}
+ function listTables( $prefix = null, $fname = 'DatabasePostgres::listTables' ) {
+ global $wgDBmwschema;
+ $eschema = $this->addQuotes( $wgDBmwschema );
+ $result = $this->query( "SELECT tablename FROM pg_tables WHERE schemaname = $eschema", $fname );
+
+ $endArray = array();
+
+ foreach( $result as $table ) {
+ $vars = get_object_vars($table);
+ $table = array_pop( $vars );
+ if( !$prefix || strpos( $table, $prefix ) === 0 ) {
+ $endArray[] = $table;
+ }
+ }
+
+ return $endArray;
+ }
+
function timestamp( $ts = 0 ) {
return wfTimestamp( TS_POSTGRES, $ts );
}
@@ -737,7 +761,7 @@ class DatabasePostgres extends DatabaseBase {
if ( !$schema ) {
$schema = $wgDBmwschema;
}
- $table = $this->tableName( $table, false );
+ $table = $this->realTableName( $table, 'raw' );
$etable = $this->addQuotes( $table );
$eschema = $this->addQuotes( $schema );
$SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
@@ -752,7 +776,7 @@ class DatabasePostgres extends DatabaseBase {
* For backward compatibility, this function checks both tables and
* views.
*/
- function tableExists( $table, $schema = false ) {
+ function tableExists( $table, $fname = __METHOD__, $schema = false ) {
return $this->relationExists( $table, array( 'r', 'v' ), $schema );
}
@@ -766,8 +790,8 @@ class DatabasePostgres extends DatabaseBase {
$q = <<<SQL
SELECT 1 FROM pg_class, pg_namespace, pg_trigger
WHERE relnamespace=pg_namespace.oid AND relkind='r'
- AND tgrelid=pg_class.oid
- AND nspname=%s AND relname=%s AND tgname=%s
+ AND tgrelid=pg_class.oid
+ AND nspname=%s AND relname=%s AND tgname=%s
SQL;
$res = $this->query(
sprintf(
@@ -982,4 +1006,17 @@ SQL;
public function getSearchEngine() {
return 'SearchPostgres';
}
+
+ public function streamStatementEnd( &$sql, &$newLine ) {
+ # Allow dollar quoting for function declarations
+ if ( substr( $newLine, 0, 4 ) == '$mw$' ) {
+ if ( $this->delimiter ) {
+ $this->delimiter = false;
+ }
+ else {
+ $this->delimiter = ';';
+ }
+ }
+ return parent::streamStatementEnd( $sql, $newLine );
+ }
} // end DatabasePostgres class
diff --git a/includes/db/DatabaseSqlite.php b/includes/db/DatabaseSqlite.php
index e298175d..b2eb1c6b 100644
--- a/includes/db/DatabaseSqlite.php
+++ b/includes/db/DatabaseSqlite.php
@@ -37,7 +37,7 @@ class DatabaseSqlite extends DatabaseBase {
$this->mName = $dbName;
parent::__construct( $server, $user, $password, $dbName, $flags );
// parent doesn't open when $user is false, but we can work with $dbName
- if( !$user && $dbName ) {
+ if( $dbName ) {
global $wgSharedDB;
if( $this->open( $server, $user, $password, $dbName ) && $wgSharedDB ) {
$this->attachDatabase( $wgSharedDB );
@@ -319,15 +319,15 @@ class DatabaseSqlite extends DatabaseBase {
* Use MySQL's naming (accounts for prefix etc) but remove surrounding backticks
*
* @param $name
- * @param bool $quoted
+ * @param $format String
* @return string
*/
- function tableName( $name, $quoted = true ) {
+ function tableName( $name, $format = 'quoted' ) {
// table names starting with sqlite_ are reserved
if ( strpos( $name, 'sqlite_' ) === 0 ) {
return $name;
}
- return str_replace( '"', '', parent::tableName( $name, $quoted ) );
+ return str_replace( '"', '', parent::tableName( $name, $format ) );
}
/**
diff --git a/includes/db/DatabaseUtility.php b/includes/db/DatabaseUtility.php
index d1bced6b..0ea713c8 100644
--- a/includes/db/DatabaseUtility.php
+++ b/includes/db/DatabaseUtility.php
@@ -10,6 +10,9 @@ class DBObject {
$this->mData = $data;
}
+ /**
+ * @return bool
+ */
function isLOB() {
return false;
}
@@ -155,6 +158,9 @@ class ResultWrapper implements Iterator {
$this->currentRow = null;
}
+ /**
+ * @return int
+ */
function current() {
if ( is_null( $this->currentRow ) ) {
$this->next();
@@ -162,16 +168,25 @@ class ResultWrapper implements Iterator {
return $this->currentRow;
}
+ /**
+ * @return int
+ */
function key() {
return $this->pos;
}
+ /**
+ * @return int
+ */
function next() {
$this->pos++;
$this->currentRow = $this->fetchObject();
return $this->currentRow;
}
+ /**
+ * @return bool
+ */
function valid() {
return $this->current() !== false;
}
diff --git a/includes/db/LBFactory.php b/includes/db/LBFactory.php
index 22a84960..dec6ae16 100644
--- a/includes/db/LBFactory.php
+++ b/includes/db/LBFactory.php
@@ -42,7 +42,6 @@ abstract class LBFactory {
/**
* Shut down, close connections and destroy the cached instance.
- *
*/
static function destroyInstance() {
if ( self::$instance ) {
@@ -64,6 +63,7 @@ abstract class LBFactory {
/**
* Construct a factory based on a configuration array (typically from $wgLBFactoryConf)
+ * @param $conf
*/
abstract function __construct( $conf );
@@ -110,6 +110,8 @@ abstract class LBFactory {
* Execute a function for each tracked load balancer
* The callback is called with the load balancer as the first parameter,
* and $params passed as the subsequent parameters.
+ * @param $callback string|array
+ * @param array $params
*/
abstract function forEachLB( $callback, $params = array() );
@@ -121,6 +123,8 @@ abstract class LBFactory {
/**
* Call a method of each tracked load balancer
+ * @param $methodName string
+ * @param $args array
*/
function forEachLBCallMethod( $methodName, $args = array() ) {
$this->forEachLB( array( $this, 'callMethod' ), array( $methodName, $args ) );
@@ -128,6 +132,9 @@ abstract class LBFactory {
/**
* Private helper for forEachLBCallMethod
+ * @param $loadBalancer
+ * @param $methodName string
+ * @param $args
*/
function callMethod( $loadBalancer, $methodName, $args ) {
call_user_func_array( array( $loadBalancer, $methodName ), $args );
@@ -232,6 +239,8 @@ class LBFactory_Simple extends LBFactory {
* Execute a function for each tracked load balancer
* The callback is called with the load balancer as the first parameter,
* and $params passed as the subsequent parameters.
+ * @param $callback
+ * @param $params array
*/
function forEachLB( $callback, $params = array() ) {
if ( isset( $this->mainLB ) ) {
diff --git a/includes/db/LBFactory_Multi.php b/includes/db/LBFactory_Multi.php
index 61e56e78..b7977a21 100644
--- a/includes/db/LBFactory_Multi.php
+++ b/includes/db/LBFactory_Multi.php
@@ -53,13 +53,16 @@ class LBFactory_Multi extends LBFactory {
var $conf, $mainLBs = array(), $extLBs = array();
var $lastWiki, $lastSection;
+ /**
+ * @param $conf array
+ */
function __construct( $conf ) {
$this->chronProt = new ChronologyProtector;
$this->conf = $conf;
$required = array( 'sectionsByDB', 'sectionLoads', 'serverTemplate' );
$optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName',
'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer',
- 'templateOverridesByCluster', 'masterTemplateOverrides',
+ 'templateOverridesByCluster', 'masterTemplateOverrides',
'readOnlyBySection' );
foreach ( $required as $key ) {
@@ -83,6 +86,10 @@ class LBFactory_Multi extends LBFactory {
}
}
+ /**
+ * @param $wiki bool|string
+ * @return string
+ */
function getSectionForWiki( $wiki = false ) {
if ( $this->lastWiki === $wiki ) {
return $this->lastSection;
@@ -99,7 +106,7 @@ class LBFactory_Multi extends LBFactory {
}
/**
- * @param $wiki string
+ * @param $wiki bool|string
* @return LoadBalancer
*/
function newMainLB( $wiki = false ) {
@@ -116,7 +123,7 @@ class LBFactory_Multi extends LBFactory {
}
/**
- * @param $wiki
+ * @param $wiki bool|string
* @return LoadBalancer
*/
function getMainLB( $wiki = false ) {
@@ -165,6 +172,9 @@ class LBFactory_Multi extends LBFactory {
/**
* Make a new load balancer object based on template and load array
*
+ * @param $template
+ * @param $loads array
+ * @param $groupLoads
* @return LoadBalancer
*/
function newLoadBalancer( $template, $loads, $groupLoads ) {
@@ -172,7 +182,7 @@ class LBFactory_Multi extends LBFactory {
$servers = $this->makeServerArray( $template, $loads, $groupLoads );
$lb = new LoadBalancer( array(
'servers' => $servers,
- 'masterWaitTimeout' => $wgMasterWaitTimeout
+ 'masterWaitTimeout' => $wgMasterWaitTimeout
));
return $lb;
}
@@ -180,6 +190,9 @@ class LBFactory_Multi extends LBFactory {
/**
* Make a server array as expected by LoadBalancer::__construct, using a template and load array
*
+ * @param $template
+ * @param $loads array
+ * @param $groupLoads
* @return array
*/
function makeServerArray( $template, $loads, $groupLoads ) {
@@ -220,6 +233,8 @@ class LBFactory_Multi extends LBFactory {
/**
* Take a group load array indexed by group then server, and reindex it by server then group
+ * @param $groupLoads
+ * @return array
*/
function reindexGroupLoads( $groupLoads ) {
$reindexed = array();
@@ -233,6 +248,8 @@ class LBFactory_Multi extends LBFactory {
/**
* Get the database name and prefix based on the wiki ID
+ * @param $wiki bool
+ * @return array
*/
function getDBNameAndPrefix( $wiki = false ) {
if ( $wiki === false ) {
@@ -247,6 +264,8 @@ class LBFactory_Multi extends LBFactory {
* Execute a function for each tracked load balancer
* The callback is called with the load balancer as the first parameter,
* and $params passed as the subsequent parameters.
+ * @param $callback
+ * @param $params array
*/
function forEachLB( $callback, $params = array() ) {
foreach ( $this->mainLBs as $lb ) {
diff --git a/includes/db/LBFactory_Single.php b/includes/db/LBFactory_Single.php
index 89b41321..f80aa4bc 100644
--- a/includes/db/LBFactory_Single.php
+++ b/includes/db/LBFactory_Single.php
@@ -15,7 +15,7 @@ class LBFactory_Single extends LBFactory {
}
/**
- * @param $wiki
+ * @param $wiki bool|string
*
* @return LoadBalancer_Single
*/
@@ -24,7 +24,7 @@ class LBFactory_Single extends LBFactory {
}
/**
- * @param $wiki
+ * @param $wiki bool|string
*
* @return LoadBalancer_Single
*/
@@ -34,7 +34,7 @@ class LBFactory_Single extends LBFactory {
/**
* @param $cluster
- * @param $wiki
+ * @param $wiki bool|string
*
* @return LoadBalancer_Single
*/
@@ -44,7 +44,7 @@ class LBFactory_Single extends LBFactory {
/**
* @param $cluster
- * @param $wiki
+ * @param $wiki bool|string
*
* @return LoadBalancer_Single
*/
diff --git a/includes/db/LoadBalancer.php b/includes/db/LoadBalancer.php
index c7210c4c..e96c6720 100644
--- a/includes/db/LoadBalancer.php
+++ b/includes/db/LoadBalancer.php
@@ -90,6 +90,8 @@ class LoadBalancer {
/**
* Get or set arbitrary data used by the parent object, usually an LBFactory
+ * @param $x
+ * @return \Mixed
*/
function parentInfo( $x = null ) {
return wfSetVar( $this->mParentInfo, $x );
@@ -99,7 +101,7 @@ class LoadBalancer {
* Given an array of non-normalised probabilities, this function will select
* an element and return the appropriate key
*
- * @param $weights
+ * @param $weights array
*
* @return int
*/
@@ -117,7 +119,7 @@ class LoadBalancer {
return false;
}
$max = mt_getrandmax();
- $rand = mt_rand(0, $max) / $max * $sum;
+ $rand = mt_rand( 0, $max ) / $max * $sum;
$sum = 0;
foreach ( $weights as $i => $w ) {
@@ -130,7 +132,7 @@ class LoadBalancer {
}
/**
- * @param $loads
+ * @param $loads array
* @param $wiki bool
* @return bool|int|string
*/
@@ -140,10 +142,10 @@ class LoadBalancer {
foreach ( $lags as $i => $lag ) {
if ( $i != 0 ) {
if ( $lag === false ) {
- wfDebug( "Server #$i is not replicating\n" );
+ wfDebugLog( 'replication', "Server #$i is not replicating\n" );
unset( $loads[$i] );
} elseif ( isset( $this->mServers[$i]['max lag'] ) && $lag > $this->mServers[$i]['max lag'] ) {
- wfDebug( "Server #$i is excessively lagged ($lag seconds)\n" );
+ wfDebugLog( 'replication', "Server #$i is excessively lagged ($lag seconds)\n" );
unset( $loads[$i] );
}
}
@@ -241,6 +243,7 @@ class LoadBalancer {
$i = $this->getRandomNonLagged( $currentLoads, $wiki );
if ( $i === false && count( $currentLoads ) != 0 ) {
# All slaves lagged. Switch to read-only mode
+ wfDebugLog( 'replication', "All slaves lagged. Switch to read-only mode\n" );
$wgReadOnly = 'The database has been automatically locked ' .
'while the slave database servers catch up to the master';
$i = $this->pickRandom( $currentLoads );
@@ -333,6 +336,8 @@ class LoadBalancer {
/**
* Wait for a specified number of microseconds, and return the period waited
+ * @param $t int
+ * @return int
*/
function sleep( $t ) {
wfProfileIn( __METHOD__ );
@@ -346,6 +351,7 @@ class LoadBalancer {
* Set the master wait position
* If a DB_SLAVE connection has been opened already, waits
* Otherwise sets a variable telling it to wait if such a connection is opened
+ * @param $pos int
*/
public function waitFor( $pos ) {
wfProfileIn( __METHOD__ );
@@ -363,6 +369,7 @@ class LoadBalancer {
/**
* Set the master wait position and wait for ALL slaves to catch up to it
+ * @param $pos int
*/
public function waitForAll( $pos ) {
wfProfileIn( __METHOD__ );
@@ -377,7 +384,8 @@ class LoadBalancer {
* Get any open connection to a given server index, local or foreign
* Returns false if there is no connection open
*
- * @return DatabaseBase
+ * @param $i int
+ * @return DatabaseBase|false
*/
function getAnyOpenConnection( $i ) {
foreach ( $this->mConns as $conns ) {
@@ -390,6 +398,9 @@ class LoadBalancer {
/**
* Wait for a given slave to catch up to the master pos stored in $this
+ * @param $index
+ * @param $open bool
+ * @return bool
*/
function doWait( $index, $open = false ) {
# Find a connection to wait on
@@ -662,12 +673,14 @@ class LoadBalancer {
* Returns a Database object whether or not the connection was successful.
* @access private
*
+ * @param $server
+ * @param $dbNameOverride bool
* @return DatabaseBase
*/
function reallyOpenConnection( $server, $dbNameOverride = false ) {
if( !is_array( $server ) ) {
throw new MWException( 'You must update your load-balancing configuration. ' .
- 'See DefaultSettings.php entry for $wgDBservers.' );
+ 'See DefaultSettings.php entry for $wgDBservers.' );
}
$host = $server['host'];
@@ -702,6 +715,10 @@ class LoadBalancer {
return $db;
}
+ /**
+ * @param $conn
+ * @throws DBConnectionError
+ */
function reportConnectionError( &$conn ) {
wfProfileIn( __METHOD__ );
@@ -719,6 +736,9 @@ class LoadBalancer {
wfProfileOut( __METHOD__ );
}
+ /**
+ * @return int
+ */
function getWriterIndex() {
return 0;
}
@@ -726,6 +746,7 @@ class LoadBalancer {
/**
* Returns true if the specified index is a valid server index
*
+ * @param $i
* @return bool
*/
function haveIndex( $i ) {
@@ -735,6 +756,7 @@ class LoadBalancer {
/**
* Returns true if the specified index is valid and has non-zero load
*
+ * @param $i
* @return bool
*/
function isNonZeroLoad( $i ) {
@@ -753,6 +775,8 @@ class LoadBalancer {
/**
* Get the host name or IP address of the server with the specified index
* Prefer a readable name if available.
+ * @param $i
+ * @return string
*/
function getServerName( $i ) {
if ( isset( $this->mServers[$i]['hostName'] ) ) {
@@ -766,6 +790,8 @@ class LoadBalancer {
/**
* Return the server info structure for a given index, or false if the index is invalid.
+ * @param $i
+ * @return bool
*/
function getServerInfo( $i ) {
if ( isset( $this->mServers[$i] ) ) {
@@ -777,6 +803,8 @@ class LoadBalancer {
/**
* Sets the server info structure for the given index. Entry at index $i is created if it doesn't exist
+ * @param $i
+ * @param $serverInfo
*/
function setServerInfo( $i, $serverInfo ) {
$this->mServers[$i] = $serverInfo;
@@ -827,8 +855,10 @@ class LoadBalancer {
* Deprecated function, typo in function name
*
* @deprecated in 1.18
+ * @param $conn
*/
function closeConnecton( $conn ) {
+ wfDeprecated( __METHOD__, '1.18' );
$this->closeConnection( $conn );
}
@@ -836,8 +866,7 @@ class LoadBalancer {
* Close a connection
* Using this function makes sure the LoadBalancer knows the connection is closed.
* If you use $conn->close() directly, the load balancer won't update its state.
- * @param $conn
- * @return void
+ * @param $conn DatabaseBase
*/
function closeConnection( $conn ) {
$done = false;
@@ -883,21 +912,32 @@ class LoadBalancer {
}
foreach ( $conns2[$masterIndex] as $conn ) {
if ( $conn->doneWrites() ) {
- $conn->commit();
+ $conn->commit( __METHOD__ );
}
}
}
}
+ /**
+ * @param $value null
+ * @return Mixed
+ */
function waitTimeout( $value = null ) {
return wfSetVar( $this->mWaitTimeout, $value );
}
+ /**
+ * @return bool
+ */
function getLaggedSlaveMode() {
return $this->mLaggedSlaveMode;
}
- /* Disables/enables lag checks */
+ /**
+ * Disables/enables lag checks
+ * @param $mode null
+ * @return bool
+ */
function allowLagged( $mode = null ) {
if ( $mode === null) {
return $this->mAllowLagged;
@@ -905,6 +945,9 @@ class LoadBalancer {
$this->mAllowLagged = $mode;
}
+ /**
+ * @return bool
+ */
function pingAll() {
$success = true;
foreach ( $this->mConns as $conns2 ) {
@@ -921,6 +964,8 @@ class LoadBalancer {
/**
* Call a function with each open connection object
+ * @param $callback
+ * @param array $params
*/
function forEachOpenConnection( $callback, $params = array() ) {
foreach ( $this->mConns as $conns2 ) {
@@ -936,7 +981,7 @@ class LoadBalancer {
/**
* Get the hostname and lag time of the most-lagged slave.
* This is useful for maintenance scripts that need to throttle their updates.
- * May attempt to open connections to slaves on the default DB. If there is
+ * May attempt to open connections to slaves on the default DB. If there is
* no lag, the maximum lag will be reported as -1.
*
* @param $wiki string Wiki ID, or false for the default database
@@ -988,22 +1033,26 @@ class LoadBalancer {
$this->mLagTimes = array( 0 => 0 );
} else {
# Send the request to the load monitor
- $this->mLagTimes = $this->getLoadMonitor()->getLagTimes(
+ $this->mLagTimes = $this->getLoadMonitor()->getLagTimes(
array_keys( $this->mServers ), $wiki );
}
return $this->mLagTimes;
}
/**
- * Get the lag in seconds for a given connection, or zero if this load
- * balancer does not have replication enabled.
+ * Get the lag in seconds for a given connection, or zero if this load
+ * balancer does not have replication enabled.
*
- * This should be used in preference to Database::getLag() in cases where
- * replication may not be in use, since there is no way to determine if
- * replication is in use at the connection level without running
+ * This should be used in preference to Database::getLag() in cases where
+ * replication may not be in use, since there is no way to determine if
+ * replication is in use at the connection level without running
* potentially restricted queries such as SHOW SLAVE STATUS. Using this
* function instead of Database::getLag() avoids a fatal error in this
* case on many installations.
+ *
+ * @param $conn DatabaseBase
+ *
+ * @return int
*/
function safeGetLag( $conn ) {
if ( $this->getServerCount() == 1 ) {
diff --git a/includes/db/LoadMonitor.php b/includes/db/LoadMonitor.php
index a6370c9e..16a0343f 100644
--- a/includes/db/LoadMonitor.php
+++ b/includes/db/LoadMonitor.php
@@ -66,12 +66,16 @@ class LoadMonitor_Null implements LoadMonitor {
function postConnectionBackoff( $conn, $threshold ) {
}
+ /**
+ * @param $serverIndexes
+ * @param $wiki
+ * @return array
+ */
function getLagTimes( $serverIndexes, $wiki ) {
return array_fill_keys( $serverIndexes, 0 );
}
}
-
/**
* Basic MySQL load monitor with no external dependencies
* Uses memcached to cache the replication lag for a short time