* @ingroup Database
*/
+use MediaWiki\Config\ServiceOptions;
use MediaWiki\Logger\LoggerFactory;
use Wikimedia\Rdbms\LBFactory;
use Wikimedia\Rdbms\DatabaseDomain;
/** @var array Cache of already-logged deprecation messages */
private static $loggedDeprecations = [];
+ /**
+ * TODO Make this a const when HHVM support is dropped (T192166)
+ *
+ * @var array
+ * @since 1.34
+ */
+ public static $applyDefaultConfigOptions = [
+ 'DBcompress',
+ 'DBDefaultGroup',
+ 'DBmwschema',
+ 'DBname',
+ 'DBpassword',
+ 'DBport',
+ 'DBprefix',
+ 'DBserver',
+ 'DBservers',
+ 'DBssl',
+ 'DBtype',
+ 'DBuser',
+ 'DBWindowsAuthentication',
+ 'DebugDumpSql',
+ 'DebugLogFile',
+ 'ExternalServers',
+ 'SQLiteDataDir',
+ 'SQLMode',
+ ];
+
/**
* @param array $lbConf Config for LBFactory::__construct()
- * @param Config $mainConfig Main config object from MediaWikiServices
+ * @param ServiceOptions $options
* @param ConfiguredReadOnlyMode $readOnlyMode
* @param BagOStuff $srvCace
* @param BagOStuff $mainStash
*/
public static function applyDefaultConfig(
array $lbConf,
- Config $mainConfig,
+ ServiceOptions $options,
ConfiguredReadOnlyMode $readOnlyMode,
BagOStuff $srvCace,
BagOStuff $mainStash,
WANObjectCache $wanCache
) {
+ $options->assertRequiredOptions( self::$applyDefaultConfigOptions );
+
global $wgCommandLineMode;
- static $typesWithSchema = [ 'postgres', 'msssql' ];
+ $typesWithSchema = self::getDbTypesWithSchemas();
$lbConf += [
'localDomain' => new DatabaseDomain(
- $mainConfig->get( 'DBname' ),
- $mainConfig->get( 'DBmwschema' ),
- $mainConfig->get( 'DBprefix' )
+ $options->get( 'DBname' ),
+ $options->get( 'DBmwschema' ),
+ $options->get( 'DBprefix' )
),
'profiler' => function ( $section ) {
return Profiler::instance()->scopedProfileIn( $section );
'cliMode' => $wgCommandLineMode,
'hostname' => wfHostname(),
'readOnlyReason' => $readOnlyMode->getReason(),
- 'defaultGroup' => $mainConfig->get( 'DBDefaultGroup' ),
+ 'defaultGroup' => $options->get( 'DBDefaultGroup' ),
];
$serversCheck = [];
// Such as MysqlInstaller::openConnection and PostgresInstaller::openConnectionWithParams.
if ( $lbConf['class'] === Wikimedia\Rdbms\LBFactorySimple::class ) {
if ( isset( $lbConf['servers'] ) ) {
- // Server array is already explicitly configured; leave alone
- } elseif ( is_array( $mainConfig->get( 'DBservers' ) ) ) {
+ // Server array is already explicitly configured
+ } elseif ( is_array( $options->get( 'DBservers' ) ) ) {
$lbConf['servers'] = [];
- foreach ( $mainConfig->get( 'DBservers' ) as $i => $server ) {
- if ( $server['type'] === 'sqlite' ) {
- $server += [ 'dbDirectory' => $mainConfig->get( 'SQLiteDataDir' ) ];
- } elseif ( $server['type'] === 'postgres' ) {
- $server += [
- 'port' => $mainConfig->get( 'DBport' ),
- // Work around the reserved word usage in MediaWiki schema
- 'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ]
- ];
- } elseif ( $server['type'] === 'mssql' ) {
- $server += [
- 'port' => $mainConfig->get( 'DBport' ),
- 'useWindowsAuth' => $mainConfig->get( 'DBWindowsAuthentication' )
- ];
- }
-
- if ( in_array( $server['type'], $typesWithSchema, true ) ) {
- $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ];
- }
-
- $server += [
- 'tablePrefix' => $mainConfig->get( 'DBprefix' ),
- 'flags' => DBO_DEFAULT,
- 'sqlMode' => $mainConfig->get( 'SQLMode' ),
- ];
-
- $lbConf['servers'][$i] = $server;
+ foreach ( $options->get( 'DBservers' ) as $i => $server ) {
+ $lbConf['servers'][$i] = self::initServerInfo( $server, $options );
}
} else {
- $flags = DBO_DEFAULT;
- $flags |= $mainConfig->get( 'DebugDumpSql' ) ? DBO_DEBUG : 0;
- $flags |= $mainConfig->get( 'DBssl' ) ? DBO_SSL : 0;
- $flags |= $mainConfig->get( 'DBcompress' ) ? DBO_COMPRESS : 0;
- $server = [
- 'host' => $mainConfig->get( 'DBserver' ),
- 'user' => $mainConfig->get( 'DBuser' ),
- 'password' => $mainConfig->get( 'DBpassword' ),
- 'dbname' => $mainConfig->get( 'DBname' ),
- 'tablePrefix' => $mainConfig->get( 'DBprefix' ),
- 'type' => $mainConfig->get( 'DBtype' ),
- 'load' => 1,
- 'flags' => $flags,
- 'sqlMode' => $mainConfig->get( 'SQLMode' ),
- ];
- if ( in_array( $server['type'], $typesWithSchema, true ) ) {
- $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ];
- }
- if ( $server['type'] === 'sqlite' ) {
- $server[ 'dbDirectory'] = $mainConfig->get( 'SQLiteDataDir' );
- } elseif ( $server['type'] === 'postgres' ) {
- $server['port'] = $mainConfig->get( 'DBport' );
- // Work around the reserved word usage in MediaWiki schema
- $server['keywordTableMap'] = [ 'user' => 'mwuser', 'text' => 'pagecontent' ];
- } elseif ( $server['type'] === 'mssql' ) {
- $server['port'] = $mainConfig->get( 'DBport' );
- $server['useWindowsAuth'] = $mainConfig->get( 'DBWindowsAuthentication' );
- }
+ $server = self::initServerInfo(
+ [
+ 'host' => $options->get( 'DBserver' ),
+ 'user' => $options->get( 'DBuser' ),
+ 'password' => $options->get( 'DBpassword' ),
+ 'dbname' => $options->get( 'DBname' ),
+ 'type' => $options->get( 'DBtype' ),
+ 'load' => 1
+ ],
+ $options
+ );
+
+ $server['flags'] |= $options->get( 'DBssl' ) ? DBO_SSL : 0;
+ $server['flags'] |= $options->get( 'DBcompress' ) ? DBO_COMPRESS : 0;
+
$lbConf['servers'] = [ $server ];
}
if ( !isset( $lbConf['externalClusters'] ) ) {
- $lbConf['externalClusters'] = $mainConfig->get( 'ExternalServers' );
+ $lbConf['externalClusters'] = $options->get( 'ExternalServers' );
}
$serversCheck = $lbConf['servers'];
} elseif ( $lbConf['class'] === Wikimedia\Rdbms\LBFactoryMulti::class ) {
if ( isset( $lbConf['serverTemplate'] ) ) {
if ( in_array( $lbConf['serverTemplate']['type'], $typesWithSchema, true ) ) {
- $lbConf['serverTemplate']['schema'] = $mainConfig->get( 'DBmwschema' );
+ $lbConf['serverTemplate']['schema'] = $options->get( 'DBmwschema' );
}
- $lbConf['serverTemplate']['sqlMode'] = $mainConfig->get( 'SQLMode' );
+ $lbConf['serverTemplate']['sqlMode'] = $options->get( 'SQLMode' );
}
- $serversCheck = $lbConf['serverTemplate'] ?? [];
+ $serversCheck = [ $lbConf['serverTemplate'] ] ?? [];
}
- self::sanityCheckServerConfig( $serversCheck, $mainConfig );
- $lbConf = self::applyDefaultCaching( $lbConf, $srvCace, $mainStash, $wanCache );
+ self::assertValidServerConfigs( $serversCheck, $options->get( 'DBname' ),
+ $options->get( 'DBprefix' ) );
+
+ $lbConf = self::injectObjectCaches( $lbConf, $srvCace, $mainStash, $wanCache );
return $lbConf;
}
+ /**
+ * @return array
+ */
+ private static function getDbTypesWithSchemas() {
+ return [ 'postgres', 'msssql' ];
+ }
+
+ /**
+ * @param array $server
+ * @param ServiceOptions $options
+ * @return array
+ */
+ private static function initServerInfo( array $server, ServiceOptions $options ) {
+ if ( $server['type'] === 'sqlite' ) {
+ $httpMethod = $_SERVER['REQUEST_METHOD'] ?? null;
+ // T93097: hint for how file-based databases (e.g. sqlite) should go about locking.
+ // See https://www.sqlite.org/lang_transaction.html
+ // See https://www.sqlite.org/lockingv3.html#shared_lock
+ $isHttpRead = in_array( $httpMethod, [ 'GET', 'HEAD', 'OPTIONS', 'TRACE' ] );
+ $server += [
+ 'dbDirectory' => $options->get( 'SQLiteDataDir' ),
+ 'trxMode' => $isHttpRead ? 'DEFERRED' : 'IMMEDIATE'
+ ];
+ } elseif ( $server['type'] === 'postgres' ) {
+ $server += [
+ 'port' => $options->get( 'DBport' ),
+ // Work around the reserved word usage in MediaWiki schema
+ 'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ]
+ ];
+ } elseif ( $server['type'] === 'oracle' ) {
+ $server += [
+ // Work around the reserved word usage in MediaWiki schema
+ 'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ]
+ ];
+ } elseif ( $server['type'] === 'mssql' ) {
+ $server += [
+ 'port' => $options->get( 'DBport' ),
+ 'useWindowsAuth' => $options->get( 'DBWindowsAuthentication' )
+ ];
+ }
+
+ if ( in_array( $server['type'], self::getDbTypesWithSchemas(), true ) ) {
+ $server += [ 'schema' => $options->get( 'DBmwschema' ) ];
+ }
+
+ $flags = DBO_DEFAULT;
+ $flags |= $options->get( 'DebugDumpSql' ) ? DBO_DEBUG : 0;
+ $flags |= $options->get( 'DebugLogFile' ) ? DBO_DEBUG : 0;
+ if ( $server['type'] === 'oracle' ) {
+ $flags |= $options->get( 'DBOracleDRCP' ) ? DBO_PERSISTENT : 0;
+ }
+
+ $server += [
+ 'tablePrefix' => $options->get( 'DBprefix' ),
+ 'flags' => $flags,
+ 'sqlMode' => $options->get( 'SQLMode' ),
+ ];
+
+ return $server;
+ }
+
/**
* @param array $lbConf
* @param BagOStuff $sCache
* @param WANObjectCache $wCache
* @return array
*/
- private static function applyDefaultCaching(
+ private static function injectObjectCaches(
array $lbConf, BagOStuff $sCache, BagOStuff $mStash, WANObjectCache $wCache
) {
// Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
/**
* @param array $servers
- * @param Config $mainConfig
+ * @param string $lbDB Local domain database name
+ * @param string $lbTP Local domain prefix
*/
- private static function sanityCheckServerConfig( array $servers, Config $mainConfig ) {
- $ldDB = $mainConfig->get( 'DBname' ); // local domain DB
- $ldTP = $mainConfig->get( 'DBprefix' ); // local domain prefix
-
+ private static function assertValidServerConfigs( array $servers, $ldDB, $ldTP ) {
foreach ( $servers as $server ) {
$type = $server['type'] ?? null;
$srvDB = $server['dbname'] ?? null; // server DB
return $class;
}
- public static function setSchemaAliases( LBFactory $lbFactory, Config $config ) {
- if ( $config->get( 'DBtype' ) === 'mysql' ) {
+ /**
+ * @param LBFactory $lbFactory
+ * @param string $dbType 'mysql', 'sqlite', etc.
+ */
+ public static function setSchemaAliases( LBFactory $lbFactory, $dbType ) {
+ if ( $dbType instanceof Config ) {
+ // Before 1.34 this took a whole Config just to get $dbType
+ wfDeprecated( __METHOD__ . ' with Config argument', '1.34' );
+ $dbType = $dbType->get( 'DBtype' );
+ }
+ if ( $dbType === 'mysql' ) {
/**
* When SQLite indexes were introduced in r45764, it was noted that
* SQLite requires index names to be unique within the whole database,