// Reset the global service locator, so any services that have already been created will be
// re-created while taking into account any custom settings and extensions.
MediaWikiServices::resetGlobalInstance( new GlobalVarConfig(), 'quick' );
+// Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections)
+if ( $wgSharedDB && $wgSharedTables ) {
+ MediaWikiServices::getInstance()->getDBLoadBalancer()->setTableAliases(
+ array_fill_keys(
+ $wgSharedTables,
+ [
+ 'dbname' => $wgSharedDB,
+ 'schema' => $wgSharedSchema,
+ 'prefix' => $wgSharedPrefix
+ ]
+ )
+ );
+}
// Define a constant that indicates that the bootstrapping of the service locator
// is complete.
protected $mPassword;
/** @var string */
protected $mDBname;
+ /** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
+ protected $tableAliases = [];
/** @var bool */
protected $cliMode;
protected $mSchema;
/** @var integer */
protected $mFlags;
- /** @var bool */
- protected $mForeign;
/** @var array */
protected $mLBInfo = [];
/** @var bool|null */
$this->mSessionVars = $params['variables'];
- $this->mForeign = $params['foreign'];
-
$this->srvCache = isset( $params['srvCache'] )
? $params['srvCache']
: new EmptyBagOStuff();
* @return string Full database name
*/
public function tableName( $name, $format = 'quoted' ) {
- global $wgSharedDB, $wgSharedPrefix, $wgSharedTables, $wgSharedSchema;
# 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
# use of `database`.table. But won't break things if someone wants
$schema = null;
} else {
list( $table ) = $dbDetails;
- if ( $wgSharedDB !== null # We have a shared database
- && $this->mForeign == false # We're not working on a foreign database
- && !$this->isQuotedIdentifier( $table ) # Prevent shared tables listing '`table`'
- && in_array( $table, $wgSharedTables ) # A shared table is selected
- ) {
- $database = $wgSharedDB;
- $schema = $wgSharedSchema === null ? $this->mSchema : $wgSharedSchema;
- $prefix = $wgSharedPrefix === null ? $this->mTablePrefix : $wgSharedPrefix;
+ if ( isset( $this->tableAliases[$table] ) ) {
+ $database = $this->tableAliases[$table]['dbname'];
+ $schema = is_string( $this->tableAliases[$table]['schema'] )
+ ? $this->tableAliases[$table]['schema']
+ : $this->mSchema;
+ $prefix = is_string( $this->tableAliases[$table]['prefix'] )
+ ? $this->tableAliases[$table]['prefix']
+ : $this->mTablePrefix;
} else {
$database = null;
$schema = $this->mSchema; # Default schema
# Quote $table and apply the prefix if not quoted.
# $tableName might be empty if this is called from Database::replaceVars()
$tableName = "{$prefix}{$table}";
- if ( $format == 'quoted' && !$this->isQuotedIdentifier( $tableName ) && $tableName !== '' ) {
+ if ( $format == 'quoted'
+ && !$this->isQuotedIdentifier( $tableName ) && $tableName !== ''
+ ) {
$tableName = $this->addIdentifierQuotes( $tableName );
}
return is_string( $reason ) ? $reason : false;
}
+ public function setTableAliases( array $aliases ) {
+ $this->tableAliases = $aliases;
+ }
+
/**
* @since 1.19
* @return string
* @param array $p
*/
function __construct( array $p ) {
- global $wgSharedDB, $wgSQLiteDataDir;
+ global $wgSQLiteDataDir;
$this->dbDir = isset( $p['dbDirectory'] ) ? $p['dbDirectory'] : $wgSQLiteDataDir;
// Super doesn't open when $user is false, but we can work with $dbName
if ( $p['dbname'] && !$this->isOpen() ) {
if ( $this->open( $p['host'], $p['user'], $p['password'], $p['dbname'] ) ) {
- if ( $wgSharedDB ) {
- $this->attachDatabase( $wgSharedDB );
+ $done = [];
+ foreach ( $this->tableAliases as $params ) {
+ if ( isset( $done[$params['dbname']] ) ) {
+ continue;
+ }
+ $this->attachDatabase( $params['dbname'] );
+ $done[$params['dbname']] = 1;
}
}
}
return $this->__call( __FUNCTION__, func_get_args() );
}
+ public function setTableAliases( array $aliases ) {
+ return $this->__call( __FUNCTION__, func_get_args() );
+ }
+
/**
* Clean up the connection when out of scope
*/
* @since 1.27
*/
public function isReadOnly();
+
+ /**
+ * Make certain table names use their own database, schema, and table prefix
+ * when passed into SQL queries pre-escaped and without a qualified database name
+ *
+ * For example, "user" can be converted to "myschema.mydbname.user" for convenience.
+ * Appearances like `user`, somedb.user, somedb.someschema.user will used literally.
+ *
+ * Calling this twice will completely clear any old table aliases. Also, note that
+ * callers are responsible for making sure the schemas and databases actually exist.
+ *
+ * @param array[] $aliases Map of (table => (dbname, schema, prefix) map)
+ * @since 1.28
+ */
+ public function setTableAliases( array $aliases );
}
private $mWaitTimeout;
/** @var string The LoadMonitor subclass name */
private $mLoadMonitorClass;
+ /** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
+ private $tableAliases = [];
/** @var LoadMonitor */
private $mLoadMonitor;
$db->setLazyMasterHandle(
$this->getLazyConnectionRef( DB_MASTER, [], $db->getWikiID() )
);
+ $db->setTableAliases( $this->tableAliases );
if ( $server['serverIndex'] === $this->getWriterIndex() ) {
if ( $this->trxRoundId !== false ) {
);
}
+ /**
+ * Make certain table names use their own database, schema, and table prefix
+ * when passed into SQL queries pre-escaped and without a qualified database name
+ *
+ * For example, "user" can be converted to "myschema.mydbname.user" for convenience.
+ * Appearances like `user`, somedb.user, somedb.someschema.user will used literally.
+ *
+ * Calling this twice will completely clear any old table aliases. Also, note that
+ * callers are responsible for making sure the schemas and databases actually exist.
+ *
+ * @param array[] $aliases Map of (table => (dbname, schema, prefix) map)
+ * @since 1.28
+ */
+ public function setTableAliases( array $aliases ) {
+ $this->tableAliases = $aliases;
+ }
+
/**
* Set a new table prefix for the existing local domain ID for testing
*
}
private function getSharedTableName( $table, $database, $prefix, $format = 'quoted' ) {
- global $wgSharedDB, $wgSharedTables, $wgSharedPrefix;
+ global $wgSharedDB, $wgSharedTables, $wgSharedPrefix, $wgSharedSchema;
- $oldName = $wgSharedDB;
- $oldTables = $wgSharedTables;
- $oldPrefix = $wgSharedPrefix;
-
- $wgSharedDB = $database;
- $wgSharedTables = [ $table ];
- $wgSharedPrefix = $prefix;
+ $this->db->setTableAliases( [
+ $table => [
+ 'dbname' => $database,
+ 'schema' => null,
+ 'prefix' => $prefix
+ ]
+ ] );
$ret = $this->db->tableName( $table, $format );
- $wgSharedDB = $oldName;
- $wgSharedTables = $oldTables;
- $wgSharedPrefix = $oldPrefix;
+ $this->db->setTableAliases( array_fill_keys(
+ $wgSharedDB ? $wgSharedTables : [],
+ [
+ 'dbname' => $wgSharedDB,
+ 'schema' => $wgSharedSchema,
+ 'prefix' => $wgSharedPrefix
+ ]
+ ) );
return $ret;
}