} catch ( Exception $ex ) {
wfProfileOut( "dbconnect-$server" );
wfProfileOut( __METHOD__ );
+ $this->restoreErrorHandler();
throw $ex;
}
$error = $this->restoreErrorHandler();
substr( $password, 0, 3 ) . "..., error: " . $error . "\n" );
wfProfileOut( __METHOD__ );
+
return $this->reportConnectionError( $error );
}
"from client host " . wfHostname() . "\n" );
wfProfileOut( __METHOD__ );
+
return $this->reportConnectionError( "Error selecting database $dbName" );
}
}
// Tell the server we're communicating with it in UTF-8.
// This may engage various charset conversions.
if ( $wgDBmysql5 ) {
- $this->query( 'SET NAMES utf8', __METHOD__ );
+ $this->mysqlSetCharset( 'utf8' );
} else {
- $this->query( 'SET NAMES binary', __METHOD__ );
+ $this->mysqlSetCharset( 'binary' );
}
// Set SQL mode, default is turning them all off, can be overridden or skipped with null
if ( is_string( $wgSQLMode ) ) {
$this->mOpened = true;
wfProfileOut( __METHOD__ );
+
return true;
}
*/
abstract protected function mysqlConnect( $realServer );
+ /**
+ * Set the character set of the MySQL link
+ *
+ * @param string $charset
+ * @return bool
+ */
+ abstract protected function mysqlSetCharset( $charset );
+
/**
* @param $res ResultWrapper
* @throws DBUnexpectedError
// these are the only errors mysql_fetch_object can cause.
// See http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-row.html.
if ( $errno == 2000 || $errno == 2013 ) {
- throw new DBUnexpectedError( $this, 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() ) );
+ throw new DBUnexpectedError(
+ $this,
+ 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() )
+ );
}
+
return $row;
}
// these are the only errors mysql_fetch_array can cause.
// See http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-row.html.
if ( $errno == 2000 || $errno == 2013 ) {
- throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() ) );
+ throw new DBUnexpectedError(
+ $this,
+ 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() )
+ );
}
+
return $row;
}
wfSuppressWarnings();
$n = $this->mysqlNumRows( $res );
wfRestoreWarnings();
+
// Unfortunately, mysql_num_rows does not reset the last errno.
// We are not checking for any errors here, since
// these are no errors mysql_num_rows can cause.
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
+
return $this->mysqlNumFields( $res );
}
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
+
return $this->mysqlFieldName( $res, $n );
}
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
+
return $this->mysqlDataSeek( $res, $row );
}
if ( $error ) {
$error .= ' (' . $this->mServer . ')';
}
+
return $error;
}
* @param $options string|array
* @return int
*/
- public function estimateRowCount( $table, $vars = '*', $conds = '', $fname = __METHOD__, $options = array() ) {
+ public function estimateRowCount( $table, $vars = '*', $conds = '',
+ $fname = __METHOD__, $options = array()
+ ) {
$options['EXPLAIN'] = true;
$res = $this->select( $table, $vars, $conds, $fname, $options );
if ( $res === false ) {
foreach ( $res as $plan ) {
$rows *= $plan->rows > 0 ? $plan->rows : 1; // avoid resetting to zero
}
+
return $rows;
}
return new MySQLField( $meta );
}
}
+
return false;
}
$result[] = $row;
}
}
+
return empty( $result ) ? false : $result;
}
$this->ping();
$sQuoted = $this->mysqlRealEscapeString( $s );
}
+
return $sQuoted;
}
public function addIdentifierQuotes( $s ) {
// Characters in the range \u0001-\uFFFF are valid in a quoted identifier
// Remove NUL bytes and escape backticks by doubling
- return '`' . str_replace( array( "\0", '`' ), array( '', '``' ), $s ) . '`';
+ return '`' . str_replace( array( "\0", '`' ), array( '', '``' ), $s ) . '`';
}
/**
$this->mOpened = false;
$this->mConn = false;
$this->open( $this->mServer, $this->mUser, $this->mPassword, $this->mDBname );
+
return true;
}
function getLag() {
if ( !is_null( $this->mFakeSlaveLag ) ) {
wfDebug( "getLag: fake slave lagged {$this->mFakeSlaveLag} seconds\n" );
+
return $this->mFakeSlaveLag;
}
$row->State != 'Waiting to reconnect after a failed master event read' &&
$row->State != 'Reconnecting after a failed master event read' &&
$row->State != 'Registering slave on master'
- ) {
+ ) {
# This is it, return the time (except -ve)
if ( $row->Time > 0x7fffffff ) {
return false;
}
}
}
+
return false;
}
if ( !is_null( $this->mFakeSlaveLag ) ) {
$status = parent::masterPosWait( $pos, $timeout );
wfProfileOut( __METHOD__ );
+
return $status;
}
}
wfProfileOut( __METHOD__ );
+
return $status;
}
$row = $this->fetchObject( $res );
if ( $row ) {
- $pos = isset( $row->Exec_master_log_pos ) ? $row->Exec_master_log_pos : $row->Exec_Master_Log_Pos;
+ $pos = isset( $row->Exec_master_log_pos )
+ ? $row->Exec_master_log_pos
+ : $row->Exec_Master_Log_Pos;
+
return new MySQLMasterPos( $row->Relay_Master_Log_File, $pos );
} else {
return false;
$this->delimiter = $m[1];
$newLine = '';
}
+
return parent::streamStatementEnd( $sql, $newLine );
}
$lockName = $this->addQuotes( $lockName );
$result = $this->query( "SELECT IS_FREE_LOCK($lockName) AS lockstatus", $method );
$row = $this->fetchObject( $result );
+
return ( $row->lockstatus == 1 );
}
return true;
} else {
wfDebug( __METHOD__ . " failed to acquire lock\n" );
+
return false;
}
}
/**
- * FROM MYSQL DOCS: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock
+ * 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
$lockName = $this->addQuotes( $lockName );
$result = $this->query( "SELECT RELEASE_LOCK($lockName) as lockstatus", $method );
$row = $this->fetchObject( $result );
+
return ( $row->lockstatus == 1 );
}
foreach ( $write as $table ) {
$tbl = $this->tableName( $table ) .
- ( $lowPriority ? ' LOW_PRIORITY' : '' ) .
- ' WRITE';
+ ( $lowPriority ? ' LOW_PRIORITY' : '' ) .
+ ' WRITE';
$items[] = $tbl;
}
foreach ( $read as $table ) {
}
$sql = "LOCK TABLES " . implode( ',', $items );
$this->query( $sql, $method );
+
return true;
}
*/
public function unlockTables( $method ) {
$this->query( "UNLOCK TABLES", $method );
+
return true;
}
*/
function getServerUptime() {
$vars = $this->getMysqlStatus( 'Uptime' );
+
return (int)$vars['Uptime'];
}
if ( !$this->tableExists( $tableName, $fName ) ) {
return false;
}
+
return $this->query( "DROP TABLE IF EXISTS " . $this->tableName( $tableName ), $fName );
}
protected function getDefaultSchemaVars() {
$vars = parent::getDefaultSchemaVars();
$vars['wgDBTableOptions'] = str_replace( 'TYPE', 'ENGINE', $GLOBALS['wgDBTableOptions'] );
- $vars['wgDBTableOptions'] = str_replace( 'CHARSET=mysql4', 'CHARSET=binary', $vars['wgDBTableOptions'] );
+ $vars['wgDBTableOptions'] = str_replace(
+ 'CHARSET=mysql4',
+ 'CHARSET=binary',
+ $vars['wgDBTableOptions']
+ );
+
return $vars;
}
return $status;
}
-}
+ /**
+ * Lists VIEWs in the database
+ *
+ * @param string $prefix Only show VIEWs with this prefix, eg.
+ * unit_test_, or $wgDBprefix. Default: null, would return all views.
+ * @param string $fname Name of calling function
+ * @return array
+ * @since 1.22
+ */
+ public function listViews( $prefix = null, $fname = __METHOD__ ) {
+
+ if ( !isset( $this->allViews ) ) {
+
+ // The name of the column containing the name of the VIEW
+ $propertyName = 'Tables_in_' . $this->mDBname;
+
+ // Query for the VIEWS
+ $result = $this->query( 'SHOW FULL TABLES WHERE TABLE_TYPE = "VIEW"' );
+ $this->allViews = array();
+ while ( ( $row = $this->fetchRow( $result ) ) !== false ) {
+ array_push( $this->allViews, $row[$propertyName] );
+ }
+ }
+
+ if ( is_null( $prefix ) || $prefix === '' ) {
+ return $this->allViews;
+ }
+ $filteredViews = array();
+ foreach ( $this->allViews as $viewName ) {
+ // Does the name of this VIEW start with the table-prefix?
+ if ( strpos( $viewName, $prefix ) === 0 ) {
+ array_push( $filteredViews, $viewName );
+ }
+ }
+ return $filteredViews;
+ }
+
+ /**
+ * Differentiates between a TABLE and a VIEW.
+ *
+ * @param $name string: Name of the TABLE/VIEW to test
+ * @return bool
+ * @since 1.22
+ */
+ public function isView( $name, $prefix = null ) {
+ return in_array( $name, $this->listViews( $prefix ) );
+ }
+}
/**
* Utility class.
*/
class MySQLField implements Field {
private $name, $tablename, $default, $max_length, $nullable,
- $is_pk, $is_unique, $is_multiple, $is_key, $type;
+ $is_pk, $is_unique, $is_multiple, $is_key, $type, $binary;
function __construct( $info ) {
$this->name = $info->name;
$this->is_multiple = $info->multiple_key;
$this->is_key = ( $this->is_pk || $this->is_unique || $this->is_multiple );
$this->type = $info->type;
+ $this->binary = isset( $info->binary ) ? $info->binary : false;
}
/**
function isMultipleKey() {
return $this->is_multiple;
}
+
+ function isBinary() {
+ return $this->binary;
+ }
}
class MySQLMasterPos implements DBMasterPos {
if ( preg_match( '!\.(\d+)/(\d+)$!', (string)$this, $m ) ) {
return array( (int)$m[1], (int)$m[2] );
}
+
return false;
}
function hasReached( MySQLMasterPos $pos ) {
$thisPos = $this->getCoordinates();
$thatPos = $pos->getCoordinates();
+
return ( $thisPos && $thatPos && $thisPos >= $thatPos );
}
}