use Wikimedia\Timestamp\ConvertibleTimestamp;
use Wikimedia\WaitConditionLoop;
-use MediaWiki;
+use Wikimedia;
use Exception;
/**
);
}
- $this->mServer = $server;
- $this->mUser = $user;
- $this->mPassword = $password;
- $this->mDBname = $dbName;
+ $this->server = $server;
+ $this->user = $user;
+ $this->password = $password;
+ $this->dbName = $dbName;
$connectVars = [
// pg_connect() user $user as the default database. Since a database is *required*,
if ( (int)$this->port > 0 ) {
$connectVars['port'] = (int)$this->port;
}
- if ( $this->mFlags & self::DBO_SSL ) {
+ if ( $this->flags & self::DBO_SSL ) {
$connectVars['sslmode'] = 1;
}
try {
// Use new connections to let LoadBalancer/LBFactory handle reuse
- $this->mConn = pg_connect( $this->connectString, PGSQL_CONNECT_FORCE_NEW );
+ $this->conn = pg_connect( $this->connectString, PGSQL_CONNECT_FORCE_NEW );
} catch ( Exception $ex ) {
$this->restoreErrorHandler();
throw $ex;
$phpError = $this->restoreErrorHandler();
- if ( !$this->mConn ) {
+ if ( !$this->conn ) {
$this->queryLogger->debug(
"DB connection error\n" .
"Server: $server, Database: $dbName, User: $user, Password: " .
throw new DBConnectionError( $this, str_replace( "\n", ' ', $phpError ) );
}
- $this->mOpened = true;
+ $this->opened = true;
# If called from the command-line (e.g. importDump), only show errors
if ( $this->cliMode ) {
$this->query( "SET bytea_output = 'escape'", __METHOD__ ); // PHP bug 53127
}
- $this->determineCoreSchema( $this->mSchema );
+ $this->determineCoreSchema( $this->schema );
// The schema to be used is now in the search path; no need for explicit qualification
- $this->mSchema = '';
+ $this->schema = '';
- return $this->mConn;
+ return $this->conn;
}
public function databasesAreIndependent() {
* @throws DBUnexpectedError
*/
public function selectDB( $db ) {
- if ( $this->mDBname !== $db ) {
- return (bool)$this->open( $this->mServer, $this->mUser, $this->mPassword, $db );
+ if ( $this->dbName !== $db ) {
+ return (bool)$this->open( $this->server, $this->user, $this->password, $db );
} else {
return true;
}
}
protected function closeConnection() {
- return $this->mConn ? pg_close( $this->mConn ) : true;
+ return $this->conn ? pg_close( $this->conn ) : true;
+ }
+
+ protected function isTransactableQuery( $sql ) {
+ return parent::isTransactableQuery( $sql ) &&
+ !preg_match( '/^SELECT\s+pg_(try_|)advisory_\w+\(/', $sql );
}
public function doQuery( $sql ) {
}
}
/* Transaction stays in the ERROR state until rolled back */
- if ( $this->mTrxLevel ) {
+ if ( $this->trxLevel ) {
// Throw away the transaction state, then raise the error as normal.
// Note that if this connection is managed by LBFactory, it's already expected
// that the other transactions LBFactory manages will be rolled back.
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
$ok = pg_free_result( $res );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
if ( !$ok ) {
throw new DBUnexpectedError( $this, "Unable to free Postgres result\n" );
}
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
$row = pg_fetch_object( $res );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
# @todo FIXME: HACK HACK HACK HACK debug
# @todo hashar: not sure if the following test really trigger if the object
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
$row = pg_fetch_array( $res );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
$conn = $this->getBindingHandle();
if ( pg_last_error( $conn ) ) {
if ( $res instanceof ResultWrapper ) {
$res = $res->result;
}
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
$n = pg_num_rows( $res );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
$conn = $this->getBindingHandle();
if ( pg_last_error( $conn ) ) {
}
public function lastError() {
- if ( $this->mConn ) {
+ if ( $this->conn ) {
if ( $this->mLastResult ) {
return pg_result_error( $this->mLastResult );
} else {
}
}
- public function affectedRows() {
+ protected function fetchAffectedRowCount() {
if ( !is_null( $this->mAffectedRows ) ) {
// Forced result for simulated queries
return $this->mAffectedRows;
unset( $options[$forUpdateKey] );
$options['FOR UPDATE'] = [];
- // All tables not in $join_conds are good
- foreach ( $table as $alias => $name ) {
- if ( is_numeric( $alias ) ) {
+ $toCheck = $table;
+ reset( $toCheck );
+ while ( $toCheck ) {
+ $alias = key( $toCheck );
+ $name = $toCheck[$alias];
+ unset( $toCheck[$alias] );
+
+ $hasAlias = !is_numeric( $alias );
+ if ( !$hasAlias && is_string( $name ) ) {
$alias = $name;
}
- if ( !isset( $join_conds[$alias] ) ) {
- $options['FOR UPDATE'][] = $alias;
- }
- }
- foreach ( $join_conds as $table_cond => $join_cond ) {
- if ( 0 === preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_cond[0] ) ) {
- $options['FOR UPDATE'][] = $table_cond;
+ if ( !isset( $join_conds[$alias] ) ||
+ !preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_conds[$alias][0] )
+ ) {
+ if ( is_array( $name ) ) {
+ // It's a parenthesized group, process all the tables inside the group.
+ $toCheck = array_merge( $toCheck, $name );
+ } else {
+ // Quote alias names so $this->tableName() won't mangle them
+ $options['FOR UPDATE'][] = $hasAlias ? $this->addIdentifierQuotes( $alias ) : $alias;
+ }
}
}
-
- // Quote alias names so $this->tableName() won't mangle them
- $options['FOR UPDATE'] = array_map( function ( $name ) use ( $table ) {
- return isset( $table[$name] ) ? $this->addIdentifierQuotes( $name ) : $name;
- }, $options['FOR UPDATE'] );
}
if ( isset( $options['ORDER BY'] ) && $options['ORDER BY'] == 'NULL' ) {
public function strencode( $s ) {
// Should not be called by us
- return pg_escape_string( $this->getBindingHandle(), $s );
+ return pg_escape_string( $this->getBindingHandle(), (string)$s );
}
public function addQuotes( $s ) {
return 'DEFAULT';
}
- return "'" . pg_escape_string( $conn, $s ) . "'";
+ return "'" . pg_escape_string( $conn, (string)$s ) . "'";
}
/**
}
public function getDBname() {
- return $this->mDBname;
+ return $this->dbName;
}
public function getServer() {
- return $this->mServer;
+ return $this->server;
}
public function buildConcat( $stringList ) {
}
public function lockIsFree( $lockName, $method ) {
+ if ( !parent::lockIsFree( $lockName, $method ) ) {
+ return false; // already held
+ }
// http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
$key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
$result = $this->query( "SELECT (CASE(pg_try_advisory_lock($key))