33require_once __DIR__ .
'/../../maintenance/Maintenance.php';
50 protected $updates = [];
57 protected $updatesSkipped = [];
63 protected $extensionUpdates = [];
86 protected $postDatabaseUpdateMaintenance = [
87 DeleteDefaultMessages::class,
88 PopulateRevisionLength::class,
89 PopulateRevisionSha1::class,
90 PopulateImageSha1::class,
91 FixExtLinksProtocolRelative::class,
92 PopulateFilearchiveSha1::class,
93 PopulateBacklinkNamespace::class,
94 FixDefaultJsonContentPages::class,
95 CleanupEmptyCategories::class,
96 AddRFCandPMIDInterwiki::class,
97 PopulatePPSortKey::class,
98 PopulateIpChanges::class,
99 RefreshExternallinksIndex::class,
114 protected $skipSchema =
false;
130 if ( $maintenance ) {
131 $this->maintenance = $maintenance;
132 $this->fileHandle = $maintenance->fileHandle;
136 $this->maintenance->
setDB( $db );
142 private function loadExtensionSchemaUpdates() {
143 $hookContainer = $this->loadExtensions();
144 (
new HookRunner( $hookContainer ) )->onLoadExtensionSchemaUpdates( $this );
153 private function loadExtensions() {
154 if ( $this->autoExtensionHookContainer ) {
156 return $this->autoExtensionHookContainer;
158 if ( defined(
'MW_EXTENSIONS_LOADED' ) ) {
159 throw new Exception( __METHOD__ .
160 ' apparently called from installer but no hook container was injected' );
162 if ( !defined(
'MEDIAWIKI_INSTALL' ) ) {
164 return MediaWikiServices::getInstance()->getHookContainer();
169 $queue = $registry->getQueue();
171 $registry->clearQueue();
174 $extInfo = $registry->readFromQueue(
$queue );
178 $legacySchemaHooks = $extInfo[
'globals'][
'wgHooks'][
'LoadExtensionSchemaUpdates'] ?? [];
179 if ( $vars && isset( $vars[
'wgHooks'][
'LoadExtensionSchemaUpdates'] ) ) {
180 $legacySchemaHooks = array_merge( $legacySchemaHooks, $vars[
'wgHooks'][
'LoadExtensionSchemaUpdates'] );
185 if ( $vars && isset( $vars[
'wgAutoloadClasses'] ) ) {
190 if ( !isset( $extInfo[
'autoloaderPaths'] )
191 || !isset( $extInfo[
'autoloaderClasses'] )
192 || !isset( $extInfo[
'autoloaderNS'] )
195 throw new LogicException(
'Missing autoloader keys from extracted extension info' );
203 [
'LoadExtensionSchemaUpdates' => $legacySchemaHooks ],
204 $extInfo[
'attributes'][
'Hooks'] ?? [],
205 $extInfo[
'attributes'][
'DeprecatedHooks'] ?? []
207 MediaWikiServices::getInstance()->getObjectFactory()
226 $class = ucfirst(
$type ) .
'Updater';
228 return new $class( $db,
$shared, $maintenance );
230 throw new MWException( __METHOD__ .
' called for unsupported $wgDBtype' );
242 $this->autoExtensionHookContainer = $hookContainer;
261 if ( $this->maintenance->isQuiet() ) {
266 $str = htmlspecialchars( $str );
285 $this->extensionUpdates[] = $update;
299 $this->extensionUpdates[] = [
'addTable', $tableName, $sqlPath,
true ];
313 $this->extensionUpdates[] = [
'addIndex', $tableName, $indexName, $sqlPath,
true ];
327 $this->extensionUpdates[] = [
'addField', $tableName, $columnName, $sqlPath,
true ];
341 $this->extensionUpdates[] = [
'dropField', $tableName, $columnName, $sqlPath,
true ];
355 $this->extensionUpdates[] = [
'dropIndex', $tableName, $indexName, $sqlPath,
true ];
368 $this->extensionUpdates[] = [
'dropTable', $tableName, $sqlPath,
true ];
385 $sqlPath, $skipBothIndexExistWarning =
false
387 $this->extensionUpdates[] = [
392 $skipBothIndexExistWarning,
409 $this->extensionUpdates[] = [
'modifyField', $tableName, $fieldName, $sqlPath,
true ];
422 $this->extensionUpdates[] = [
'modifyTable', $tableName, $sqlPath,
true ];
432 return ( $this->db->tableExists( $tableName, __METHOD__ ) );
445 $this->postDatabaseUpdateMaintenance[] = $class;
454 return $this->extensionUpdates;
463 return $this->postDatabaseUpdateMaintenance;
472 private function writeSchemaUpdateFile( array $schemaUpdate = [] ) {
473 $updates = $this->updatesSkipped;
474 $this->updatesSkipped = [];
476 foreach ( $updates as [ $func,
$args, $origParams ] ) {
480 $this->updatesSkipped[] = $origParams;
504 public function doUpdates( array $what = [
'core',
'extensions',
'stats' ] ) {
507 $what = array_fill_keys( $what,
true );
508 $this->skipSchema = isset( $what[
'noschema'] ) || $this->fileHandle !==
null;
509 if ( isset( $what[
'core'] ) ) {
513 if ( isset( $what[
'extensions'] ) ) {
514 $this->loadExtensionSchemaUpdates();
518 if ( isset( $what[
'stats'] ) ) {
522 if ( $this->fileHandle ) {
523 $this->skipSchema =
false;
524 $this->writeSchemaUpdateFile();
534 private function runUpdates( array $updates, $passSelf ) {
535 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
538 $updatesSkipped = [];
539 foreach ( $updates as $params ) {
540 $origParams = $params;
541 $func = array_shift( $params );
542 if ( !is_array( $func ) && method_exists( $this, $func ) ) {
543 $func = [ $this, $func ];
544 } elseif ( $passSelf ) {
545 array_unshift( $params, $this );
547 $ret = $func( ...$params );
549 if ( $ret !==
false ) {
550 $updatesDone[] = $origParams;
551 $lbFactory->waitForReplication( [
'timeout' => self::REPLICATION_WAIT_TIMEOUT ] );
553 $updatesSkipped[] = [ $func, $params, $origParams ];
556 $this->updatesSkipped = array_merge( $this->updatesSkipped, $updatesSkipped );
557 $this->updates = array_merge( $this->updates, $updatesDone );
570 if ( !$this->db->tableExists(
'updatelog', __METHOD__ ) ) {
574 $row = $this->db->selectRow(
578 [
'ul_key' => $key ],
600 if ( !$this->db->tableExists(
'updatelog', __METHOD__ ) ) {
605 $values = [
'ul_key' => $key ];
607 $values[
'ul_value'] = $val;
609 $this->db->insert(
'updatelog', $values, __METHOD__, [
'IGNORE' ] );
622 return $this->db->tableExists(
'updatelog', __METHOD__ ) &&
623 $this->db->fieldExists(
'updatelog',
'ul_value', __METHOD__ );
644 $this->
output(
"...skipping update to shared table $name.\n" );
668 $this->db->sourceFile(
693 if ( fwrite( $this->fileHandle,
$line ) ===
false ) {
712 if ( $msg ===
null ) {
713 $msg =
"Applying $path patch";
715 if ( $this->skipSchema ) {
716 $this->
output(
"...skipping schema change ($msg).\n" );
721 $this->
output(
"{$msg}..." );
723 if ( !$isFullPath ) {
726 if ( $this->fileHandle !==
null ) {
729 $this->db->sourceFile(
$path );
731 $this->
output(
"done.\n" );
745 $baseDir = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::BaseDirectory );
748 if ( file_exists(
"$baseDir/maintenance/$dbType/archives/$patch" ) ) {
749 return "$baseDir/maintenance/$dbType/archives/$patch";
751 return "$baseDir/maintenance/archives/$patch";
766 protected function addTable( $name, $patch, $fullpath =
false ) {
767 if ( !$this->
doTable( $name ) ) {
771 if ( $this->db->tableExists( $name, __METHOD__ ) ) {
772 $this->
output(
"...$name table already exists.\n" );
774 return $this->
applyPatch( $patch, $fullpath,
"Creating $name table" );
792 protected function addField( $table, $field, $patch, $fullpath =
false ) {
793 if ( !$this->
doTable( $table ) ) {
797 if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
798 $this->
output(
"...$table table does not exist, skipping new field patch.\n" );
799 } elseif ( $this->db->fieldExists( $table, $field, __METHOD__ ) ) {
800 $this->
output(
"...have $field field in $table table.\n" );
802 return $this->
applyPatch( $patch, $fullpath,
"Adding $field field to table $table" );
820 protected function addIndex( $table, $index, $patch, $fullpath =
false ) {
821 if ( !$this->
doTable( $table ) ) {
825 if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
826 $this->
output(
"...skipping: '$table' table doesn't exist yet.\n" );
827 } elseif ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
828 $this->
output(
"...index $index already set on $table table.\n" );
830 return $this->
applyPatch( $patch, $fullpath,
"Adding index $index to table $table" );
848 protected function dropField( $table, $field, $patch, $fullpath =
false ) {
849 if ( !$this->
doTable( $table ) ) {
853 if ( $this->db->fieldExists( $table, $field, __METHOD__ ) ) {
854 return $this->
applyPatch( $patch, $fullpath,
"Table $table contains $field field. Dropping" );
856 $this->
output(
"...$table table does not contain $field field.\n" );
874 protected function dropIndex( $table, $index, $patch, $fullpath =
false ) {
875 if ( !$this->
doTable( $table ) ) {
879 if ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
880 return $this->
applyPatch( $patch, $fullpath,
"Dropping $index index from table $table" );
882 $this->
output(
"...$index key doesn't exist.\n" );
905 $skipBothIndexExistWarning, $patch, $fullpath =
false
907 if ( !$this->
doTable( $table ) ) {
912 if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
913 $this->
output(
"...skipping: '$table' table doesn't exist yet.\n" );
919 if ( $this->db->indexExists( $table, $newIndex, __METHOD__ ) ) {
920 $this->
output(
"...index $newIndex already set on $table table.\n" );
921 if ( !$skipBothIndexExistWarning &&
922 $this->db->indexExists( $table, $oldIndex, __METHOD__ )
924 $this->
output(
"...WARNING: $oldIndex still exists, despite it has " .
925 "been renamed into $newIndex (which also exists).\n" .
926 " $oldIndex should be manually removed if not needed anymore.\n" );
933 if ( !$this->db->indexExists( $table, $oldIndex, __METHOD__ ) ) {
934 $this->
output(
"...skipping: index $oldIndex doesn't exist.\n" );
943 "Renaming index $oldIndex into $newIndex to table $table"
961 protected function dropTable( $table, $patch =
false, $fullpath =
false ) {
962 if ( !$this->
doTable( $table ) ) {
966 if ( $this->db->tableExists( $table, __METHOD__ ) ) {
967 $msg =
"Dropping table $table";
969 if ( $patch ===
false ) {
970 $this->
output(
"$msg ..." );
971 $this->db->dropTable( $table, __METHOD__ );
972 $this->
output(
"done.\n" );
974 return $this->
applyPatch( $patch, $fullpath, $msg );
977 $this->
output(
"...$table doesn't exist.\n" );
997 protected function modifyField( $table, $field, $patch, $fullpath =
false ) {
998 if ( !$this->
doTable( $table ) ) {
1002 $updateKey =
"$table-$field-$patch";
1003 if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
1004 $this->
output(
"...$table table does not exist, skipping modify field patch.\n" );
1005 } elseif ( !$this->db->fieldExists( $table, $field, __METHOD__ ) ) {
1006 $this->
output(
"...$field field does not exist in $table table, " .
1007 "skipping modify field patch.\n" );
1009 $this->
output(
"...$field in table $table already modified by patch $patch.\n" );
1011 $apply = $this->
applyPatch( $patch, $fullpath,
"Modifying $field field of table $table" );
1035 if ( !$this->
doTable( $table ) ) {
1039 $updateKey =
"$table-$patch";
1040 if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
1041 $this->
output(
"...$table table does not exist, skipping modify table patch.\n" );
1043 $this->
output(
"...table $table already modified by patch $patch.\n" );
1045 $apply = $this->
applyPatch( $patch, $fullpath,
"Modifying table $table" );
1075 $this->
output(
"Running $class...\n" );
1076 $task = $this->maintenance->runChild( $class );
1077 $ok = $task->execute();
1079 throw new RuntimeException(
"Execution of $class did not complete successfully." );
1081 $this->
output(
"done.\n" );
1090 $repo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
1091 $zonePath = $repo->getZonePath(
'temp' );
1092 if ( $repo->getBackend()->directoryExists( [
'dir' => $zonePath ] ) ) {
1094 $status = $repo->getBackend()->secure( [
1099 if ( $status->isOK() ) {
1100 $this->
output(
"Set the local repo temp zone container to be private.\n" );
1102 $this->
output(
"Failed to set the local repo temp zone container to be private.\n" );
1114 $this->
output(
"Purging caches..." );
1117 $this->db->delete(
'objectcache',
'*', __METHOD__ );
1125 $services = MediaWikiServices::getInstance();
1127 $services->getResourceLoader(),
1129 $services->getMainWANObjectCache()
1131 $blobStore->clear();
1134 $this->db->delete(
'module_deps',
'*', __METHOD__ );
1135 $this->
output(
"done.\n" );
1142 $this->
output(
"...site_stats is populated..." );
1143 $row = $this->db->selectRow(
'site_stats',
'*', [
'ss_row_id' => 1 ], __METHOD__ );
1144 if ( $row ===
false ) {
1145 $this->
output(
"data is missing! rebuilding...\n" );
1146 } elseif ( isset( $row->site_stats ) && $row->ss_total_pages == -1 ) {
1147 $this->
output(
"missing ss_total_pages, rebuilding...\n" );
1149 $this->
output(
"done.\n" );
1156 # Common updater functions
1163 if ( $this->db->selectField(
1170 $this->
output(
"...collations up-to-date.\n" );
1175 $this->
output(
"Updating category collations..." );
1176 $task = $this->maintenance->runChild( UpdateCollation::class );
1178 $this->
output(
"...done.\n" );
1185 $this->
output(
"Converting djvu metadata..." );
1186 $task = $this->maintenance->runChild( RefreshImageMetadata::class );
1187 '@phan-var RefreshImageMetadata $task';
1188 $task->loadParamsAndArgs( RefreshImageMetadata::class, [
1190 'mediatype' =>
'OFFICE',
1191 'mime' =>
'image/*',
1195 $ok = $task->execute();
1196 if ( $ok !==
false ) {
1197 $this->
output(
"...done.\n" );
1209 $cl = $this->maintenance->runChild(
1210 RebuildLocalisationCache::class,
'rebuildLocalisationCache.php'
1212 '@phan-var RebuildLocalisationCache $cl';
1213 $this->
output(
"Rebuilding localisation cache...\n" );
1216 $this->
output(
"done.\n" );
1220 if ( $this->
updateRowExists( MigrateLinksTable::class .
'templatelinks' ) ) {
1221 $this->
output(
"...templatelinks table has already been migrated.\n" );
1227 $task = $this->maintenance->runChild(
1228 MigrateLinksTable::class,
'migrateLinksTable.php'
1230 '@phan-var MigrateLinksTable $task';
1231 $task->loadParamsAndArgs( MigrateLinksTable::class, [
1233 'table' =>
'templatelinks'
1235 $this->
output(
"Running migrateLinksTable.php on templatelinks...\n" );
1237 $this->
output(
"done.\n" );
1247 "Migrating comments to the 'comments' table, printing progress markers. For large\n" .
1248 "databases, you may want to hit Ctrl-C and do this manually with\n" .
1249 "maintenance/migrateComments.php.\n"
1251 $task = $this->maintenance->runChild( MigrateComments::class,
'migrateComments.php' );
1252 $ok = $task->execute();
1253 $this->
output( $ok ?
"done.\n" :
"errors were encountered.\n" );
1262 if ( $this->
tableExists(
'image_comment_temp' ) ) {
1263 $this->
output(
"Merging image_comment_temp into the image table\n" );
1264 $task = $this->maintenance->runChild(
1265 MigrateImageCommentTemp::class,
'migrateImageCommentTemp.php'
1269 $ok = $task->execute();
1270 $this->
output( $ok ?
"done.\n" :
"errors were encountered.\n" );
1272 $this->
dropTable(
'image_comment_temp' );
1284 "Migrating actors to the 'actor' table, printing progress markers. For large\n" .
1285 "databases, you may want to hit Ctrl-C and do this manually with\n" .
1286 "maintenance/migrateActors.php.\n"
1288 $task = $this->maintenance->runChild( MigrateActors::class,
'migrateActors.php' );
1289 $ok = $task->execute();
1290 $this->
output( $ok ?
"done.\n" :
"errors were encountered.\n" );
1299 if ( $this->db->fieldExists(
'archive',
'ar_text', __METHOD__ ) ) {
1300 $this->
output(
"Migrating archive ar_text to modern storage.\n" );
1301 $task = $this->maintenance->runChild( MigrateArchiveText::class,
'migrateArchiveText.php' );
1304 if ( $task->execute() ) {
1305 $this->
applyPatch(
'patch-drop-ar_text.sql',
false,
1306 'Dropping ar_text and ar_flags columns' );
1316 $info = $this->db->fieldInfo(
'archive',
'ar_rev_id' );
1318 throw new MWException(
'Missing ar_rev_id field of archive table. Should not happen.' );
1320 if ( $info->isNullable() ) {
1321 $this->
output(
"Populating ar_rev_id.\n" );
1322 $task = $this->maintenance->runChild( PopulateArchiveRevId::class,
'populateArchiveRevId.php' );
1323 if ( $task->execute() ) {
1324 $this->
applyPatch(
'patch-ar_rev_id-not-null.sql',
false,
1325 'Making ar_rev_id not nullable' );
1335 if ( !$this->
updateRowExists(
'populate externallinks.el_index_60' ) ) {
1337 "Populating el_index_60 field, printing progress markers. For large\n" .
1338 "databases, you may want to hit Ctrl-C and do this manually with\n" .
1339 "maintenance/populateExternallinksIndex60.php.\n"
1341 $task = $this->maintenance->runChild( PopulateExternallinksIndex60::class,
1342 'populateExternallinksIndex60.php' );
1344 $this->
output(
"done.\n" );
1355 "Migrating revision data to the MCR 'slot' and 'content' tables, printing progress markers.\n" .
1356 "For large databases, you may want to hit Ctrl-C and do this manually with\n" .
1357 "maintenance/populateContentTables.php.\n"
1359 $task = $this->maintenance->runChild(
1360 PopulateContentTables::class,
'populateContentTables.php'
1362 $ok = $task->execute();
1363 $this->
output( $ok ?
"done.\n" :
"errors were encountered.\n" );
1386 if ( $table === $this ) {
1389 $func = array_shift( $params );
1392 if ( $this->db->tableExists( $table, __METHOD__ ) ) {
1396 if ( !is_array( $func ) && method_exists( $this, $func ) ) {
1397 $func = [ $this, $func ];
1398 } elseif ( $passSelf ) {
1399 array_unshift( $params, $this );
1403 return $func( ...$params );
1423 if ( $table === $this ) {
1427 $func = array_shift( $params );
1430 if ( !$this->db->tableExists( $table, __METHOD__ ) ||
1431 !$this->db->fieldExists( $table, $field, __METHOD__ )
1436 if ( !is_array( $func ) && method_exists( $this, $func ) ) {
1437 $func = [ $this, $func ];
1438 } elseif ( $passSelf ) {
1439 array_unshift( $params, $this );
1443 return $func( ...$params );
global $wgCommandLineMode
static registerClasses(array $files)
Register a file to load the given class from.
static loadFiles(array $files)
Batch version of loadFile()
static registerNamespaces(array $dirs)
Register a directory to load the classes of a given namespace from, per PSR4.
Class for handling database updates.
purgeCache()
Purge various database caches.
addExtensionTable( $tableName, $sqlPath)
Convenience wrapper for addExtensionUpdate() when adding a new table (which is the most common usage ...
getDB()
Get a database connection to run updates.
setFileAccess()
Set any .htaccess files or equivalent for storage repos.
migrateImageCommentTemp()
Merge image_comment_temp into the image table.
addIndex( $table, $index, $patch, $fullpath=false)
Add a new index to an existing table.
array $updates
Array of updates to perform on the database.
modifyExtensionTable( $tableName, $sqlPath)
Modify an existing extension table.
bool $skipSchema
Flag specifying whether or not to skip schema (e.g.
populateArchiveRevId()
Populate ar_rev_id, then make it not nullable.
runMaintenance( $class, $unused='')
Run a maintenance script.
migrateArchiveText()
Migrate ar_text to modern storage.
addField( $table, $field, $patch, $fullpath=false)
Add a new field to an existing table.
addExtensionIndex( $tableName, $indexName, $sqlPath)
Add an index to an existing extension table.
modifyTable( $table, $patch, $fullpath=false)
Modify an existing table, similar to modifyField.
doUpdates(array $what=[ 'core', 'extensions', 'stats'])
Do all the updates.
ifTableNotExists( $table, $func,... $params)
Only run a function if a table does not exist.
updateRowExists( $key)
Helper function: check if the given key is present in the updatelog table.
const REPLICATION_WAIT_TIMEOUT
getCoreUpdateList()
Get an array of updates to perform on the database.
populateExternallinksIndex60()
Populates the externallinks.el_index_60 field.
output( $str)
Output some text.
getPostDatabaseUpdateMaintenance()
getExtensionUpdates()
Get the list of extension-defined updates.
insertUpdateRow( $key, $val=null)
Helper function: Add a key to the updatelog table.
setAutoExtensionHookContainer(HookContainer $hookContainer)
Set the HookContainer to use for loading extension schema updates.
canUseNewUpdatelog()
Updatelog was changed in 1.17 to have a ul_value column so we can record more information about what ...
patchPath(IDatabase $db, $patch)
Get the full path of a patch file.
copyFile( $filename)
Append an SQL fragment to the open file handle.
string[] $postDatabaseUpdateMaintenance
Scripts to run after database update Should be a subclass of LoggedUpdateMaintenance.
HookContainer null $autoExtensionHookContainer
dropExtensionTable( $tableName, $sqlPath=false)
Drop an extension table.
resource null $fileHandle
File handle for SQL output.
renameIndex( $table, $oldIndex, $newIndex, $skipBothIndexExistWarning, $patch, $fullpath=false)
Rename an index from an existing table.
rebuildLocalisationCache()
Rebuilds the localisation cache.
addExtensionField( $tableName, $columnName, $sqlPath)
Add a field to an existing extension table.
IMaintainableDatabase $db
Handle to the database subclass.
ifFieldExists( $table, $field, $func,... $params)
Only run a function if the named field exists.
addTable( $name, $patch, $fullpath=false)
Add a new table to the database.
modifyField( $table, $field, $patch, $fullpath=false)
Modify an existing field.
dropExtensionField( $tableName, $columnName, $sqlPath)
Drop a field from an extension table.
static newForDB(IMaintainableDatabase $db, $shared=false, Maintenance $maintenance=null)
addPostDatabaseUpdateMaintenance( $class)
Add a maintenance script to be run after the database updates are complete.
dropField( $table, $field, $patch, $fullpath=false)
Drop a field from an existing table.
doCollationUpdate()
Update CategoryLinks collation.
renameExtensionIndex( $tableName, $oldIndexName, $newIndexName, $sqlPath, $skipBothIndexExistWarning=false)
Rename an index on an extension table Intended for use in LoadExtensionSchemaUpdates hook handlers.
migrateActors()
Migrate actors to the new 'actor' table.
addExtensionUpdate(array $update)
Add a new update coming from an extension.
array $updatesSkipped
Array of updates that were skipped.
appendLine( $line)
Append a line to the open filehandle.
dropExtensionIndex( $tableName, $indexName, $sqlPath)
Drop an index from an extension table Intended for use in LoadExtensionSchemaUpdates hook handlers.
array $extensionUpdates
List of extension-provided database updates.
checkStats()
Check the site_stats table is not properly populated.
modifyExtensionField( $tableName, $fieldName, $sqlPath)
Modify an existing field in an extension table.
applyPatch( $path, $isFullPath=false, $msg=null)
Applies a SQL patch.
dropIndex( $table, $index, $patch, $fullpath=false)
Drop an index from an existing table.
populateContentTables()
Populates the MCR content tables.
__construct(IMaintainableDatabase &$db, $shared, Maintenance $maintenance=null)
dropTable( $table, $patch=false, $fullpath=false)
If the specified table exists, drop it, or execute the patch if one is provided.
migrateComments()
Migrate comments to the new 'comment' table.
getSchemaVars()
Get appropriate schema variables in the current database connection.
doTable( $name)
Returns whether updates should be executed on the database table $name.
Fake maintenance wrapper, mostly used for the web installer/updater.
static getExistingLocalSettings()
Determine if LocalSettings.php exists.
static getDBTypes()
Get a list of known DB types.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
setDB(IMaintainableDatabase $db)
Sets database object to be returned by getDB().
A class containing constants representing the names of configuration variables.
static doAllAndCommit( $database, array $options=[])
Do all updates and commit them.
$wgSharedTables
Config variable stub for the SharedTables setting, for use by phpdoc and IDEs.
$wgCategoryCollation
Config variable stub for the CategoryCollation setting, for use by phpdoc and IDEs.
$wgSharedDB
Config variable stub for the SharedDB setting, for use by phpdoc and IDEs.
$wgLocalisationCacheConf
Config variable stub for the LocalisationCacheConf setting, for use by phpdoc and IDEs.
Advanced database interface for IDatabase handles that include maintenance methods.