X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=maintenance%2Fupdaters.inc;h=a49c87579795b8fef067852337a687c65439caac;hb=bd5f56332bed6f6fc6881cda77e3982893ff30e2;hp=a5576594ad8f8657a7d81620d346b647a2160fd1;hpb=28bdb2118c73f32e49f19fefd321f0cab7360026;p=lhc%2Fweb%2Fwiklou.git diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index a5576594ad..a49c875797 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -1,10 +1,9 @@ selectRow( + 'updatelog', + '1', + array( 'ul_key' => $key ), + __FUNCTION__ + ); + return (bool)$row; +} + function rename_table( $from, $to, $patch ) { global $wgDatabase; if ( $wgDatabase->tableExists( $from ) ) { @@ -140,9 +224,9 @@ function add_field( $table, $field, $patch, $fullpath=false ) { function add_index( $table, $index, $patch, $fullpath=false ) { global $wgDatabase; if( $wgDatabase->indexExists( $table, $index ) ) { - echo "...$index key already set.\n"; + echo "...$index key already set on $table table.\n"; } else { - echo "Adding $index key... "; + echo "Adding $index key to table $table... "; if( $fullpath ) { dbsource( $patch, $wgDatabase ); } else { @@ -263,6 +347,28 @@ function do_archive_user_index() { } } +function do_image_user_index() { + global $wgDatabase; + if( $wgDatabase->indexExists( 'image', 'img_usertext_timestamp' ) ) { + echo "...usertext,timestamp key on image already exists.\n"; + } else { + echo "Adding usertext,timestamp key on image table... "; + dbsource( archive("patch-image-user-index.sql"), $wgDatabase ); + echo "ok\n"; + } +} + +function do_oldimage_user_index() { + global $wgDatabase; + if( $wgDatabase->indexExists( 'oldimage', 'oi_usertext_timestamp' ) ) { + echo "...usertext,timestamp key on oldimage already exists.\n"; + } else { + echo "Adding usertext,timestamp key on oldimage table... "; + dbsource( archive("patch-oldimage-user-index.sql"), $wgDatabase ); + echo "ok\n"; + } +} + function do_watchlist_update() { global $wgDatabase; $fname = 'do_watchlist_update'; @@ -348,20 +454,20 @@ function do_user_update() { * 1.4 betas were missing the 'binary' marker from logging.log_title, * which causes a collation mismatch error on joins in MySQL 4.1. */ -function do_logging_encoding() { +function check_bin( $table, $field, $patchFile ) { global $wgDatabase, $wgDBtype; if ($wgDBtype != 'mysql') return; - $logging = $wgDatabase->tableName( 'logging' ); - $res = $wgDatabase->query( "SELECT log_title FROM $logging LIMIT 0" ); - $flags = explode( ' ', mysql_field_flags( $res, 0 ) ); + $tableName = $wgDatabase->tableName( $table ); + $res = $wgDatabase->query( "SELECT $field FROM $tableName LIMIT 0" ); + $flags = explode( ' ', mysql_field_flags( $res->result, 0 ) ); $wgDatabase->freeResult( $res ); if( in_array( 'binary', $flags ) ) { - echo "Logging table has correct title encoding.\n"; + echo "$table table has correct $field encoding.\n"; } else { - echo "Fixing title encoding on logging table... "; - dbsource( archive( 'patch-logging-title.sql' ), $wgDatabase ); + echo "Fixing $field encoding on $table table... "; + dbsource( archive( $patchFile ), $wgDatabase ); echo "ok\n"; } } @@ -454,7 +560,7 @@ function do_schema_restructuring() { UNIQUE INDEX name_title (page_namespace,page_title), INDEX (page_random), INDEX (page_len) - ) TYPE=InnoDB", $fname ); + ) ENGINE=InnoDB", $fname ); $wgDatabase->query("CREATE TABLE $revision ( rev_id int(8) unsigned NOT NULL auto_increment, rev_page int(8) unsigned NOT NULL, @@ -472,7 +578,7 @@ function do_schema_restructuring() { INDEX page_timestamp (rev_page,rev_timestamp), INDEX user_timestamp (rev_user,rev_timestamp), INDEX usertext_timestamp (rev_user_text,rev_timestamp) - ) TYPE=InnoDB", $fname ); + ) ENGINE=InnoDB", $fname ); echo wfTimestamp( TS_DB ); echo "......Locking tables.\n"; @@ -824,32 +930,26 @@ function do_templatelinks_update() { echo "Done. Please run maintenance/refreshLinks.php for a more thorough templatelinks update.\n"; } -# July 2006 -# Add ( rc_namespace, rc_user_text ) index [R. Church] +// Add index on ( rc_namespace, rc_user_text ) [Jul. 2006] +// Add index on ( rc_user_text, rc_timestamp ) [Nov. 2006] function do_rc_indices_update() { global $wgDatabase; echo( "Checking for additional recent changes indices...\n" ); - # See if we can find the index we want - $info = $wgDatabase->indexInfo( 'recentchanges', 'rc_ns_usertext', __METHOD__ ); - if( !$info ) { - # None, so create - echo( "...index on ( rc_namespace, rc_user_text ) not found; creating\n" ); - dbsource( archive( 'patch-recentchanges-utindex.sql' ) ); - } else { - # Index seems to exist - echo( "...index on ( rc_namespace, rc_user_text ) seems to be ok\n" ); - } - #Add (rc_user_text, rc_timestamp) index [A. Garrett], November 2006 - # See if we can find the index we want - $info = $wgDatabase->indexInfo( 'recentchanges', 'rc_user_text', __METHOD__ ); - if( !$info ) { - # None, so create - echo( "...index on ( rc_user_text, rc_timestamp ) not found; creating\n" ); - dbsource( archive( 'patch-rc_user_text-index.sql' ) ); - } else { - # Index seems to exist - echo( "...index on ( rc_user_text, rc_timestamp ) seems to be ok\n" ); + $indexes = array( + 'rc_ns_usertext' => 'patch-recentchanges-utindex.sql', + 'rc_user_text' => 'patch-rc_user_text-index.sql', + ); + + foreach( $indexes as $index => $patch ) { + $info = $wgDatabase->indexInfo( 'recentchanges', $index, __METHOD__ ); + if( !$info ) { + echo( "...index `{$index}` not found; adding..." ); + dbsource( archive( $patch ) ); + echo( "done.\n" ); + } else { + echo( "...index `{$index}` seems ok.\n" ); + } } } @@ -876,6 +976,7 @@ function do_backlinking_indices_update() { !index_has_field('imagelinks', 'il_to', 'il_from')) { dbsource( archive( 'patch-backlinkindexes.sql' ) ); + echo( "...backlinking indices updated\n" ); } } @@ -884,6 +985,31 @@ function do_categorylinks_indices_update() { if (!index_has_field('categorylinks', 'cl_sortkey', 'cl_from')) { dbsource( archive( 'patch-categorylinksindex.sql' ) ); + echo( "...categorylinks indices updated\n" ); + } +} + +function do_filearchive_indices_update() { + global $wgDatabase; + echo( "Checking filearchive indices...\n" ); + $info = $wgDatabase->indexInfo( 'filearchive', 'fa_user_timestamp', __METHOD__ ); + if ( !$info ) + { + dbsource( archive( 'patch-filearhive-user-index.sql' ) ); + echo( "...filearchive indices updated\n" ); + } +} + +function maybe_do_profiling_memory_update() { + global $wgDatabase; + if ( !$wgDatabase->tableExists( 'profiling' ) ) { + // Simply ignore + } elseif ( $wgDatabase->fieldExists( 'profiling', 'pf_memory' ) ) { + echo "profiling table has pf_memory field.\n"; + } else { + echo "Adding pf_memory field to table profiling..."; + dbsource( archive( 'patch-profiling-memory.sql' ), $wgDatabase ); + echo "ok\n"; } } @@ -894,13 +1020,32 @@ function do_stats_init() { $row = $wgDatabase->selectRow( 'site_stats', '*', array( 'ss_row_id' => 1 ), __METHOD__ ); if( $row === false ) { echo "data is missing! rebuilding...\n"; - - global $IP; - require_once "$IP/maintenance/initStats.inc"; - wfInitStats(); + } elseif ( isset( $row->site_stats ) && $row->ss_total_pages == -1 ) { + echo "missing ss_total_pages, rebuilding...\n"; } else { echo "ok.\n"; + return; + } + + global $IP; + require_once "$IP/maintenance/initStats.inc"; + wfInitStats(); +} + +function do_active_users_init() { + global $wgDatabase; + $activeUsers = $wgDatabase->selectField( 'site_stats', 'ss_active_users', false, __METHOD__ ); + if( $activeUsers == -1 ) { + $activeUsers = $wgDatabase->selectField( 'recentchanges', + 'COUNT( DISTINCT rc_user_text )', + array( 'rc_user != 0', 'rc_bot' => 0, "rc_log_type != 'newusers'" ), __METHOD__ + ); + $wgDatabase->update( 'site_stats', + array( 'ss_active_users' => intval($activeUsers) ), + array( 'ss_row_id' => 1 ), __METHOD__, array( 'LIMIT' => 1 ) + ); } + echo( "...ss_active_users user count set...\n" ); } function purge_cache() { @@ -913,36 +1058,26 @@ function purge_cache() { } function do_all_updates( $shared = false, $purge = true ) { - global $wgNewTables, $wgNewFields, $wgRenamedTables, $wgSharedDB, $wgDatabase, $wgDBtype, $IP; + global $wgNewTables, $wgNewFields, $wgRenamedTables, $wgSharedDB, $wgSharedTables, $wgDatabase, $wgDBtype, $IP; wfRunHooks('LoadExtensionSchemaUpdates'); - $doUser = !$wgSharedDB || $shared; + $doUser = $shared ? $wgSharedDB && in_array('user', $wgSharedTables) : !$wgSharedDB || !in_array('user', $wgSharedTables); if ($wgDBtype === 'postgres') { do_postgres_updates(); return; } - - # Rename tables - foreach ( $wgRenamedTables as $tableRecord ) { - rename_table( $tableRecord[0], $tableRecord[1], $tableRecord[2] ); - } - - # Add missing tables - foreach ( $wgNewTables as $tableRecord ) { - add_table( $tableRecord[0], $tableRecord[1] ); - flush(); - } - - # Add missing fields - foreach ( $wgNewFields as $fieldRecord ) { - if ( $fieldRecord[0] != 'user' || $doUser ) { - add_field( $fieldRecord[0], $fieldRecord[1], $fieldRecord[2] ); - } + + # Run core updates in sequence... + global $wgMysqlUpdates; + foreach( $wgMysqlUpdates as $params ) { + $func = array_shift( $params ); + call_user_func_array( $func, $params ); flush(); } + /// @fixme clean up this mess too! global $wgExtNewTables, $wgExtNewFields, $wgExtNewIndexes; # Add missing extension tables foreach ( $wgExtNewTables as $tableRecord ) { @@ -962,52 +1097,6 @@ function do_all_updates( $shared = false, $purge = true ) { flush(); } - # Do schema updates which require special handling - do_interwiki_update(); flush(); - do_index_update(); flush(); - do_old_links_update(); flush(); - do_image_name_unique_update(); flush(); - do_watchlist_update(); flush(); - if ( $doUser ) { - do_user_update(); flush(); - } -###### do_copy_newtalk_to_watchlist(); flush(); - do_logging_encoding(); flush(); - - do_schema_restructuring(); flush(); - do_inverse_timestamp(); flush(); - do_text_id(); flush(); - do_namespace_size(); flush(); - - do_pagelinks_update(); flush(); - do_templatelinks_update(); flush(); // after pagelinks - - do_drop_img_type(); flush(); - - if ( $doUser ) { - do_user_unique_update(); flush(); - } - do_user_groups_update(); flush(); - - do_watchlist_null(); flush(); - - //do_image_index_update(); flush(); - - do_logging_timestamp_index(); flush(); - - do_page_random_update(); flush(); - - do_rc_indices_update(); flush(); - - add_table( 'redirect', 'patch-redirect.sql' ); - - do_backlinking_indices_update(); flush(); - - do_categorylinks_indices_update(); flush(); - - do_restrictions_update(); flush (); - - do_archive_user_index(); flush (); echo "Deleting old default messages (this may take a long time!)..."; flush(); deleteDefaultMessages(); @@ -1104,7 +1193,54 @@ function do_restrictions_update() { } print "ok\n"; } +} + +function do_category_population() { + if( update_row_exists( 'populate category' ) ) { + echo "...category table already populated.\n"; + return; + } + require_once( 'populateCategory.inc' ); + echo "Populating category table, printing progress markers. ". +"For large databases, you\n". +"may want to hit Ctrl-C and do this manually with maintenance/\n". +"populateCategory.php.\n"; + populateCategory( '', 10, 0, true ); + echo "Done populating category table.\n"; +} + +function do_populate_parent_id() { + if( update_row_exists( 'populate rev_parent_id' ) ) { + echo "...rev_parent_id column already populated.\n"; + return; + } + require_once( 'populateParentId.inc' ); + global $wgDatabase; + populate_rev_parent_id( $wgDatabase ); +} + +function update_password_format() { + if ( update_row_exists( 'password format' ) ) { + echo "...password hash format already changed\n"; + return; + } + + echo "Updating password hash format..."; + + global $wgDatabase, $wgPasswordSalt; + $user = $wgDatabase->tableName( 'user' ); + if ( $wgPasswordSalt ) { + $sql = "UPDATE $user SET user_password=CONCAT(':B:', user_id, ':', user_password) " . + "WHERE user_password NOT LIKE ':%'"; + } else { + $sql = "UPDATE $user SET user_password=CONCAT(':A:', user_password) " . + "WHERE user_password NOT LIKE ':%'"; + } + $wgDatabase->query( $sql, __METHOD__ ); + $wgDatabase->insert( 'updatelog', array( 'ul_key' => 'password format' ), __METHOD__ ); + + echo "done\n"; } function @@ -1238,6 +1374,10 @@ END; function do_postgres_updates() { global $wgDatabase, $wgVersion, $wgDBmwschema, $wgDBts2schema, $wgShowExceptionDetails, $wgDBuser; + ## Gather version numbers in case we need them + $version = $wgDatabase->getServerVersion(); ## long string + $numver = $wgDatabase->numeric_version; ## X.Y e.g. 8.3 + $wgShowExceptionDetails = 1; # Just in case their LocalSettings.php does not have this: @@ -1246,25 +1386,34 @@ function do_postgres_updates() { # Verify that this user is configured correctly $safeuser = $wgDatabase->addQuotes($wgDBuser); - $SQL = "SELECT array_to_string(useconfig,'*') FROM pg_user WHERE usename = $safeuser"; + $SQL = "SELECT array_to_string(useconfig,'*') FROM pg_catalog.pg_user WHERE usename = $safeuser"; $config = pg_fetch_result( $wgDatabase->doQuery( $SQL ), 0, 0 ); $conf = array(); foreach( explode( '*', $config ) as $c ) { list( $x,$y ) = explode( '=', $c ); $conf[$x] = $y; } - $newpath = array(); - if( !array_key_exists( 'search_path', $conf ) or strpos( $conf['search_path'],$wgDBmwschema ) === false ) { - print "Adding in schema \"$wgDBmwschema\" to search_path for user \"$wgDBuser\"\n"; - $newpath[$wgDBmwschema] = 1; + if( !array_key_exists( 'search_path', $conf ) ) { + $search_path = ''; + } + else { + $search_path = $conf['search_path']; + } + if( strpos( $search_path, $wgDBmwschema ) === false ) { + echo "Adding in schema \"$wgDBmwschema\" to search_path for user \"$wgDBuser\"\n"; + $search_path = "$wgDBmwschema, $search_path"; } - if( !array_key_exists( 'search_path', $conf ) or strpos( $conf['search_path'],$wgDBts2schema ) === false ) { - print "Adding in schema \"$wgDBts2schema\" to search_path for user \"$wgDBuser\"\n"; - $newpath[$wgDBts2schema] = 1; + if( strpos( $search_path, $wgDBts2schema ) === false ) { + echo "Adding in schema \"$wgDBts2schema\" to search_path for user \"$wgDBuser\"\n"; + $search_path = "$search_path, $wgDBts2schema"; } - $searchpath = implode( ',', array_keys( $newpath ) ); - if( strlen( $searchpath ) ) { - $wgDatabase->doQuery( "ALTER USER $wgDBuser SET search_path = $searchpath" ); + if( array_key_exists( 'search_path', $conf ) === false || $search_path != $conf['search_path'] ) { + $wgDatabase->doQuery( "ALTER USER $wgDBuser SET search_path = $search_path" ); + $wgDatabase->doQuery( "SET search_path = $search_path" ); + } + else { + $path = $conf['search_path']; + echo "... search_path for user \"$wgDBuser\" looks correct ($path)\n"; } $goodconf = array( 'client_min_messages' => 'error', @@ -1274,8 +1423,12 @@ function do_postgres_updates() { foreach( array_keys( $goodconf ) AS $key ) { $value = $goodconf[$key]; if( !array_key_exists( $key, $conf ) or $conf[$key] !== $value ) { - print "Setting $key to '$value' for user \"$wgDBuser\"\n"; + echo "Setting $key to '$value' for user \"$wgDBuser\"\n"; $wgDatabase->doQuery( "ALTER USER $wgDBuser SET $key = '$value'" ); + $wgDatabase->doQuery( "SET $key = '$value'" ); + } + else { + echo "... default value of \"$key\" is correctly set to \"$value\" for user \"$wgDBuser\"\n"; } } @@ -1285,35 +1438,47 @@ function do_postgres_updates() { ); $newtables = array( + array("category", "patch-category.sql"), array("mediawiki_version", "patch-mediawiki_version.sql"), array("mwuser", "patch-mwuser.sql"), array("pagecontent", "patch-pagecontent.sql"), array("querycachetwo", "patch-querycachetwo.sql"), + array("page_props", "patch-page_props.sql"), array("page_restrictions", "patch-page_restrictions.sql"), array("profiling", "patch-profiling.sql"), + array("protected_titles", "patch-protected_titles.sql"), array("redirect", "patch-redirect.sql"), + array("updatelog", "patch-updatelog.sql"), ); $newcols = array( + array("archive", "ar_deleted", "SMALLINT NOT NULL DEFAULT 0"), array("archive", "ar_len", "INTEGER"), - array("ipblocks", "ipb_anon_only", "CHAR NOT NULL DEFAULT '0'"), - array("ipblocks", "ipb_block_email", "CHAR NOT NULL DEFAULT '0'"), - array("ipblocks", "ipb_create_account", "CHAR NOT NULL DEFAULT '1'"), - array("ipblocks", "ipb_deleted", "INTEGER NOT NULL DEFAULT 0"), - array("ipblocks", "ipb_enable_autoblock", "CHAR NOT NULL DEFAULT '1'"), - array("filearchive", "fa_deleted", "INTEGER NOT NULL DEFAULT 0"), - array("logging", "log_deleted", "INTEGER NOT NULL DEFAULT 0"), + array("archive", "ar_page_id", "INTEGER"), + array("archive", "ar_parent_id", "INTEGER"), + array("image", "img_sha1", "TEXT NOT NULL DEFAULT ''"), + array("ipblocks", "ipb_anon_only", "SMALLINT NOT NULL DEFAULT 0"), + array("ipblocks", "ipb_by_text", "TEXT NOT NULL DEFAULT ''"), + array("ipblocks", "ipb_block_email", "SMALLINT NOT NULL DEFAULT 0"), + array("ipblocks", "ipb_create_account", "SMALLINT NOT NULL DEFAULT 1"), + array("ipblocks", "ipb_deleted", "SMALLINT NOT NULL DEFAULT 0"), + array("ipblocks", "ipb_enable_autoblock", "SMALLINT NOT NULL DEFAULT 1"), + array("ipblocks", "ipb_allow_usertalk", "SMALLINT NOT NULL DEFAULT 0"), + array("filearchive", "fa_deleted", "SMALLINT NOT NULL DEFAULT 0"), + array("logging", "log_deleted", "SMALLINT NOT NULL DEFAULT 0"), array("logging", "log_id", "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('log_log_id_seq')"), array("logging", "log_params", "TEXT"), array("mwuser", "user_editcount", "INTEGER"), array("mwuser", "user_newpass_time", "TIMESTAMPTZ"), - array("oldimage", "oi_metadata", "BYTEA NOT NULL"), - array("oldimage", "oi_media_type", "TEXT NOT NULL"), + array("oldimage", "oi_deleted", "SMALLINT NOT NULL DEFAULT 0"), + array("oldimage", "oi_metadata", "BYTEA NOT NULL DEFAULT ''"), + array("oldimage", "oi_media_type", "TEXT"), array("oldimage", "oi_major_mime", "TEXT NOT NULL DEFAULT 'unknown'"), array("oldimage", "oi_minor_mime", "TEXT NOT NULL DEFAULT 'unknown'"), - array("oldimage", "oi_deleted", "CHAR NOT NULL DEFAULT '0'"), + array("oldimage", "oi_sha1", "TEXT NOT NULL DEFAULT ''"), array("page_restrictions", "pr_id", "INTEGER NOT NULL UNIQUE DEFAULT nextval('pr_id_val')"), - array("recentchanges", "rc_deleted", "INTEGER NOT NULL DEFAULT 0"), + array("profiling", "pf_memory", "NUMERIC(18,10) NOT NULL DEFAULT 0"), + array("recentchanges", "rc_deleted", "SMALLINT NOT NULL DEFAULT 0"), array("recentchanges", "rc_log_action", "TEXT"), array("recentchanges", "rc_log_type", "TEXT"), array("recentchanges", "rc_logid", "INTEGER NOT NULL DEFAULT 0"), @@ -1321,26 +1486,70 @@ function do_postgres_updates() { array("recentchanges", "rc_old_len", "INTEGER"), array("recentchanges", "rc_params", "TEXT"), array("revision", "rev_len", "INTEGER"), + array("revision", "rev_deleted", "SMALLINT NOT NULL DEFAULT 0"), + array("user_newtalk", "user_last_timestamp", "TIMESTAMPTZ"), + array("site_stats", "ss_active_users", "INTEGER DEFAULT '-1'"), + array("revision", "rev_parent_id", "INTEGER DEFAULT NULL"), ); - # table, column, desired type, USING clause if needed + # table, column, desired type, USING clause if needed (with new default if needed) $typechanges = array( - array("image", "img_size", "int4", ""), - array("image", "img_width", "int4", ""), - array("image", "img_height", "int4", ""), - array("ipblocks", "ipb_address", "text", "ipb_address::text"), - array("math", "math_inputhash", "bytea", "decode(math_inputhash,'escape')"), - array("math", "math_outputhash", "bytea", "decode(math_outputhash,'escape')"), - array("oldimage", "oi_size", "int4", ""), - array("oldimage", "oi_width", "int4", ""), - array("oldimage", "oi_height", "int4", ""), - array("user_newtalk", "user_ip", "text", "host(user_ip)"), + array("archive", "ar_deleted", "smallint", ""), + array("archive", "ar_minor_edit", "smallint", "ar_minor_edit::smallint DEFAULT 0"), + array("filearchive", "fa_deleted", "smallint", ""), + array("filearchive", "fa_height", "integer", ""), + array("filearchive", "fa_metadata", "bytea", "decode(fa_metadata,'escape')"), + array("filearchive", "fa_size", "integer", ""), + array("filearchive", "fa_width", "integer", ""), + array("filearchive", "fa_storage_group","text", ""), + array("filearchive", "fa_storage_key", "text", ""), + array("image", "img_metadata", "bytea", "decode(img_metadata,'escape')"), + array("image", "img_size", "integer", ""), + array("image", "img_width", "integer", ""), + array("image", "img_height", "integer", ""), + array("interwiki", "iw_local", "smallint", "iw_local::smallint DEFAULT 0"), + array("interwiki", "iw_trans", "smallint", "iw_trans::smallint DEFAULT 0"), + array("ipblocks", "ipb_auto", "smallint", "ipb_auto::smallint DEFAULT 0"), + array("ipblocks", "ipb_anon_only", "smallint", "CASE WHEN ipb_anon_only=' ' THEN 0 ELSE ipb_anon_only::smallint END DEFAULT 0"), + array("ipblocks", "ipb_create_account", "smallint", "CASE WHEN ipb_create_account=' ' THEN 0 ELSE ipb_create_account::smallint END DEFAULT 1"), + array("ipblocks", "ipb_enable_autoblock", "smallint", "CASE WHEN ipb_enable_autoblock=' ' THEN 0 ELSE ipb_enable_autoblock::smallint END DEFAULT 1"), + array("ipblocks", "ipb_block_email", "smallint", "CASE WHEN ipb_block_email=' ' THEN 0 ELSE ipb_block_email::smallint END DEFAULT 0"), + array("ipblocks", "ipb_address", "text", "ipb_address::text"), + array("ipblocks", "ipb_deleted", "smallint", "ipb_deleted::smallint"), + array("math", "math_inputhash", "bytea", "decode(math_inputhash,'escape')"), + array("math", "math_outputhash", "bytea", "decode(math_outputhash,'escape')"), + array("mwuser", "user_token", "text", ""), + array("mwuser", "user_email_token","text", ""), + array("objectcache", "keyname", "text", ""), + array("oldimage", "oi_height", "integer", ""), + array("oldimage", "oi_metadata", "bytea", "decode(img_metadata,'escape')"), + array("oldimage", "oi_size", "integer", ""), + array("oldimage", "oi_width", "integer", ""), + array("page", "page_is_redirect","smallint", "page_is_redirect::smallint DEFAULT 0"), + array("page", "page_is_new", "smallint", "page_is_new::smallint DEFAULT 0"), + array("querycache", "qc_value", "integer", ""), + array("querycachetwo","qcc_value", "integer", ""), + array("recentchanges","rc_bot", "smallint", "rc_bot::smallint DEFAULT 0"), + array("recentchanges","rc_deleted", "smallint", ""), + array("recentchanges","rc_minor", "smallint", "rc_minor::smallint DEFAULT 0"), + array("recentchanges","rc_new", "smallint", "rc_new::smallint DEFAULT 0"), + array("recentchanges","rc_type", "smallint", "rc_type::smallint DEFAULT 0"), + array("recentchanges","rc_patrolled", "smallint", "rc_patrolled::smallint DEFAULT 0"), + array("revision", "rev_deleted", "smallint", "rev_deleted::smallint DEFAULT 0"), + array("revision", "rev_minor_edit", "smallint", "rev_minor_edit::smallint DEFAULT 0"), + array("templatelinks","tl_namespace", "smallint", "tl_namespace::smallint"), + array("user_newtalk", "user_ip", "text", "host(user_ip)"), ); $newindexes = array( - array("revision", "rev_text_id_idx", "patch-rev_text_id_idx.sql"), - array("archive", "usertext_timestamp", "patch-archive-user-index.sql"), + array("archive", "archive_user_text", "(ar_user_text)"), + array("image", "img_sha1", "(img_sha1)"), + array("oldimage", "oi_sha1", "(oi_sha1)"), + array("revision", "rev_text_id_idx", "(rev_text_id)"), + array("recentchanges", "rc_timestamp_nobot", "(rc_timestamp) WHERE rc_bot = 0"), + array("templatelinks", "templatelinks_from", "(tl_from)"), + array("watchlist", "wl_user", "(wl_user)"), ); $newrules = array( @@ -1348,48 +1557,48 @@ function do_postgres_updates() { foreach ($newsequences as $ns) { if ($wgDatabase->sequenceExists($ns)) { - echo "... sequence $ns already exists\n"; + echo "... sequence \"$ns\" already exists\n"; continue; } - echo "... create sequence $ns\n"; + echo "Creating sequence \"$ns\"\n"; $wgDatabase->query("CREATE SEQUENCE $ns"); } foreach ($newtables as $nt) { if ($wgDatabase->tableExists($nt[0])) { - echo "... table $nt[0] already exists\n"; + echo "... table \"$nt[0]\" already exists\n"; continue; } - echo "... create table $nt[0]\n"; + echo "Creating table \"$nt[0]\"\n"; dbsource(archive($nt[1])); } ## Needed before newcols if ($wgDatabase->tableExists("archive2")) { - echo "... convert archive2 back to normal archive table\n"; + echo "Converting \"archive2\" back to normal archive table\n"; if ($wgDatabase->ruleExists("archive", "archive_insert")) { - echo "... drop rule archive_insert\n"; + echo "Dropping rule \"archive_insert\"\n"; $wgDatabase->query("DROP RULE archive_insert ON archive"); } if ($wgDatabase->ruleExists("archive", "archive_delete")) { - echo "... drop rule archive_delete\n"; + echo "Dropping rule \"archive_delete\"\n"; $wgDatabase->query("DROP RULE archive_delete ON archive"); } - dbsource(archive("patch-remove-archive2.sql")); - } else - echo "... obsolete archive2 not present\n"; + } + else + echo "... obsolete table \"archive2\" does not exist\n"; foreach ($newcols as $nc) { $fi = $wgDatabase->fieldInfo($nc[0], $nc[1]); if (!is_null($fi)) { - echo "... column $nc[0].$nc[1] already exists\n"; + echo "... column \"$nc[0].$nc[1]\" already exists\n"; continue; } - echo "... add column $nc[0].$nc[1]\n"; + echo "Adding column \"$nc[0].$nc[1]\"\n"; $wgDatabase->query("ALTER TABLE $nc[0] ADD $nc[1] $nc[2]"); } @@ -1401,11 +1610,17 @@ function do_postgres_updates() { } if ($fi->type() === $tc[2]) - echo "... $tc[0].$tc[1] is already $tc[2]\n"; + echo "... column \"$tc[0].$tc[1]\" is already of type \"$tc[2]\"\n"; else { - echo "... change $tc[0].$tc[1] from {$fi->type()} to $tc[2]\n"; + echo "Changing column type of \"$tc[0].$tc[1]\" from \"{$fi->type()}\" to \"$tc[2]\"\n"; $sql = "ALTER TABLE $tc[0] ALTER $tc[1] TYPE $tc[2]"; if (strlen($tc[3])) { + $default = array(); + if (preg_match( '/DEFAULT (.+)/', $tc[3], $default)) { + $sqldef = "ALTER TABLE $tc[0] ALTER $tc[1] SET DEFAULT $default[1]"; + $wgDatabase->query($sqldef); + $tc[3] = preg_replace( '/\s*DEFAULT .+/', '', $tc[3]); + } $sql .= " USING $tc[3]"; } $sql .= ";\nCOMMIT;\n"; @@ -1413,92 +1628,143 @@ function do_postgres_updates() { } } + if ($wgDatabase->fieldInfo('oldimage','oi_deleted')->type() !== 'smallint') { + echo "Changing \"oldimage.oi_deleted\" to type \"smallint\"\n"; + $wgDatabase->query( "ALTER TABLE oldimage ALTER oi_deleted DROP DEFAULT" ); + $wgDatabase->query( "ALTER TABLE oldimage ALTER oi_deleted TYPE SMALLINT USING (oi_deleted::smallint)" ); + $wgDatabase->query( "ALTER TABLE oldimage ALTER oi_deleted SET DEFAULT 0" ); + } + else + echo "... column \"oldimage.oi_deleted\" is already of type \"smallint\"\n"; + + foreach ($newindexes as $ni) { if (pg_index_exists($ni[0], $ni[1])) { - echo "... index $ni[1] on $ni[0] already exists\n"; + echo "... index \"$ni[1]\" on table \"$ni[0]\" already exists\n"; continue; } - dbsource(archive($ni[2])); + echo "Creating index \"$ni[1]\" on table \"$ni[0]\" $ni[2]\n"; + $wgDatabase->query( "CREATE INDEX $ni[1] ON $ni[0] $ni[2]" ); } foreach ($newrules as $nr) { if ($wgDatabase->ruleExists($nr[0], $nr[1])) { - echo "... rule $nr[1] on $nr[0] already exists\n"; + echo "... rule \"$nr[1]\" on table \"$nr[0]\" already exists\n"; continue; } + echo "Adding rule \"$nr[1]\" to table \"$nr[0]\"\n"; dbsource(archive($nr[2])); } + if ($wgDatabase->hasConstraint("oldimage_oi_name_fkey")) { + echo "Making foriegn key on table \"oldimage\" (to image) a cascade delete\n"; + $wgDatabase->query( "ALTER TABLE oldimage DROP CONSTRAINT oldimage_oi_name_fkey" ); + $wgDatabase->query( "ALTER TABLE oldimage ADD CONSTRAINT oldimage_oi_name_fkey_cascade ". + "FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE" ); + } + else + echo "... table \"oldimage\" has correct cascade delete foreign key to image\n"; + if (!$wgDatabase->triggerExists("page", "page_deleted")) { - echo "... create page_deleted trigger\n"; + echo "Adding function and trigger \"page_deleted\" to table \"page\"\n"; dbsource(archive('patch-page_deleted.sql')); } + else + echo "... table \"page\" has \"page_deleted\" trigger\n"; $fi = $wgDatabase->fieldInfo("recentchanges", "rc_cur_id"); if (!$fi->nullable()) { - echo "... remove NOT NULL constraint on recentchanges.rc_cur_id\n"; + echo "Removing NOT NULL constraint from \"recentchanges.rc_cur_id\"\n"; dbsource(archive('patch-rc_cur_id-not-null.sql')); } + else + echo "... column \"recentchanges.rc_cur_id\" has a NOT NULL constraint\n"; $pu = pg_describe_index("pagelink_unique"); if (!is_null($pu) && ($pu[0] != "pl_from" || $pu[1] != "pl_namespace" || $pu[2] != "pl_title")) { - echo "... dropping obsolete pagelink_unique index\n"; + echo "Dropping obsolete version of index \"pagelink_unique index\"\n"; $wgDatabase->query("DROP INDEX pagelink_unique"); $pu = null; - } else - echo "... obsolete pagelink_unique index not present\n"; + } + else + echo "... obsolete version of index \"pagelink_unique index\" does not exist\n"; if (is_null($pu)) { - echo "... adding new pagelink_unique index\n"; + echo "Creating index \"pagelink_unique index\"\n"; $wgDatabase->query("CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title)"); - } else - echo "... already have current pagelink_unique index\n"; + } + else + echo "... index \"pagelink_unique_index\" already exists\n"; if (pg_fkey_deltype("revision_rev_user_fkey") == 'r') { - echo "... revision_rev_user_fkey is already ON DELETE RESTRICT\n"; - } else { - echo "... change revision_rev_user_fkey to ON DELETE RESTRICT\n"; + echo "... constraint \"revision_rev_user_fkey\" is ON DELETE RESTRICT\n"; + } + else { + echo "Changing constraint \"revision_rev_user_fkey\" to ON DELETE RESTRICT\n"; dbsource(archive('patch-revision_rev_user_fkey.sql')); } - if (is_null($wgDatabase->fieldInfo("archive", "ar_deleted"))) { - echo "... add archive.ar_deleted\n"; - dbsource(archive("patch-archive-ar_deleted.sql")); - } else - echo "... archive.ar_deleted already exists\n"; + # Fix ipb_address index + if (pg_index_exists('ipblocks', 'ipb_address' )) { + echo "Removing deprecated index 'ipb_address'...\n"; + $wgDatabase->query('DROP INDEX ipb_address'); + } + if (pg_index_exists('ipblocks', 'ipb_address_unique' )) { + echo "... have ipb_address_unique\n"; + } + else { + echo "Adding ipb_address_unique index\n"; + dbsource(archive('patch-ipb_address_unique.sql')); + } - global $wgExtNewTables, $wgExtNewFields, $wgExtNewIndexes; + global $wgExtNewTables, $wgExtPGNewFields, $wgExtNewIndexes; # Add missing extension tables foreach ( $wgExtNewTables as $nt ) { if ($wgDatabase->tableExists($nt[0])) { - echo "... table $nt[0] already exists\n"; + echo "... table \"$nt[0]\" already exists\n"; continue; } - - echo "... create table $nt[0]\n"; + echo "Creating table \"$nt[0]\"\n"; dbsource($nt[1]); } # Add missing extension fields - foreach ( $wgExtNewFields as $nc ) { + foreach ( $wgExtPGNewFields as $nc ) { $fi = $wgDatabase->fieldInfo($nc[0], $nc[1]); if (!is_null($fi)) { - echo "... column $nc[0].$nc[1] already exists\n"; + echo "... column \"$nc[0].$nc[1]\" already exists\n"; continue; } - - echo "... add column $nc[0].$nc[1]\n"; - $wgDatabase->query("ALTER TABLE $nc[0] ADD $nc[1] $nc[2]"); + echo "Adding column \"$nc[0].$nc[1]\"\n"; + $wgDatabase->query( "ALTER TABLE $nc[0] ADD $nc[1] $nc[2]" ); } # Add missing extension indexes foreach ( $wgExtNewIndexes as $ni ) { if (pg_index_exists($ni[0], $ni[1])) { - echo "... index $ni[1] on $ni[0] already exists\n"; + echo "... index \"$ni[1]\" on table \"$ni[0]\" already exists\n"; continue; } + echo "Creating index \"$ni[1]\" on table \"$ni[0]\"\n"; dbsource($ni[2]); } + # Tweak the page_title tsearch2 trigger to filter out slashes + # This is create or replace, so harmless to call if not needed + dbsource(archive('patch-ts2pagetitle.sql')); + + ## If the server is 8.3 or higher, rewrite the tsearch2 triggers + ## in case they have the old 'default' versions + if ( $numver >= 8.3 ) + dbsource(archive('patch-tsearch2funcs.sql')); + + ## Put a new row in the mediawiki_version table + $wgDatabase->insert( 'mediawiki_version', + array( + 'type' => 'Update', + 'ctype' => 'U', + 'mw_version' => $wgVersion, + 'pg_version' => $version, + 'sql_version' => '$LastChangedRevision$', + 'sql_date' => '$LastChangedDate$', + ) ); return; } - -?>