Add preliminary MS SQL support

This likely has outstanding bugs but basic wiki operations work just fine in it.

Change-Id: I25df82065a307b9abc30c694f8c8afff0996d7c1
This commit is contained in:
Skizzerz 2014-01-02 21:04:26 -06:00 committed by Kunal Mehta
parent 3673bbf201
commit f7174057a4
13 changed files with 2670 additions and 1124 deletions

View file

@ -94,6 +94,12 @@ production.
callbacks for frequently occurring events.
* Special:ProtectedPages shows now a table. The timestamp, the reason and
the protecting user is also shown.
* Added experimental support for using Microsoft SQL Server as the database
backend.
** Added new Microsoft SQL Server-specific configuration variable
$wgDBWindowsAuthentication, which makes the web server authenticate against
the database server using Integrated Windows Authentication instead of
$wgDBuser/$wgDBpassword.
=== Bug fixes in 1.23 ===
* (bug 41759) The "updated since last visit" markers (on history pages, recent
@ -350,7 +356,7 @@ MediaWiki 1.23 requires PHP 5.3.2 or later.
MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
support for them is somewhat less mature. There is experimental support for
Oracle.
Oracle and Microsoft SQL Server.
The supported versions are:
@ -358,6 +364,7 @@ The supported versions are:
* PostgreSQL 8.3 or later
* SQLite 3.3.7 or later
* Oracle 9.0.1 or later
* Microsoft SQL Server 2005 (9.00.1399)
== Upgrading ==

View file

@ -474,7 +474,8 @@ $wgAutoloadLocalClasses = array(
'LoadMonitorMySQL' => 'includes/db/LoadMonitor.php',
'LoadMonitorNull' => 'includes/db/LoadMonitor.php',
'MssqlField' => 'includes/db/DatabaseMssql.php',
'MssqlResult' => 'includes/db/DatabaseMssql.php',
'MssqlBlob' => 'includes/db/DatabaseMssql.php',
'MssqlResultWrapper' => 'includes/db/DatabaseMssql.php',
'MySQLField' => 'includes/db/DatabaseMysqlBase.php',
'MySQLMasterPos' => 'includes/db/DatabaseMysqlBase.php',
'ORAField' => 'includes/db/DatabaseOracle.php',
@ -611,6 +612,8 @@ $wgAutoloadLocalClasses = array(
'InstallDocFormatter' => 'includes/installer/InstallDocFormatter.php',
'Installer' => 'includes/installer/Installer.php',
'LocalSettingsGenerator' => 'includes/installer/LocalSettingsGenerator.php',
'MssqlInstaller' => 'includes/installer/MssqlInstaller.php',
'MssqlUpdater' => 'includes/installer/MssqlUpdater.php',
'MysqlInstaller' => 'includes/installer/MysqlInstaller.php',
'MysqlUpdater' => 'includes/installer/MysqlUpdater.php',
'OracleInstaller' => 'includes/installer/OracleInstaller.php',

View file

@ -1585,7 +1585,7 @@ $wgSQLMode = '';
/**
* Mediawiki schema
*/
$wgDBmwschema = 'mediawiki';
$wgDBmwschema = null;
/**
* To override default SQLite data directory ($docroot/../data)
@ -1805,6 +1805,11 @@ $wgSlaveLagWarning = 10;
*/
$wgSlaveLagCritical = 30;
/**
* Use Windows Authentication instead of $wgDBuser / $wgDBpassword for MS SQL Server
*/
$wgDBWindowsAuthentication = false;
/**@}*/ # End of DB settings }
/************************************************************************//**

View file

@ -245,6 +245,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
protected $mTrxPreCommitCallbacks = array();
protected $mTablePrefix;
protected $mSchema;
protected $mFlags;
protected $mForeign;
protected $mErrorCount = 0;
@ -428,6 +429,15 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
return wfSetVar( $this->mTablePrefix, $prefix );
}
/**
* Get/set the db schema.
* @param string $schema The database schema to set, or omitted to leave it unchanged.
* @return string The previous db schema.
*/
public function dbSchema( $schema = null ) {
return wfSetVar( $this->mSchema, $schema );
}
/**
* Set the filehandle to copy write statements to.
*
@ -711,7 +721,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
* @param array $params Parameters passed from DatabaseBase::factory()
*/
function __construct( $params = null ) {
global $wgDBprefix, $wgCommandLineMode, $wgDebugDBTransactions;
global $wgDBprefix, $wgDBmwschema, $wgCommandLineMode, $wgDebugDBTransactions;
$this->mTrxAtomicLevels = new SplStack;
@ -722,6 +732,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
$dbName = $params['dbname'];
$flags = $params['flags'];
$tablePrefix = $params['tablePrefix'];
$schema = $params['schema'];
$foreign = $params['foreign'];
} else { // legacy calling pattern
wfDeprecated( __METHOD__ . " method called without parameter array.", "1.23" );
@ -732,6 +743,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
$dbName = isset( $args[3] ) ? $args[3] : false;
$flags = isset( $args[4] ) ? $args[4] : 0;
$tablePrefix = isset( $args[5] ) ? $args[5] : 'get from global';
$schema = 'get from global';
$foreign = isset( $args[6] ) ? $args[6] : false;
}
@ -757,6 +769,13 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
$this->mTablePrefix = $tablePrefix;
}
/** Get the database schema*/
if ( $schema == 'get from global' ) {
$this->mSchema = $wgDBmwschema;
} else {
$this->mSchema = $schema;
}
$this->mForeign = $foreign;
if ( $user ) {
@ -792,7 +811,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
*
* @param string $dbType A possible DB type
* @param array $p An array of options to pass to the constructor.
* Valid options are: host, user, password, dbname, flags, tablePrefix, driver
* Valid options are: host, user, password, dbname, flags, tablePrefix, schema, driver
* @throws MWException If the database driver or extension cannot be found
* @return DatabaseBase|null DatabaseBase subclass or null
*/
@ -832,6 +851,18 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
" no viable database extension found for type '$dbType'" );
}
// Determine schema defaults. Currently Microsoft SQL Server uses $wgDBmwschema,
// and everything else doesn't use a schema (e.g. null)
// Although postgres and oracle support schemas, we don't use them (yet)
// to maintain backwards compatibility
$defaultSchemas = array(
'mysql' => null,
'postgres' => null,
'sqlite' => null,
'oracle' => null,
'mssql' => 'get from global',
);
$class = 'Database' . ucfirst( $driver );
if ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) {
$params = array(
@ -841,6 +872,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
'dbname' => isset( $p['dbname'] ) ? $p['dbname'] : false,
'flags' => isset( $p['flags'] ) ? $p['flags'] : 0,
'tablePrefix' => isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global',
'schema' => isset( $p['schema'] ) ? $p['schema'] : $defaultSchemas[$dbType],
'foreign' => isset( $p['foreign'] ) ? $p['foreign'] : false
);
@ -2162,7 +2194,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
* @return string Full database name
*/
public function tableName( $name, $format = 'quoted' ) {
global $wgSharedDB, $wgSharedPrefix, $wgSharedTables;
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
@ -2186,10 +2218,17 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
# We reverse the explode so that database.table and table both output
# the correct table.
$dbDetails = explode( '.', $name, 2 );
if ( count( $dbDetails ) == 2 ) {
list( $database, $table ) = $dbDetails;
if ( count( $dbDetails ) == 3 ) {
list( $database, $schema, $table ) = $dbDetails;
# We don't want any prefix added in this case
$prefix = '';
} elseif ( count( $dbDetails ) == 2 ) {
list( $database, $table ) = $dbDetails;
# We don't want any prefix added in this case
# In dbs that support it, $database may actually be the schema
# but that doesn't affect any of the functionality here
$prefix = '';
$schema = null;
} else {
list( $table ) = $dbDetails;
if ( $wgSharedDB !== null # We have a shared database
@ -2198,19 +2237,30 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
&& in_array( $table, $wgSharedTables ) # A shared table is selected
) {
$database = $wgSharedDB;
$schema = $wgSharedSchema === null ? $this->mSchema : $wgSharedSchema;
$prefix = $wgSharedPrefix === null ? $this->mTablePrefix : $wgSharedPrefix;
} else {
$database = null;
$schema = $this->mSchema; # Default schema
$prefix = $this->mTablePrefix; # Default prefix
}
}
# 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 ) ) {
if ( $format == 'quoted' && !$this->isQuotedIdentifier( $tableName ) && $tableName !== '' ) {
$tableName = $this->addIdentifierQuotes( $tableName );
}
# Quote $schema and merge it with the table name if needed
if ( $schema !== null ) {
if ( $format == 'quoted' && !$this->isQuotedIdentifier( $schema ) ) {
$schema = $this->addIdentifierQuotes( $schema );
}
$tableName = $schema . '.' . $tableName;
}
# Quote $database and merge it with the table name if needed
if ( $database !== null ) {
if ( $format == 'quoted' && !$this->isQuotedIdentifier( $database ) ) {

File diff suppressed because it is too large Load diff

View file

@ -220,6 +220,7 @@ class DatabaseOracle extends DatabaseBase {
'dbname' => isset( $args[3] ) ? $args[3] : false,
'flags' => isset( $args[4] ) ? $args[4] : 0,
'tablePrefix' => isset( $args[5] ) ? $args[5] : 'get from global',
'schema' => 'get from global',
'foreign' => isset( $args[6] ) ? $args[6] : false
);
}

View file

@ -57,6 +57,7 @@ class DatabaseSqlite extends DatabaseBase {
'dbname' => isset( $args[3] ) ? $args[3] : false,
'flags' => isset( $args[4] ) ? $args[4] : 0,
'tablePrefix' => isset( $args[5] ) ? $args[5] : 'get from global',
'schema' => 'get from global',
'foreign' => isset( $args[6] ) ? $args[6] : false
);
}

View file

@ -52,7 +52,7 @@ class DBObject {
*/
class Blob {
/** @var string */
private $mData;
protected $mData;
function __construct( $data ) {
$this->mData = $data;

View file

@ -241,6 +241,7 @@ Consider putting the database somewhere else altogether, for example in <code>/v
'config-type-postgres' => 'PostgreSQL',
'config-type-sqlite' => 'SQLite',
'config-type-oracle' => 'Oracle',
'config-type-mssql' => 'Microsoft SQL Server',
'config-support-info' => 'MediaWiki supports the following database systems:
$1
@ -250,10 +251,12 @@ If you do not see the database system you are trying to use listed below, then f
'config-dbsupport-postgres' => '* [{{int:version-db-postgres-url}} PostgreSQL] is a popular open source database system as an alternative to MySQL. There may be some minor outstanding bugs, and it is not recommended for use in a production environment. ([http://www.php.net/manual/en/pgsql.installation.php How to compile PHP with PostgreSQL support])',
'config-dbsupport-sqlite' => '* [{{int:version-db-sqlite-url}} SQLite] is a lightweight database system that is very well supported. ([http://www.php.net/manual/en/pdo.installation.php How to compile PHP with SQLite support], uses PDO)',
'config-dbsupport-oracle' => '* [{{int:version-db-oracle-url}} Oracle] is a commercial enterprise database. ([http://www.php.net/manual/en/oci8.installation.php How to compile PHP with OCI8 support])',
'config-dbsupport-mssql' => '* [{{int:version-db-mssql-url}} Microsoft SQL Server] is a commercial enterprise database for Windows. ([http://www.php.net/manual/en/sqlsrv.installation.php How to compile PHP with SQLSRV support])',
'config-header-mysql' => 'MySQL settings',
'config-header-postgres' => 'PostgreSQL settings',
'config-header-sqlite' => 'SQLite settings',
'config-header-oracle' => 'Oracle settings',
'config-header-mssql' => 'Microsoft SQL Server settings',
'config-invalid-db-type' => 'Invalid database type',
'config-missing-db-name' => 'You must enter a value for "Database name"',
'config-missing-db-host' => 'You must enter a value for "Database host"',
@ -272,6 +275,7 @@ Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).',
'config-db-sys-create-oracle' => 'Installer only supports using a SYSDBA account for creating a new account.',
'config-db-sys-user-exists-oracle' => 'User account "$1" already exists. SYSDBA can only be used for creating of a new account!',
'config-postgres-old' => 'PostgreSQL $1 or later is required. You have $2.',
'config-mssql-old' => 'Microsoft SQL Server $1 or later is required. You have $2.',
'config-sqlite-name-help' => 'Choose a name that identifies your wiki.
Do not use spaces or hyphens.
This will be used for the SQLite data file name.',
@ -352,6 +356,13 @@ This is more efficient than MySQL's UTF-8 mode, and allows you to use the full r
In <strong>UTF-8 mode</strong>, MySQL will know what character set your data is in, and can present and convert it appropriately, but it will not let you store characters above the [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
'config-mssql-auth' => 'Authentication type:',
'config-mssql-install-auth' => 'Select the authentication type that will be used to connect to the database during the installation process.
If you select "Windows Authentication", the credentials of whatever user the webserver is running as will be used.',
'config-mssql-web-auth' => 'Select the authentication type that the web server will use to connect to the database server, during ordinary operation of the wiki.
If you select "Windows Authentication", the credentials of whatever user the webserver is running as will be used.',
'config-mssql-sqlauth' => 'SQL Server Authentication',
'config-mssql-windowsauth' => 'Windows Authentication',
'config-site-name' => 'Name of wiki:',
'config-site-name-help' => "This will appear in the title bar of the browser and in various other places.",
'config-site-name-blank' => 'Enter a site name.',
@ -705,6 +716,8 @@ Used in help box.',
'config-type-postgres' => '{{optional}}',
'config-type-sqlite' => '{{optional}}',
'config-type-oracle' => '{{optional}}',
'config-type-mssql' => '{{optional}}',
'config-header-mssql' => 'Used as a section heading on the installer form, inside of a fieldset',
'config-support-info' => 'Parameters:
* $1 - a list of DBMSs that MediaWiki supports, composed with config-dbsupport-* messages.',
'config-support-mysql' => 'Parameters:
@ -723,6 +736,8 @@ Used in help box.',
* $1 - database server name
See also:
* {{msg-mw|Config-db-host-oracle-help}}',
'config-support-mssql' => 'Parameters:
* $1 - a link to the Microsoft SQL Server home page, the anchor text of which is "Microsoft SQL Server".',
'config-invalid-db-name' => 'Used as error message. Parameters:
* $1 - database name
See also:
@ -740,6 +755,9 @@ If you\'re translating this message to a right-to-left language, consider writin
'config-postgres-old' => 'Used as error message. Used as warning. Parameters:
* $1 - minimum version
* $2 - the version of PostgreSQL that has been installed',
'config-mssql-old' => 'Used as an error message. Parameters:
* $1 - minimum version
* $2 - the version of Microsoft SQL Server that has been installed',
'config-sqlite-parent-unwritable-group' => 'Used as SQLite error message. Parameters:
* $1 - data directory
* $2 - "dirname" part of $1
@ -762,6 +780,11 @@ See also:
* $1 - filename',
'config-sqlite-cant-create-db' => 'Used as SQLite error message. Parameters:
* $1 - filename',
'config-mssql-auth' => 'radio button label',
'config-mssql-install-auth' => 'Used as the help text for the "Authentication type" radio button when typing in database settings for installation',
'config-mssql-web-auth' => 'Used as the help text for the "Authentication type" radio button when typing in database settings for normal wiki usage',
'config-mssql-sqlauth' => 'Radio button',
'config-mssql-windowsauth' => 'Radio button. The official term is "Integrated Windows Authentication" but Microsoft itself uses "Windows Authentication" elsewhere in Microsoft SQL Server as a synonym.',
'config-can-upgrade' => 'Parameters:
* $1 - Version or Revision indicator.',
'config-upgrade-done' => 'Used as success message. Parameters:
@ -4894,7 +4917,7 @@ Instalación anulada.',
'config-using531' => 'MediaWiki no puede utilizarse con PHP $1 debido a un error con los parámetros de referencia para <code>__call()</code> .
Actualice el sistema a PHP 5.3.2 o superior, o vuelva a la versión PHP 5.3.0 para resolver este problema.
Instalación anulada.',
'config-suhosin-max-value-length' => 'Suhosin está instalado y limita el parámetro <code>length</code> GET a $1 bytes.
'config-suhosin-max-value-length' => 'Suhosin está instalado y limita el parámetro <code>length</code> GET a $1 bytes.
El componente ResourceLoader (gestor de recursos) de MediaWiki trabajará en este límite, pero eso perjudicará el rendimiento.
Si es posible, deberías establecer <code>suhosin.get.max_value_length</code> en el valor 1024 o superior en <code>php.ini</code> y establecer <code>$wgResourceLoaderMaxQueryLength</code> en el mismo valor en <code>php.ini</code>.',
'config-db-type' => 'Tipo de base de datos',
@ -4932,7 +4955,7 @@ Esta no es la contraseña para la cuenta de MediaWiki; esta es la contraseña pa
'config-db-wiki-help' => 'Introduce el nombre de usuario y la contraseña que serán usados para acceder a la base de datos durante la operación normal del wiki.
Si esta cuenta no existe y la cuenta de instalación tiene suficientes privilegios, se creará esta cuenta de usuario con los privilegios mínimos necesarios para la operación normal del wiki.',
'config-db-prefix' => 'Prefijo para las tablas de la base de datos:',
'config-db-prefix-help' => 'Si necesita compartir una base de datos entre múltiples wikis, o entre MediaWiki y otra aplicación web, puede optar por agregar un prefijo a todos los nombres de tabla para evitar conflictos.
'config-db-prefix-help' => 'Si necesita compartir una base de datos entre múltiples wikis, o entre MediaWiki y otra aplicación web, puede optar por agregar un prefijo a todos los nombres de tabla para evitar conflictos.
No utilice espacios.
Normalmente se deja este campo vacío.',
@ -15509,7 +15532,7 @@ Jeśli korzystasz ze współdzielonego hostingu, dostawca usługi hostingowej mo
Możesz utworzyć konto użytkownika bazy danych podczas instalacji MediaWiki. Wówczas należy podać nazwę i hasło użytkownika z rolą SYSDBA w celu użycia go przez instalator do utworzenia nowe konta użytkownika, z którego korzystać będzie MediaWiki.
Możesz również skorzystać z konta użytkownika bazy danych utworzonego bezpośrednio w Oracle i wówczas wystarczy podać tylko nazwę i hasło tego użytkownika. Konto z rolą SYSDBA nie będzie potrzebne, jednak konto użytkownika powinno mieć uprawnienia do utworzenia obiektów w schemacie bazy danych. Możesz też podać dwa konta - konto dla instalatora, z pomocą którego zostaną obiekty w schemacie bazy danych i drugie konto, z którego będzie MediaWiki korzystać będzie do pracy.
Możesz również skorzystać z konta użytkownika bazy danych utworzonego bezpośrednio w Oracle i wówczas wystarczy podać tylko nazwę i hasło tego użytkownika. Konto z rolą SYSDBA nie będzie potrzebne, jednak konto użytkownika powinno mieć uprawnienia do utworzenia obiektów w schemacie bazy danych. Możesz też podać dwa konta - konto dla instalatora, z pomocą którego zostaną obiekty w schemacie bazy danych i drugie konto, z którego będzie MediaWiki korzystać będzie do pracy.
W podkatalogu "maintenance/oracle" znajduje się skrypt do tworzenia konta użytkownika. Korzystanie z konta użytkownika z ograniczonymi uprawnieniami spowoduje wyłączenie funkcji związanych z aktualizacją oprogramowania MediaWiki.',
'config-db-install-account' => 'Konto użytkownika dla instalatora',
@ -15900,7 +15923,7 @@ A la trovrà an LocalSetting.php.",
Për agiorné sta instalassion, për piasì anvece giré <code>update.php</code>",
'config-localsettings-key' => "Ciav d'agiornament:",
'config-localsettings-badkey' => "La ciav ch'it l'has dàit a l'é pa giusta.",
'config-upgrade-key-missing' => "A l'é stàita trovà n'istalassion esistenta ëd MediaWiki.
'config-upgrade-key-missing' => "A l'é stàita trovà n'istalassion esistenta ëd MediaWiki.
Për agiorné soa istalassion, për piasì ch'a buta la linia -sota al fond ëd <code>LocalSettings.php</code>:
$1",
@ -19593,7 +19616,7 @@ Ang mas masasalimuot na mga kaayusan ng mga karapatan ng tagagamit ay makukuha p
'config-license-gfdl' => 'Lisensiyang 1.3 ng Malayang Dokumentasyon ng GNU o mas lalong huli',
'config-license-pd' => 'Nasasakupan ng Madla',
'config-license-cc-choose' => 'Pumili ng isang pasadyang Lisensiya ng Malikhaing mga Pangkaraniwan',
'config-license-help' => "Maraming mga pangmadlang wiki ang naglalagay ng lahat ng mga ambag sa ilalim ng [http://freedomdefined.org/Definition lisensiyang malaya].
'config-license-help' => "Maraming mga pangmadlang wiki ang naglalagay ng lahat ng mga ambag sa ilalim ng [http://freedomdefined.org/Definition lisensiyang malaya].
Nakakatulong ito sa paglikha ng isang diwa ng pagmamay-ari ng pamayanan at nakapanghihikayat ng ambag na pangmahabang panahon.
Sa pangkalahatan, hindi kailangan ang isang wiking pribado o pangsamahan.
@ -20023,7 +20046,7 @@ MediaWiki вимагає підтримку UTF-8 для коректної ро
'config-mysql-old' => 'Необхідна MySQL $1 або пізніша, а у Вас $2.',
'config-db-port' => 'Порт бази даних:',
'config-db-schema' => 'Схема для MediaWiki',
'config-db-schema-help' => 'Ця схема зазвичай працює добре.
'config-db-schema-help' => 'Ця схема зазвичай працює добре.
Змінюйте її тільки якщо знаєте, що Вам це потрібно.',
'config-pg-test-error' => "Не вдається підключитися до бази даних '''$1''': $2",
'config-sqlite-dir' => 'Папка даних SQLite:',
@ -20250,7 +20273,7 @@ GFDL — допустима ліцензія, але у ній важко роз
'config-upload-deleted-help' => 'Оберіть папку для архівації видалених файлів.
В ідеалі, вона не має бути доступною через інтернет.',
'config-logo' => 'URL логотипу:',
'config-logo-help' => 'Стандартна схема оформлення MediaWiki містить вільне для логотипу місце над бічною панеллю розміром 135x160 пікселів.
'config-logo-help' => 'Стандартна схема оформлення MediaWiki містить вільне для логотипу місце над бічною панеллю розміром 135x160 пікселів.
Завантажте зображення відповідного розміру і введіть тут його URL.
@ -20370,9 +20393,9 @@ $messages['ur'] = array(
'config-git' => 'Git ورژن کنٹرول مصنع لطیف ملا: <code>$1</code> ۔',
'config-git-bad' => 'GIT ورژن کنٹرول مصنع لطیف نہيں ملا ۔',
'config-mysql-only-myisam-dep' => "' ' تنبیہ: ' '[[MyISAM|مائ اسام]] واحد دستیاب 'ذخیرہ جاتی انجن' ہے جو مائی ایس کیو ایل کے لیے ہے ، جو کہ ناموزوں ہے میڈیا وکی کے لیے ،کیوں کہ :
* یہ ہموار قطاروں کی سہولت بمشکل فراہم کرتا ہے
* یہ ہموار قطاروں کی سہولت بمشکل فراہم کرتا ہے
* یہ دوسرے انجنوں کے مقابلے زیادہ بگڑ جاتا ہے
* میڈیا وکی کوڈ بیس ہمیشہ سنبھال نہيں پاتا مائی اسام کو ۔
* میڈیا وکی کوڈ بیس ہمیشہ سنبھال نہيں پاتا مائی اسام کو ۔
آپ کا مائی ایس کیو ایل کا نصب ہمیشہ اننو ڈی بی کی سہولت نہيں دے سکتا ، ہو سکتا ہے یہ مزید ترقیاتی کام چاہے", # Fuzzy
'config-profile-fishbowl' => 'صرف مجاز ایڈیٹرز',

View file

@ -102,6 +102,7 @@ abstract class Installer {
'mysql',
'postgres',
'oracle',
'mssql',
'sqlite',
);

View file

@ -0,0 +1,692 @@
<?php
/**
* Microsoft SQL Server-specific installer.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Deployment
*/
/**
* Class for setting up the MediaWiki database using Microsoft SQL Server.
*
* @ingroup Deployment
* @since 1.23
*/
class MssqlInstaller extends DatabaseInstaller {
protected $globalNames = array(
'wgDBserver',
'wgDBname',
'wgDBuser',
'wgDBpassword',
'wgDBmwschema',
'wgDBprefix',
'wgDBWindowsAuthentication',
);
protected $internalDefaults = array(
'_InstallUser' => 'sa',
'_InstallWindowsAuthentication' => 'sqlauth',
'_WebWindowsAuthentication' => 'sqlauth',
);
public $minimumVersion = '9.00.1399'; // SQL Server 2005 RTM (TODO: are SQL Express version numbers different?)
// These are schema-level privs
// Note: the web user will be created will full permissions if possible, this permission
// list is only used if we are unable to grant full permissions.
public $webUserPrivs = array(
'DELETE',
'INSERT',
'SELECT',
'UPDATE',
'EXECUTE',
);
/**
* @return string
*/
public function getName() {
return 'mssql';
}
/**
* @return Bool
*/
public function isCompiled() {
return self::checkExtension( 'sqlsrv' );
}
/**
* @return string
*/
public function getConnectForm() {
if ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth' ) {
$displayStyle = 'display: none;';
} else {
$displayStyle = 'display: block;';
}
return $this->getTextBox(
'wgDBserver',
'config-db-host',
array(),
$this->parent->getHelpBox( 'config-db-host-help' )
) .
Html::openElement( 'fieldset' ) .
Html::element( 'legend', array(), wfMessage( 'config-db-wiki-settings' )->text() ) .
$this->getTextBox( 'wgDBname', 'config-db-name', array( 'dir' => 'ltr' ),
$this->parent->getHelpBox( 'config-db-name-help' ) ) .
$this->getTextBox( 'wgDBmwschema', 'config-db-schema', array( 'dir' => 'ltr' ),
$this->parent->getHelpBox( 'config-db-schema-help' ) ) .
$this->getTextBox( 'wgDBprefix', 'config-db-prefix', array( 'dir' => 'ltr' ),
$this->parent->getHelpBox( 'config-db-prefix-help' ) ) .
Html::closeElement( 'fieldset' ) .
Html::openElement( 'fieldset' ) .
Html::element( 'legend', array(), wfMessage( 'config-db-install-account' )->text() ) .
$this->getRadioSet( array(
'var' => '_InstallWindowsAuthentication',
'label' => 'config-mssql-auth',
'itemLabelPrefix' => 'config-mssql-',
'values' => array( 'sqlauth', 'windowsauth' ),
'itemAttribs' => array(
'sqlauth' => array(
'class' => 'showHideRadio',
'rel' => 'dbCredentialBox',
),
'windowsauth' => array(
'class' => 'hideShowRadio',
'rel' => 'dbCredentialBox',
)
),
'help' => $this->parent->getHelpBox( 'config-mssql-install-auth' )
) ) .
Html::openElement( 'div', array( 'id' => 'dbCredentialBox', 'style' => $displayStyle ) ) .
$this->getTextBox(
'_InstallUser',
'config-db-username',
array( 'dir' => 'ltr' ),
$this->parent->getHelpBox( 'config-db-install-username' )
) .
$this->getPasswordBox(
'_InstallPassword',
'config-db-password',
array( 'dir' => 'ltr' ),
$this->parent->getHelpBox( 'config-db-install-password' )
) .
Html::closeElement( 'div' ) .
Html::closeElement( 'fieldset' );
}
public function submitConnectForm() {
// Get variables from the request.
$newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBname', 'wgDBmwschema', 'wgDBprefix' ) );
// Validate them.
$status = Status::newGood();
if ( !strlen( $newValues['wgDBserver'] ) ) {
$status->fatal( 'config-missing-db-host' );
}
if ( !strlen( $newValues['wgDBname'] ) ) {
$status->fatal( 'config-missing-db-name' );
} elseif ( !preg_match( '/^[a-z0-9_]+$/i', $newValues['wgDBname'] ) ) {
$status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
}
if ( !preg_match( '/^[a-z0-9_]*$/i', $newValues['wgDBmwschema'] ) ) {
$status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
}
if ( !preg_match( '/^[a-z0-9_]*$/i', $newValues['wgDBprefix'] ) ) {
$status->fatal( 'config-invalid-db-prefix', $newValues['wgDBprefix'] );
}
if ( !$status->isOK() ) {
return $status;
}
// Check for blank schema and remap to dbo
if ( $newValues['wgDBmwschema'] === '' ) {
$this->setVar( 'wgDBmwschema', 'dbo' );
}
// User box
$this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword', '_InstallWindowsAuthentication' ) );
// Try to connect
$status = $this->getConnection();
if ( !$status->isOK() ) {
return $status;
}
/**
* @var $conn DatabaseBase
*/
$conn = $status->value;
// Check version
$version = $conn->getServerVersion();
if ( version_compare( $version, $this->minimumVersion ) < 0 ) {
return Status::newFatal( 'config-mssql-old', $this->minimumVersion, $version );
}
return $status;
}
/**
* @return Status
*/
public function openConnection() {
global $wgDBWindowsAuthentication;
$status = Status::newGood();
$user = $this->getVar( '_InstallUser' );
$password = $this->getVar( '_InstallPassword' );
if ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth' ) {
// Use Windows authentication for this connection
$wgDBWindowsAuthentication = true;
} else {
$wgDBWindowsAuthentication = false;
}
try {
$db = DatabaseBase::factory( 'mssql', array(
'host' => $this->getVar( 'wgDBserver' ),
'user' => $user,
'password' => $password,
'dbname' => false,
'flags' => 0,
'tablePrefix' => $this->getVar( 'wgDBprefix' ) ) );
$db->prepareStatements( false );
$db->scrollableCursor( false );
$status->value = $db;
} catch ( DBConnectionError $e ) {
$status->fatal( 'config-connection-error', $e->getMessage() );
}
return $status;
}
public function preUpgrade() {
global $wgDBuser, $wgDBpassword;
$status = $this->getConnection();
if ( !$status->isOK() ) {
$this->parent->showStatusError( $status );
return;
}
/**
* @var $conn DatabaseBase
*/
$conn = $status->value;
$conn->selectDB( $this->getVar( 'wgDBname' ) );
# Normal user and password are selected after this step, so for now
# just copy these two
$wgDBuser = $this->getVar( '_InstallUser' );
$wgDBpassword = $this->getVar( '_InstallPassword' );
}
/**
* Return true if the install user can create accounts
*
* @return bool
*/
public function canCreateAccounts() {
$status = $this->getConnection();
if ( !$status->isOK() ) {
return false;
}
/** @var $conn DatabaseBase */
$conn = $status->value;
// We need the server-level ALTER ANY LOGIN permission to create new accounts
$res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'SERVER' )" );
$serverPrivs = array(
'ALTER ANY LOGIN' => false,
'CONTROL SERVER' => false,
);
foreach ( $res as $row ) {
$serverPrivs[$row->permission_name] = true;
}
if ( !$serverPrivs['ALTER ANY LOGIN'] ) {
return false;
}
// Check to ensure we can grant everything needed as well
// We can't actually tell if we have WITH GRANT OPTION for a given permission, so we assume we do
// and just check for the permission
// http://technet.microsoft.com/en-us/library/ms178569.aspx
// The following array sets up which permissions imply whatever permissions we specify
$implied = array(
// schema database server
'DELETE' => array( 'DELETE', 'CONTROL SERVER' ),
'EXECUTE' => array( 'EXECUTE', 'CONTROL SERVER' ),
'INSERT' => array( 'INSERT', 'CONTROL SERVER' ),
'SELECT' => array( 'SELECT', 'CONTROL SERVER' ),
'UPDATE' => array( 'UPDATE', 'CONTROL SERVER' ),
);
$grantOptions = array_flip( $this->webUserPrivs );
// Check for schema and db-level permissions, but only if the schema/db exists
$schemaPrivs = $dbPrivs = array(
'DELETE' => false,
'EXECUTE' => false,
'INSERT' => false,
'SELECT' => false,
'UPDATE' => false,
);
$dbPrivs['ALTER ANY USER'] = false;
if ( $this->databaseExists( $this->getVar( 'wgDBname' ) ) ) {
$conn->selectDB( $this->getVar( 'wgDBname' ) );
$res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'DATABASE' )" );
foreach ( $res as $row ) {
$dbPrivs[$row->permission_name] = true;
}
// If the db exists, we need ALTER ANY USER privs on it to make a new user
if ( !$dbPrivs['ALTER ANY USER'] ) {
return false;
}
if ( $this->schemaExists( $this->getVar( 'wgDBmwschema' ) ) ) {
// wgDBmwschema is validated to only contain alphanumeric + underscore, so this is safe
$res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( '{$this->getVar( 'wgDBmwschema' )}', 'SCHEMA' )" );
foreach ( $res as $row ) {
$schemaPrivs[$row->permission_name] = true;
}
}
}
// Now check all the grants we'll need to be doing to see if we can
foreach ( $this->webUserPrivs as $permission ) {
if ( ( isset( $schemaPrivs[$permission] ) && $schemaPrivs[$permission] )
|| ( isset( $dbPrivs[$implied[$permission][0]] ) && $dbPrivs[$implied[$permission][0]] )
|| ( isset( $serverPrivs[$implied[$permission][1]] ) && $serverPrivs[$implied[$permission][1]] ) ) {
unset( $grantOptions[$permission] );
}
}
if ( count( $grantOptions ) ) {
// Can't grant everything
return false;
}
return true;
}
/**
* @return string
*/
public function getSettingsForm() {
if ( $this->canCreateAccounts() ) {
$noCreateMsg = false;
} else {
$noCreateMsg = 'config-db-web-no-create-privs';
}
$wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
$displayStyle = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ? 'display: none' : '';
$s = Html::openElement( 'fieldset' ) .
Html::element( 'legend', array(), wfMessage( 'config-db-web-account' )->text() ) .
$this->getCheckBox(
'_SameAccount', 'config-db-web-account-same',
array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' )
) .
Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) .
$this->getRadioSet( array(
'var' => '_WebWindowsAuthentication',
'label' => 'config-mssql-auth',
'itemLabelPrefix' => 'config-mssql-',
'values' => array( 'sqlauth', 'windowsauth' ),
'itemAttribs' => array(
'sqlauth' => array(
'class' => 'showHideRadio',
'rel' => 'dbCredentialBox',
),
'windowsauth' => array(
'class' => 'hideShowRadio',
'rel' => 'dbCredentialBox',
)
),
'help' => $this->parent->getHelpBox( 'config-mssql-web-auth' )
) ) .
Html::openElement( 'div', array( 'id' => 'dbCredentialBox', 'style' => $displayStyle ) ) .
$this->getTextBox( 'wgDBuser', 'config-db-username' ) .
$this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
Html::closeElement( 'div' );
if ( $noCreateMsg ) {
$s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() );
} else {
$s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
}
$s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' );
return $s;
}
/**
* @return Status
*/
public function submitSettingsForm() {
$this->setVarsFromRequest(
array( 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount', '_WebWindowsAuthentication' )
);
if ( $this->getVar( '_SameAccount' ) ) {
$this->setVar( '_WebWindowsAuthentication', $this->getVar( '_InstallWindowsAuthentication' ) );
$this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
$this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
}
if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
$this->setVar( 'wgDBuser', '' );
$this->setVar( 'wgDBpassword', '' );
$this->setVar( 'wgDBWindowsAuthentication', true );
} else {
$this->setVar( 'wgDBWindowsAuthentication', false );
}
if ( $this->getVar( '_CreateDBAccount' ) && $this->getVar( '_WebWindowsAuthentication' ) == 'sqlauth' && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) {
return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
}
// Validate the create checkbox
$canCreate = $this->canCreateAccounts();
if ( !$canCreate ) {
$this->setVar( '_CreateDBAccount', false );
$create = false;
} else {
$create = $this->getVar( '_CreateDBAccount' );
}
if ( !$create ) {
// Test the web account
$user = $this->getVar( 'wgDBuser' );
$password = $this->getVar( 'wgDBpassword' );
if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
$user = 'windowsauth';
$password = 'windowsauth';
}
try {
DatabaseBase::factory( 'mssql', array(
'host' => $this->getVar( 'wgDBserver' ),
'user' => $user,
'password' => $password,
'dbname' => false,
'flags' => 0,
'tablePrefix' => $this->getVar( 'wgDBprefix' ),
'schema' => $this->getVar( 'wgDBmwschema' ),
) );
} catch ( DBConnectionError $e ) {
return Status::newFatal( 'config-connection-error', $e->getMessage() );
}
}
return Status::newGood();
}
public function preInstall() {
# Add our user callback to installSteps, right before the tables are created.
$callback = array(
'name' => 'user',
'callback' => array( $this, 'setupUser' ),
);
$this->parent->addInstallStep( $callback, 'tables' );
}
/**
* @return Status
*/
public function setupDatabase() {
$status = $this->getConnection();
if ( !$status->isOK() ) {
return $status;
}
/** @var DatabaseBase $conn */
$conn = $status->value;
$dbName = $this->getVar( 'wgDBname' );
$schemaName = $this->getVar( 'wgDBmwschema' );
if ( !$this->databaseExists( $dbName ) ) {
$conn->query( "CREATE DATABASE " . $conn->addIdentifierQuotes( $dbName ), __METHOD__ );
$conn->selectDB( $dbName );
if ( !$this->schemaExists( $schemaName ) ) {
$conn->query( "CREATE SCHEMA " . $conn->addIdentifierQuotes( $schemaName ), __METHOD__ );
}
if ( !$this->catalogExists( $schemaName ) ) {
$conn->query( "CREATE FULLTEXT CATALOG " . $conn->addIdentifierQuotes( $schemaName ), __METHOD__ );
}
}
$this->setupSchemaVars();
return $status;
}
/**
* @return Status
*/
public function setupUser() {
$dbUser = $this->getVar( 'wgDBuser' );
if ( $dbUser == $this->getVar( '_InstallUser' )
|| ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth'
&& $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) ) {
return Status::newGood();
}
$status = $this->getConnection();
if ( !$status->isOK() ) {
return $status;
}
$this->setupSchemaVars();
$dbName = $this->getVar( 'wgDBname' );
$this->db->selectDB( $dbName );
$server = $this->getVar( 'wgDBserver' );
$password = $this->getVar( 'wgDBpassword' );
$schemaName = $this->getVar( 'wgDBmwschema' );
if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
$dbUser = 'windowsauth';
$password = 'windowsauth';
}
if ( $this->getVar( '_CreateDBAccount' ) ) {
$tryToCreate = true;
} else {
$tryToCreate = false;
}
$escUser = $this->db->addIdentifierQuotes( $dbUser );
$escDb = $this->db->addIdentifierQuotes( $dbName );
$escSchema = $this->db->addIdentifierQuotes( $schemaName );
$grantableNames = array();
if ( $tryToCreate ) {
$escPass = $this->db->addQuotes( $password );
if ( !$this->loginExists( $dbUser ) ) {
try {
$this->db->begin();
$this->db->selectDB( 'master' );
$logintype = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ? 'FROM WINDOWS' : "WITH PASSWORD = $escPass";
$this->db->query( "CREATE LOGIN $escUser $logintype" );
$this->db->selectDB( $dbName );
$this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
$this->db->commit();
$grantableNames[] = $dbUser;
} catch ( DBQueryError $dqe ) {
$this->db->rollback();
$status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
}
} elseif ( !$this->userExists( $dbUser ) ) {
try {
$this->db->begin();
$this->db->selectDB( $dbName );
$this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
$this->db->commit();
$grantableNames[] = $dbUser;
} catch ( DBQueryError $dqe ) {
$this->db->rollback();
$status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
}
} else {
$status->warning( 'config-install-user-alreadyexists', $dbUser );
$grantableNames[] = $dbUser;
}
}
// Try to grant to all the users we know exist or we were able to create
$this->db->selectDB( $dbName );
foreach ( $grantableNames as $name ) {
try {
// First try to grant full permissions
$fullPrivArr = array(
'BACKUP DATABASE', 'BACKUP LOG', 'CREATE FUNCTION', 'CREATE PROCEDURE',
'CREATE TABLE', 'CREATE VIEW', 'CREATE FULLTEXT CATALOG', 'SHOWPLAN'
);
$fullPrivList = implode( ', ', $fullPrivArr );
$this->db->begin();
$this->db->query( "GRANT $fullPrivList ON DATABASE :: $escDb TO $escUser", __METHOD__ );
$this->db->query( "GRANT CONTROL ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
$this->db->commit();
} catch ( DBQueryError $dqe ) {
// If that fails, try to grant the limited subset specified in $this->webUserPrivs
try {
$privList = implode( ', ', $this->webUserPrivs );
$this->db->rollback();
$this->db->begin();
$this->db->query( "GRANT $privList ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
$this->db->commit();
} catch ( DBQueryError $dqe ) {
$this->db->rollback();
$status->fatal( 'config-install-user-grant-failed', $dbUser, $dqe->getText() );
}
// Also try to grant SHOWPLAN on the db, but don't fail if we can't
// (just makes a couple things in mediawiki run slower since
// we have to run SELECT COUNT(*) instead of getting the query plan)
try {
$this->db->query( "GRANT SHOWPLAN ON DATABASE :: $escDb TO $escUser", __METHOD__ );
} catch ( DBQueryError $dqe ) {
}
}
}
return $status;
}
public function createTables() {
$status = parent::createTables();
// Do last-minute stuff like fulltext indexes (since they can't be inside a transaction)
if ( $status->isOk() ) {
$searchindex = $this->db->tableName( 'searchindex' );
$schema = $this->db->addIdentifierQuotes( $this->getVar( 'wgDBmwschema' ) );
try {
$this->db->query( "CREATE FULLTEXT INDEX ON $searchindex (si_title, si_text) KEY INDEX si_page ON $schema" );
} catch ( DBQueryError $dqe ) {
$status->fatal( 'config-install-tables-failed', $dqe->getText() );
}
}
return $status;
}
/**
* Try to see if the login exists
* @param string $user Username to check
* @return boolean
*/
private function loginExists( $user ) {
$res = $this->db->selectField( 'sys.sql_logins', 1, array( 'name' => $user ) );
return (bool)$res;
}
/**
* Try to see if the user account exists
* We assume we already have the appropriate database selected
* @param string $user Username to check
* @return boolean
*/
private function userExists( $user ) {
$res = $this->db->selectField( 'sys.sysusers', 1, array( 'name' => $user ) );
return (bool)$res;
}
/**
* Try to see if a given database exists
* @param string $dbName Database name to check
* @return boolean
*/
private function databaseExists( $dbName ) {
$res = $this->db->selectField( 'sys.databases', 1, array( 'name' => $dbName ) );
return (bool)$res;
}
/**
* Try to see if a given schema exists
* We assume we already have the appropriate database selected
* @param string $schemaName Schema name to check
* @return boolean
*/
private function schemaExists( $schemaName ) {
$res = $this->db->selectField( 'sys.schemas', 1, array( 'name' => $schemaName ) );
return (bool)$res;
}
/**
* Try to see if a given fulltext catalog exists
* We assume we already have the appropriate database selected
* @param string $schemaName Catalog name to check
* @return boolean
*/
private function catalogExists( $catalogName ) {
$res = $this->db->selectField( 'sys.fulltext_catalogs', 1, array( 'name' => $catalogName ) );
return (bool)$res;
}
/**
* Get variables to substitute into tables.sql and the SQL patch files.
*
* @return array
*/
public function getSchemaVars() {
return array(
'wgDBname' => $this->getVar( 'wgDBname' ),
'wgDBmwschema' => $this->getVar( 'wgDBmwschema' ),
'wgDBuser' => $this->getVar( 'wgDBuser' ),
'wgDBpassword' => $this->getVar( 'wgDBpassword' ),
);
}
public function getLocalSettings() {
$schema = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBmwschema' ) );
$prefix = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBprefix' ) );
$windowsauth = $this->getVar( 'wgDBWindowsAuthentication' ) ? 'true' : 'false';
return "# MSSQL specific settings
\$wgDBWindowsAuthentication = {$windowsauth};
\$wgDBmwschema = \"{$schema}\";
\$wgDBprefix = \"{$prefix}\";";
}
}

View file

@ -0,0 +1,46 @@
<?php
/**
* Microsoft SQL Server-specific installer.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Deployment
*/
/**
* Class for setting up the MediaWiki database using Microsoft SQL Server.
*
* @ingroup Deployment
* @since 1.23
*/
class MssqlUpdater extends DatabaseUpdater {
/**
* @var DatabaseMssql
*/
protected $db;
protected function getCoreUpdateList() {
return array(
array( 'disableContentHandlerUseDB' ),
// 1.23
);
}
}

File diff suppressed because it is too large Load diff