protected function ignoreErrors( $ignoreErrors = null ) {
$res = $this->getFlag( self::DBO_IGNORE );
if ( $ignoreErrors !== null ) {
- $ignoreErrors
- ? $this->setFlag( self::DBO_IGNORE )
- : $this->clearFlag( self::DBO_IGNORE );
+ // setFlag()/clearFlag() do not allow DBO_IGNORE changes for sanity
+ if ( $ignoreErrors ) {
+ $this->mFlags |= self::DBO_IGNORE;
+ } else {
+ $this->mFlags &= ~self::DBO_IGNORE;
+ }
}
return $res;
}
public function setFlag( $flag, $remember = self::REMEMBER_NOTHING ) {
+ if ( ( $flag & self::DBO_IGNORE ) ) {
+ throw new \UnexpectedValueException( "Modifying DBO_IGNORE is not allowed." );
+ }
+
if ( $remember === self::REMEMBER_PRIOR ) {
array_push( $this->priorFlags, $this->mFlags );
}
}
public function clearFlag( $flag, $remember = self::REMEMBER_NOTHING ) {
+ if ( ( $flag & self::DBO_IGNORE ) ) {
+ throw new \UnexpectedValueException( "Modifying DBO_IGNORE is not allowed." );
+ }
+
if ( $remember === self::REMEMBER_PRIOR ) {
array_push( $this->priorFlags, $this->mFlags );
}
# Update state tracking to reflect transaction loss due to disconnection
$this->handleSessionLoss();
if ( $this->reconnect() ) {
- $msg = __METHOD__ . ": lost connection to {$this->getServer()}; reconnected";
- $this->connLogger->warning( $msg );
- $this->queryLogger->warning(
- "$msg:\n" . ( new RuntimeException() )->getTraceAsString() );
+ $msg = __METHOD__ . ': lost connection to {dbserver}; reconnected';
+ $params = [ 'dbserver' => $this->getServer() ];
+ $this->connLogger->warning( $msg, $params );
+ $this->queryLogger->warning( $msg, $params +
+ [ 'trace' => ( new RuntimeException() )->getTraceAsString() ] );
if ( !$recoverable ) {
# Callers may catch the exception and continue to use the DB
$ret = $this->doProfiledQuery( $sql, $commentedSql, $isNonTempWrite, $fname );
}
} else {
- $msg = __METHOD__ . ": lost connection to {$this->getServer()} permanently";
- $this->connLogger->error( $msg );
+ $msg = __METHOD__ . ': lost connection to {dbserver} permanently';
+ $this->connLogger->error( $msg, [ 'dbserver' => $this->getServer() ] );
}
}
*
* @param string $error Error text
* @param int $errno Error number
+ * @return bool
*/
protected function wasQueryTimeout( $error, $errno ) {
return false;
// No alias? Set it equal to the table name
$alias = $table;
}
+
+ if ( is_array( $table ) ) {
+ // A parenthesized group
+ if ( count( $table ) > 1 ) {
+ $joinedTable = '('
+ . $this->tableNamesWithIndexClauseOrJOIN( $table, $use_index, $ignore_index, $join_conds )
+ . ')';
+ } else {
+ // Degenerate case
+ $innerTable = reset( $table );
+ $innerAlias = key( $table );
+ $joinedTable = $this->tableNameWithAlias(
+ $innerTable,
+ is_string( $innerAlias ) ? $innerAlias : $innerTable
+ );
+ }
+ } else {
+ $joinedTable = $this->tableNameWithAlias( $table, $alias );
+ }
+
// Is there a JOIN clause for this table?
if ( isset( $join_conds[$alias] ) ) {
list( $joinType, $conds ) = $join_conds[$alias];
$tableClause = $joinType;
- $tableClause .= ' ' . $this->tableNameWithAlias( $table, $alias );
+ $tableClause .= ' ' . $joinedTable;
if ( isset( $use_index[$alias] ) ) { // has USE INDEX?
$use = $this->useIndexClause( implode( ',', (array)$use_index[$alias] ) );
if ( $use != '' ) {
$retJOIN[] = $tableClause;
} elseif ( isset( $use_index[$alias] ) ) {
// Is there an INDEX clause for this table?
- $tableClause = $this->tableNameWithAlias( $table, $alias );
+ $tableClause = $joinedTable;
$tableClause .= ' ' . $this->useIndexClause(
implode( ',', (array)$use_index[$alias] )
);
$ret[] = $tableClause;
} elseif ( isset( $ignore_index[$alias] ) ) {
// Is there an INDEX clause for this table?
- $tableClause = $this->tableNameWithAlias( $table, $alias );
+ $tableClause = $joinedTable;
$tableClause .= ' ' . $this->ignoreIndexClause(
implode( ',', (array)$ignore_index[$alias] )
);
$ret[] = $tableClause;
} else {
- $tableClause = $this->tableNameWithAlias( $table, $alias );
+ $tableClause = $joinedTable;
$ret[] = $tableClause;
}
$this->mTrxIdleCallbacks = []; // clear
$this->mTrxPreCommitCallbacks = []; // clear
- $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK );
- $this->runTransactionListenerCallbacks( self::TRIGGER_ROLLBACK );
+ try {
+ $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK );
+ } catch ( Exception $e ) {
+ // already logged; finish and let LoadBalancer move on during mass-rollback
+ }
+ try {
+ $this->runTransactionListenerCallbacks( self::TRIGGER_ROLLBACK );
+ } catch ( Exception $e ) {
+ // already logged; let LoadBalancer move on during mass-rollback
+ }
}
/**