2010-08-15 18:55:08 +00:00
|
|
|
<?php
|
2010-08-21 18:20:09 +00:00
|
|
|
/**
|
|
|
|
|
* PostgreSQL-specific updater.
|
|
|
|
|
*
|
2012-05-06 05:50:15 +00:00
|
|
|
* 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
|
|
|
|
|
*
|
2010-08-21 18:20:09 +00:00
|
|
|
* @file
|
|
|
|
|
* @ingroup Deployment
|
|
|
|
|
*/
|
2010-12-01 20:15:45 +00:00
|
|
|
|
2010-08-15 18:55:08 +00:00
|
|
|
/**
|
|
|
|
|
* Class for handling updates to Postgres databases.
|
|
|
|
|
*
|
|
|
|
|
* @ingroup Deployment
|
|
|
|
|
* @since 1.17
|
|
|
|
|
*/
|
2010-08-21 20:23:42 +00:00
|
|
|
class PostgresUpdater extends DatabaseUpdater {
|
2010-08-22 08:07:26 +00:00
|
|
|
|
2011-11-20 17:54:47 +00:00
|
|
|
/**
|
|
|
|
|
* @var DatabasePostgres
|
|
|
|
|
*/
|
|
|
|
|
protected $db;
|
|
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
/**
|
|
|
|
|
* @todo FIXME: Postgres should use sequential updates like Mysql, Sqlite
|
|
|
|
|
* and everybody else. It never got refactored like it should've.
|
2012-02-09 21:35:05 +00:00
|
|
|
* @return array
|
2010-08-22 08:07:26 +00:00
|
|
|
*/
|
2010-08-15 18:55:08 +00:00
|
|
|
protected function getCoreUpdateList() {
|
2010-08-22 08:07:26 +00:00
|
|
|
return array(
|
2012-03-14 20:20:53 +00:00
|
|
|
# rename tables 1.7.3
|
|
|
|
|
# r15791 Change reserved word table names "user" and "text"
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'renameTable', 'user', 'mwuser' ),
|
|
|
|
|
array( 'renameTable', 'text', 'pagecontent' ),
|
2013-04-20 21:11:46 +00:00
|
|
|
array( 'renameIndex', 'mwuser', 'user_pkey', 'mwuser_pkey' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'renameIndex', 'mwuser', 'user_user_name_key', 'mwuser_user_name_key' ),
|
2013-04-20 21:11:46 +00:00
|
|
|
array( 'renameIndex', 'pagecontent', 'text_pkey', 'pagecontent_pkey' ),
|
2012-03-14 20:20:53 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
# renamed sequences
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'renameSequence', 'ipblocks_ipb_id_val', 'ipblocks_ipb_id_seq' ),
|
|
|
|
|
array( 'renameSequence', 'rev_rev_id_val', 'revision_rev_id_seq' ),
|
|
|
|
|
array( 'renameSequence', 'text_old_id_val', 'text_old_id_seq' ),
|
|
|
|
|
array( 'renameSequence', 'rc_rc_id_seq', 'recentchanges_rc_id_seq' ),
|
|
|
|
|
array( 'renameSequence', 'log_log_id_seq', 'logging_log_id_seq' ),
|
|
|
|
|
array( 'renameSequence', 'pr_id_val', 'page_restrictions_pr_id_seq' ),
|
|
|
|
|
array( 'renameSequence', 'us_id_seq', 'uploadstash_us_id_seq' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
# since r58263
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'renameSequence', 'category_id_seq', 'category_cat_id_seq' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
|
|
|
|
|
# new sequences if not renamed above
|
|
|
|
|
array( 'addSequence', 'logging', false, 'logging_log_id_seq' ),
|
|
|
|
|
array( 'addSequence', 'page_restrictions', false, 'page_restrictions_pr_id_seq' ),
|
|
|
|
|
array( 'addSequence', 'filearchive', 'fa_id', 'filearchive_fa_id_seq' ),
|
2013-10-28 22:08:52 +00:00
|
|
|
array( 'addSequence', 'archive', false, 'archive_ar_id_seq' ),
|
|
|
|
|
array( 'addSequence', 'externallinks', false, 'externallinks_el_id_seq' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
# new tables
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'addTable', 'category', 'patch-category.sql' ),
|
|
|
|
|
array( 'addTable', 'page', 'patch-page.sql' ),
|
|
|
|
|
array( 'addTable', 'querycachetwo', 'patch-querycachetwo.sql' ),
|
|
|
|
|
array( 'addTable', 'page_props', 'patch-page_props.sql' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
array( 'addTable', 'page_restrictions', 'patch-page_restrictions.sql' ),
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'addTable', 'profiling', 'patch-profiling.sql' ),
|
|
|
|
|
array( 'addTable', 'protected_titles', 'patch-protected_titles.sql' ),
|
|
|
|
|
array( 'addTable', 'redirect', 'patch-redirect.sql' ),
|
|
|
|
|
array( 'addTable', 'updatelog', 'patch-updatelog.sql' ),
|
|
|
|
|
array( 'addTable', 'change_tag', 'patch-change_tag.sql' ),
|
|
|
|
|
array( 'addTable', 'tag_summary', 'patch-tag_summary.sql' ),
|
|
|
|
|
array( 'addTable', 'valid_tag', 'patch-valid_tag.sql' ),
|
|
|
|
|
array( 'addTable', 'user_properties', 'patch-user_properties.sql' ),
|
|
|
|
|
array( 'addTable', 'log_search', 'patch-log_search.sql' ),
|
|
|
|
|
array( 'addTable', 'l10n_cache', 'patch-l10n_cache.sql' ),
|
|
|
|
|
array( 'addTable', 'iwlinks', 'patch-iwlinks.sql' ),
|
|
|
|
|
array( 'addTable', 'msg_resource', 'patch-msg_resource.sql' ),
|
|
|
|
|
array( 'addTable', 'msg_resource_links', 'patch-msg_resource_links.sql' ),
|
|
|
|
|
array( 'addTable', 'module_deps', 'patch-module_deps.sql' ),
|
|
|
|
|
array( 'addTable', 'uploadstash', 'patch-uploadstash.sql' ),
|
|
|
|
|
array( 'addTable', 'user_former_groups', 'patch-user_former_groups.sql' ),
|
|
|
|
|
array( 'addTable', 'sites', 'patch-sites.sql' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
|
|
|
|
# Needed before new field
|
|
|
|
|
array( 'convertArchive2' ),
|
|
|
|
|
|
|
|
|
|
# new fields
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'addPgField', 'updatelog', 'ul_value', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_len', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_page_id', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_parent_id', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_content_model', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_content_format', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'categorylinks', 'cl_sortkey_prefix', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'categorylinks', 'cl_collation', "TEXT NOT NULL DEFAULT 0" ),
|
|
|
|
|
array( 'addPgField', 'categorylinks', 'cl_type', "TEXT NOT NULL DEFAULT 'page'" ),
|
|
|
|
|
array( 'addPgField', 'image', 'img_sha1', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_allow_usertalk', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_anon_only', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_by_text', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_block_email', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_create_account', 'SMALLINT NOT NULL DEFAULT 1' ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_enable_autoblock', 'SMALLINT NOT NULL DEFAULT 1' ),
|
|
|
|
|
array( 'addPgField', 'ipblocks', 'ipb_parent_block_id',
|
|
|
|
|
'INTEGER DEFAULT NULL REFERENCES ipblocks(ipb_id) ' .
|
|
|
|
|
'ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED' ),
|
|
|
|
|
array( 'addPgField', 'filearchive', 'fa_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'filearchive', 'fa_sha1', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'logging', 'log_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'logging', 'log_id',
|
|
|
|
|
"INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('logging_log_id_seq')" ),
|
|
|
|
|
array( 'addPgField', 'logging', 'log_params', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'mwuser', 'user_editcount', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'mwuser', 'user_newpass_time', 'TIMESTAMPTZ' ),
|
|
|
|
|
array( 'addPgField', 'oldimage', 'oi_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'oldimage', 'oi_major_mime', "TEXT NOT NULL DEFAULT 'unknown'" ),
|
|
|
|
|
array( 'addPgField', 'oldimage', 'oi_media_type', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'oldimage', 'oi_metadata', "BYTEA NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'oldimage', 'oi_minor_mime', "TEXT NOT NULL DEFAULT 'unknown'" ),
|
|
|
|
|
array( 'addPgField', 'oldimage', 'oi_sha1', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'page', 'page_content_model', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'page_restrictions', 'pr_id',
|
|
|
|
|
"INTEGER NOT NULL UNIQUE DEFAULT nextval('page_restrictions_pr_id_seq')" ),
|
|
|
|
|
array( 'addPgField', 'profiling', 'pf_memory', 'NUMERIC(18,10) NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_log_action', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_log_type', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_logid', 'INTEGER NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_new_len', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_old_len', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'recentchanges', 'rc_params', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'redirect', 'rd_interwiki', 'TEXT NULL' ),
|
|
|
|
|
array( 'addPgField', 'redirect', 'rd_fragment', 'TEXT NULL' ),
|
|
|
|
|
array( 'addPgField', 'revision', 'rev_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'revision', 'rev_len', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'revision', 'rev_parent_id', 'INTEGER DEFAULT NULL' ),
|
|
|
|
|
array( 'addPgField', 'revision', 'rev_content_model', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'revision', 'rev_content_format', 'TEXT' ),
|
|
|
|
|
array( 'addPgField', 'site_stats', 'ss_active_users', "INTEGER DEFAULT '-1'" ),
|
|
|
|
|
array( 'addPgField', 'user_newtalk', 'user_last_timestamp', 'TIMESTAMPTZ' ),
|
|
|
|
|
array( 'addPgField', 'logging', 'log_user_text', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'logging', 'log_page', 'INTEGER' ),
|
|
|
|
|
array( 'addPgField', 'interwiki', 'iw_api', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'interwiki', 'iw_wikiid', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'revision', 'rev_sha1', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_sha1', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'uploadstash', 'us_chunk_inx', "INTEGER NULL" ),
|
|
|
|
|
array( 'addPgField', 'job', 'job_timestamp', "TIMESTAMPTZ" ),
|
|
|
|
|
array( 'addPgField', 'job', 'job_random', "INTEGER NOT NULL DEFAULT 0" ),
|
|
|
|
|
array( 'addPgField', 'job', 'job_attempts', "INTEGER NOT NULL DEFAULT 0" ),
|
|
|
|
|
array( 'addPgField', 'job', 'job_token', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'job', 'job_token_timestamp', "TIMESTAMPTZ" ),
|
|
|
|
|
array( 'addPgField', 'job', 'job_sha1', "TEXT NOT NULL DEFAULT ''" ),
|
|
|
|
|
array( 'addPgField', 'archive', 'ar_id',
|
|
|
|
|
"INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('archive_ar_id_seq')" ),
|
|
|
|
|
array( 'addPgField', 'externallinks', 'el_id',
|
|
|
|
|
"INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('externallinks_el_id_seq')" ),
|
2013-12-06 17:22:36 +00:00
|
|
|
array( 'addPgField', 'uploadstash', 'us_props', "BYTEA" ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
|
|
|
|
# type changes
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'changeField', 'archive', 'ar_deleted', 'smallint', '' ),
|
|
|
|
|
array( 'changeField', 'archive', 'ar_minor_edit', 'smallint',
|
|
|
|
|
'ar_minor_edit::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_deleted', 'smallint', '' ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_height', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_metadata', 'bytea', "decode(fa_metadata,'escape')" ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_size', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_width', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_storage_group', 'text', '' ),
|
|
|
|
|
array( 'changeField', 'filearchive', 'fa_storage_key', 'text', '' ),
|
|
|
|
|
array( 'changeField', 'image', 'img_metadata', 'bytea', "decode(img_metadata,'escape')" ),
|
|
|
|
|
array( 'changeField', 'image', 'img_size', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'image', 'img_width', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'image', 'img_height', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'interwiki', 'iw_local', 'smallint', 'iw_local::smallint' ),
|
|
|
|
|
array( 'changeField', 'interwiki', 'iw_trans', 'smallint', 'iw_trans::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_auto', 'smallint', 'ipb_auto::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_anon_only', 'smallint',
|
|
|
|
|
"CASE WHEN ipb_anon_only=' ' THEN 0 ELSE ipb_anon_only::smallint END DEFAULT 0" ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_create_account', 'smallint',
|
|
|
|
|
"CASE WHEN ipb_create_account=' ' THEN 0 ELSE ipb_create_account::smallint END DEFAULT 1" ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_enable_autoblock', 'smallint',
|
|
|
|
|
"CASE WHEN ipb_enable_autoblock=' ' THEN 0 ELSE ipb_enable_autoblock::smallint END DEFAULT 1" ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_block_email', 'smallint',
|
|
|
|
|
"CASE WHEN ipb_block_email=' ' THEN 0 ELSE ipb_block_email::smallint END DEFAULT 0" ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_address', 'text', 'ipb_address::text' ),
|
|
|
|
|
array( 'changeField', 'ipblocks', 'ipb_deleted', 'smallint', 'ipb_deleted::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'mwuser', 'user_token', 'text', '' ),
|
|
|
|
|
array( 'changeField', 'mwuser', 'user_email_token', 'text', '' ),
|
|
|
|
|
array( 'changeField', 'objectcache', 'keyname', 'text', '' ),
|
|
|
|
|
array( 'changeField', 'oldimage', 'oi_height', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'oldimage', 'oi_metadata', 'bytea', "decode(img_metadata,'escape')" ),
|
|
|
|
|
array( 'changeField', 'oldimage', 'oi_size', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'oldimage', 'oi_width', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'page', 'page_is_redirect', 'smallint',
|
|
|
|
|
'page_is_redirect::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'page', 'page_is_new', 'smallint', 'page_is_new::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'querycache', 'qc_value', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'querycachetwo', 'qcc_value', 'integer', '' ),
|
|
|
|
|
array( 'changeField', 'recentchanges', 'rc_bot', 'smallint', 'rc_bot::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'recentchanges', 'rc_deleted', 'smallint', '' ),
|
|
|
|
|
array( 'changeField', 'recentchanges', 'rc_minor', 'smallint', 'rc_minor::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'recentchanges', 'rc_new', 'smallint', 'rc_new::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'recentchanges', 'rc_type', 'smallint', 'rc_type::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'recentchanges', 'rc_patrolled', 'smallint',
|
|
|
|
|
'rc_patrolled::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'revision', 'rev_deleted', 'smallint', 'rev_deleted::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'revision', 'rev_minor_edit', 'smallint',
|
|
|
|
|
'rev_minor_edit::smallint DEFAULT 0' ),
|
|
|
|
|
array( 'changeField', 'templatelinks', 'tl_namespace', 'smallint', 'tl_namespace::smallint' ),
|
|
|
|
|
array( 'changeField', 'user_newtalk', 'user_ip', 'text', 'host(user_ip)' ),
|
|
|
|
|
array( 'changeField', 'uploadstash', 'us_image_bits', 'smallint', '' ),
|
|
|
|
|
array( 'changeField', 'profiling', 'pf_time', 'float', '' ),
|
|
|
|
|
array( 'changeField', 'profiling', 'pf_memory', 'float', '' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
|
|
|
|
# null changes
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'changeNullableField', 'oldimage', 'oi_bits', 'NULL' ),
|
|
|
|
|
array( 'changeNullableField', 'oldimage', 'oi_timestamp', 'NULL' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
array( 'changeNullableField', 'oldimage', 'oi_major_mime', 'NULL' ),
|
|
|
|
|
array( 'changeNullableField', 'oldimage', 'oi_minor_mime', 'NULL' ),
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'changeNullableField', 'image', 'img_metadata', 'NOT NULL' ),
|
|
|
|
|
array( 'changeNullableField', 'filearchive', 'fa_metadata', 'NOT NULL' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'changeNullableField', 'recentchanges', 'rc_cur_id', 'NULL' ),
|
2014-04-20 22:09:34 +00:00
|
|
|
array( 'changeNullableField', 'recentchanges', 'rc_cur_time', 'NULL' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
|
|
|
|
array( 'checkOiDeleted' ),
|
|
|
|
|
|
|
|
|
|
# New indexes
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'addPgIndex', 'archive', 'archive_user_text', '(ar_user_text)' ),
|
|
|
|
|
array( 'addPgIndex', 'image', 'img_sha1', '(img_sha1)' ),
|
|
|
|
|
array( 'addPgIndex', 'ipblocks', 'ipb_parent_block_id', '(ipb_parent_block_id)' ),
|
|
|
|
|
array( 'addPgIndex', 'oldimage', 'oi_sha1', '(oi_sha1)' ),
|
|
|
|
|
array( 'addPgIndex', 'page', 'page_mediawiki_title', '(page_title) WHERE page_namespace = 8' ),
|
|
|
|
|
array( 'addPgIndex', 'pagelinks', 'pagelinks_title', '(pl_title)' ),
|
|
|
|
|
array( 'addPgIndex', 'page_props', 'pp_propname_page', '(pp_propname, pp_page)' ),
|
|
|
|
|
array( 'addPgIndex', 'revision', 'rev_text_id_idx', '(rev_text_id)' ),
|
|
|
|
|
array( 'addPgIndex', 'recentchanges', 'rc_timestamp_bot', '(rc_timestamp) WHERE rc_bot = 0' ),
|
|
|
|
|
array( 'addPgIndex', 'templatelinks', 'templatelinks_from', '(tl_from)' ),
|
|
|
|
|
array( 'addPgIndex', 'watchlist', 'wl_user', '(wl_user)' ),
|
2014-06-03 19:20:04 +00:00
|
|
|
array( 'addPgIndex', 'watchlist', 'wl_user_notificationtimestamp', '(wl_user, wl_notificationtimestamp)' ),
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'addPgIndex', 'logging', 'logging_user_type_time',
|
|
|
|
|
'(log_user, log_type, log_timestamp)' ),
|
|
|
|
|
array( 'addPgIndex', 'logging', 'logging_page_id_time', '(log_page,log_timestamp)' ),
|
|
|
|
|
array( 'addPgIndex', 'iwlinks', 'iwl_prefix_from_title', '(iwl_prefix, iwl_from, iwl_title)' ),
|
|
|
|
|
array( 'addPgIndex', 'iwlinks', 'iwl_prefix_title_from', '(iwl_prefix, iwl_title, iwl_from)' ),
|
|
|
|
|
array( 'addPgIndex', 'job', 'job_timestamp_idx', '(job_timestamp)' ),
|
|
|
|
|
array( 'addPgIndex', 'job', 'job_sha1', '(job_sha1)' ),
|
|
|
|
|
array( 'addPgIndex', 'job', 'job_cmd_token', '(job_cmd, job_token, job_random)' ),
|
|
|
|
|
array( 'addPgIndex', 'job', 'job_cmd_token_id', '(job_cmd, job_token, job_id)' ),
|
|
|
|
|
array( 'addPgIndex', 'filearchive', 'fa_sha1', '(fa_sha1)' ),
|
2014-02-05 10:20:17 +00:00
|
|
|
array( 'addPgIndex', 'logging', 'logging_user_text_type_time',
|
|
|
|
|
'(log_user_text, log_type, log_timestamp)' ),
|
2013-12-09 21:11:06 +00:00
|
|
|
array( 'addPgIndex', 'logging', 'logging_user_text_time', '(log_user_text, log_timestamp)' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'pagelink_unique', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'pl_from', 'int4_ops', 'btree', 0 ),
|
|
|
|
|
array( 'pl_namespace', 'int2_ops', 'btree', 0 ),
|
|
|
|
|
array( 'pl_title', 'text_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'cl_sortkey', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'cl_to', 'text_ops', 'btree', 0 ),
|
|
|
|
|
array( 'cl_sortkey', 'text_ops', 'btree', 0 ),
|
|
|
|
|
array( 'cl_from', 'int4_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX cl_sortkey ON "categorylinks" ' .
|
|
|
|
|
'USING "btree" ("cl_to", "cl_sortkey", "cl_from")' ),
|
2013-01-11 00:22:03 +00:00
|
|
|
array( 'checkIndex', 'iwl_prefix_title_from', array(
|
2013-04-20 21:11:46 +00:00
|
|
|
array( 'iwl_prefix', 'text_ops', 'btree', 0 ),
|
|
|
|
|
array( 'iwl_title', 'text_ops', 'btree', 0 ),
|
|
|
|
|
array( 'iwl_from', 'int4_ops', 'btree', 0 ),
|
2013-01-11 00:22:03 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX iwl_prefix_title_from ON "iwlinks" ' .
|
|
|
|
|
'USING "btree" ("iwl_prefix", "iwl_title", "iwl_from")' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'logging_times', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'log_timestamp', 'timestamptz_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
|
|
|
|
'CREATE INDEX "logging_times" ON "logging" USING "btree" ("log_timestamp")' ),
|
|
|
|
|
array( 'dropIndex', 'oldimage', 'oi_name' ),
|
|
|
|
|
array( 'checkIndex', 'oi_name_archive_name', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'oi_name', 'text_ops', 'btree', 0 ),
|
|
|
|
|
array( 'oi_archive_name', 'text_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "oi_name_archive_name" ON "oldimage" ' .
|
|
|
|
|
'USING "btree" ("oi_name", "oi_archive_name")' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'oi_name_timestamp', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'oi_name', 'text_ops', 'btree', 0 ),
|
|
|
|
|
array( 'oi_timestamp', 'timestamptz_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "oi_name_timestamp" ON "oldimage" ' .
|
|
|
|
|
'USING "btree" ("oi_name", "oi_timestamp")' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'page_main_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'page_title', 'text_pattern_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "page_main_title" ON "page" ' .
|
|
|
|
|
'USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 0)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'page_mediawiki_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'page_title', 'text_pattern_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "page_mediawiki_title" ON "page" ' .
|
|
|
|
|
'USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 8)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'page_project_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'page_title', 'text_pattern_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "page_project_title" ON "page" ' .
|
|
|
|
|
'USING "btree" ("page_title" "text_pattern_ops") ' .
|
|
|
|
|
'WHERE ("page_namespace" = 4)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'page_talk_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'page_title', 'text_pattern_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "page_talk_title" ON "page" ' .
|
|
|
|
|
'USING "btree" ("page_title" "text_pattern_ops") ' .
|
|
|
|
|
'WHERE ("page_namespace" = 1)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'page_user_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'page_title', 'text_pattern_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "page_user_title" ON "page" ' .
|
|
|
|
|
'USING "btree" ("page_title" "text_pattern_ops") WHERE ' .
|
|
|
|
|
'("page_namespace" = 2)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'page_utalk_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'page_title', 'text_pattern_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE INDEX "page_utalk_title" ON "page" ' .
|
|
|
|
|
'USING "btree" ("page_title" "text_pattern_ops") ' .
|
|
|
|
|
'WHERE ("page_namespace" = 3)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'ts2_page_text', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'textvector', 'tsvector_ops', 'gist', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
|
|
|
|
'CREATE INDEX "ts2_page_text" ON "pagecontent" USING "gist" ("textvector")' ),
|
|
|
|
|
array( 'checkIndex', 'ts2_page_title', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'titlevector', 'tsvector_ops', 'gist', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
|
|
|
|
'CREATE INDEX "ts2_page_title" ON "page" USING "gist" ("titlevector")' ),
|
|
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
array( 'checkOiNameConstraint' ),
|
|
|
|
|
array( 'checkPageDeletedTrigger' ),
|
|
|
|
|
array( 'checkRevUserFkey' ),
|
2013-04-20 21:11:46 +00:00
|
|
|
array( 'dropIndex', 'ipblocks', 'ipb_address' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
array( 'checkIndex', 'ipb_address_unique', array(
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'ipb_address', 'text_ops', 'btree', 0 ),
|
2013-04-20 21:11:46 +00:00
|
|
|
array( 'ipb_user', 'int4_ops', 'btree', 0 ),
|
|
|
|
|
array( 'ipb_auto', 'int2_ops', 'btree', 0 ),
|
2013-02-03 19:28:43 +00:00
|
|
|
array( 'ipb_anon_only', 'int2_ops', 'btree', 0 ),
|
2012-03-22 02:42:44 +00:00
|
|
|
),
|
2013-10-23 12:16:03 +00:00
|
|
|
'CREATE UNIQUE INDEX ipb_address_unique ' .
|
|
|
|
|
'ON ipblocks (ipb_address,ipb_user,ipb_auto,ipb_anon_only)' ),
|
2012-03-22 02:42:44 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
array( 'checkIwlPrefix' ),
|
|
|
|
|
|
|
|
|
|
# All FK columns should be deferred
|
2013-10-23 12:16:03 +00:00
|
|
|
array( 'changeFkeyDeferrable', 'archive', 'ar_user', 'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'categorylinks', 'cl_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'externallinks', 'el_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'filearchive', 'fa_deleted_user',
|
|
|
|
|
'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'filearchive', 'fa_user', 'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'image', 'img_user', 'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'imagelinks', 'il_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'ipblocks', 'ipb_by', 'mwuser(user_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'ipblocks', 'ipb_user', 'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'ipblocks', 'ipb_parent_block_id',
|
|
|
|
|
'ipblocks(ipb_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'langlinks', 'll_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'logging', 'log_user', 'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'oldimage', 'oi_name',
|
|
|
|
|
'image(img_name) ON DELETE CASCADE ON UPDATE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'oldimage', 'oi_user', 'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'pagelinks', 'pl_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'page_props', 'pp_page', 'page (page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'page_restrictions', 'pr_page',
|
|
|
|
|
'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'protected_titles', 'pt_user',
|
|
|
|
|
'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'recentchanges', 'rc_user',
|
|
|
|
|
'mwuser(user_id) ON DELETE SET NULL' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'redirect', 'rd_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'revision', 'rev_page', 'page (page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'revision', 'rev_user', 'mwuser(user_id) ON DELETE RESTRICT' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'templatelinks', 'tl_from', 'page(page_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'user_groups', 'ug_user', 'mwuser(user_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'user_newtalk', 'user_id', 'mwuser(user_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'user_properties', 'up_user',
|
|
|
|
|
'mwuser(user_id) ON DELETE CASCADE' ),
|
|
|
|
|
array( 'changeFkeyDeferrable', 'watchlist', 'wl_user', 'mwuser(user_id) ON DELETE CASCADE' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
# r81574
|
|
|
|
|
array( 'addInterwikiType' ),
|
2010-08-22 08:07:26 +00:00
|
|
|
# end
|
|
|
|
|
array( 'tsearchFixes' ),
|
2013-10-25 20:10:42 +00:00
|
|
|
|
2013-11-21 20:54:30 +00:00
|
|
|
// 1.23
|
2013-12-08 19:31:47 +00:00
|
|
|
array( 'addPgField', 'recentchanges', 'rc_source', "TEXT NOT NULL DEFAULT ''" ),
|
2013-12-13 00:54:51 +00:00
|
|
|
array( 'addPgField', 'page', 'page_links_updated', "TIMESTAMPTZ NULL" ),
|
Password Expiration
Add functionality to expire users' passwords:
* Adds column to the user table to keep a password expiration
* Adds $wgPasswordExpirationDays, which will force users to reset
their passwords after a set number of days. By default, this set
to false, so passwords never expire.
* Adds a default grace period of 7 days, where if the user's password
is expired, they can still login, but are encouraged to reset their
password.
* Adds hook 'LoginPasswordResetMessage' to update reset message, in
case an extension wants to vary the message on a particular reset
event.
* Adds hook 'ResetPasswordExpiration' to allow extensions to change
the expiration date when the user resets their password. E.g., if
an extension wants to vary the expiration based on the user's group.
If the user is in the grace period, they get a password reset form
added to the login successful page. If an extension prevents showing
the login successful page (like CentralAuth), it should be updated to
show a password change form during the grace period. After the grace
period, the user will not be able to login without changing their
password.
Also prevents a successful reset if the user is "changing" their
password to their existing password.
No passwords will expire by default. Sites will have to call
User->expirePassword() from their own maintenance script to trigger a
password reset for a user.
Bug: 54997
Change-Id: I92a9fc63b409b182b1d7b48781d73fc7216f8061
2013-10-09 18:09:28 +00:00
|
|
|
array( 'addPgField', 'mwuser', 'user_password_expires', 'TIMESTAMPTZ NULL' ),
|
2014-05-11 15:34:55 +00:00
|
|
|
array( 'changeFieldPurgeTable', 'l10n_cache', 'lc_value', 'bytea',
|
|
|
|
|
"replace(lc_value,'\','\\\\')::bytea" ),
|
2014-08-12 06:35:35 +00:00
|
|
|
// 1.23.9
|
2015-08-14 21:17:01 +00:00
|
|
|
array( 'rebuildTextSearch' ),
|
2014-04-29 18:11:58 +00:00
|
|
|
|
|
|
|
|
// 1.24
|
2014-03-31 11:00:28 +00:00
|
|
|
array( 'addPgField', 'page_props', 'pp_sortkey', 'float NULL' ),
|
|
|
|
|
array( 'addPgIndex', 'page_props', 'pp_propname_sortkey_page',
|
2014-04-29 18:11:58 +00:00
|
|
|
'( pp_propname, pp_sortkey, pp_page ) WHERE ( pp_sortkey IS NOT NULL )' ),
|
2014-05-25 14:38:50 +00:00
|
|
|
array( 'addPgField', 'page', 'page_lang', 'TEXT default NULL' ),
|
2014-03-06 23:01:35 +00:00
|
|
|
array( 'addPgField', 'pagelinks', 'pl_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'templatelinks', 'tl_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
|
|
|
|
|
array( 'addPgField', 'imagelinks', 'il_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
|
2015-01-09 21:17:52 +00:00
|
|
|
|
|
|
|
|
// 1.25
|
2014-07-30 20:56:20 +00:00
|
|
|
array( 'dropTable', 'hitcounter' ),
|
|
|
|
|
array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
|
|
|
|
|
array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
|
2014-12-08 20:27:11 +00:00
|
|
|
array( 'dropFkey', 'recentchanges', 'rc_cur_id' )
|
2010-08-22 08:07:26 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function getOldGlobalUpdates() {
|
|
|
|
|
global $wgExtNewTables, $wgExtPGNewFields, $wgExtPGAlteredFields, $wgExtNewIndexes;
|
|
|
|
|
|
|
|
|
|
$updates = array();
|
|
|
|
|
|
|
|
|
|
# Add missing extension tables
|
|
|
|
|
foreach ( $wgExtNewTables as $tableRecord ) {
|
|
|
|
|
$updates[] = array(
|
|
|
|
|
'addTable', $tableRecord[0], $tableRecord[1], true
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Add missing extension fields
|
2010-10-14 20:31:34 +00:00
|
|
|
foreach ( $wgExtPGNewFields as $fieldRecord ) {
|
2010-08-22 08:07:26 +00:00
|
|
|
$updates[] = array(
|
2013-10-08 11:43:42 +00:00
|
|
|
'addPgField', $fieldRecord[0], $fieldRecord[1],
|
|
|
|
|
$fieldRecord[2]
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Change altered columns
|
|
|
|
|
foreach ( $wgExtPGAlteredFields as $fieldRecord ) {
|
|
|
|
|
$updates[] = array(
|
2013-10-08 11:43:42 +00:00
|
|
|
'changeField', $fieldRecord[0], $fieldRecord[1],
|
|
|
|
|
$fieldRecord[2]
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Add missing extension indexes
|
2010-10-14 20:34:01 +00:00
|
|
|
foreach ( $wgExtNewIndexes as $fieldRecord ) {
|
2010-08-22 08:07:26 +00:00
|
|
|
$updates[] = array(
|
2013-10-08 11:43:42 +00:00
|
|
|
'addPgExtIndex', $fieldRecord[0], $fieldRecord[1],
|
|
|
|
|
$fieldRecord[2]
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
2010-12-01 20:15:45 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
return $updates;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function describeTable( $table ) {
|
|
|
|
|
$q = <<<END
|
|
|
|
|
SELECT attname, attnum FROM pg_namespace, pg_class, pg_attribute
|
|
|
|
|
WHERE pg_class.relnamespace = pg_namespace.oid
|
|
|
|
|
AND attrelid=pg_class.oid AND attnum > 0
|
|
|
|
|
AND relname=%s AND nspname=%s
|
|
|
|
|
END;
|
|
|
|
|
$res = $this->db->query( sprintf( $q,
|
2013-10-08 11:43:42 +00:00
|
|
|
$this->db->addQuotes( $table ),
|
|
|
|
|
$this->db->addQuotes( $this->db->getCoreSchema() ) ) );
|
2010-08-22 08:07:26 +00:00
|
|
|
if ( !$res ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$cols = array();
|
2010-10-13 23:11:40 +00:00
|
|
|
foreach ( $res as $r ) {
|
2010-08-22 08:07:26 +00:00
|
|
|
$cols[] = array(
|
2013-10-08 11:43:42 +00:00
|
|
|
"name" => $r[0],
|
|
|
|
|
"ord" => $r[1],
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
return $cols;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function describeIndex( $idx ) {
|
|
|
|
|
// first fetch the key (which is a list of columns ords) and
|
|
|
|
|
// the table the index applies to (an oid)
|
|
|
|
|
$q = <<<END
|
|
|
|
|
SELECT indkey, indrelid FROM pg_namespace, pg_class, pg_index
|
|
|
|
|
WHERE nspname=%s
|
|
|
|
|
AND pg_class.relnamespace = pg_namespace.oid
|
|
|
|
|
AND relname=%s
|
|
|
|
|
AND indexrelid=pg_class.oid
|
|
|
|
|
END;
|
|
|
|
|
$res = $this->db->query(
|
|
|
|
|
sprintf(
|
|
|
|
|
$q,
|
2012-03-09 19:01:30 +00:00
|
|
|
$this->db->addQuotes( $this->db->getCoreSchema() ),
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->addQuotes( $idx )
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
if ( !$res ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if ( !( $r = $this->db->fetchRow( $res ) ) ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$indkey = $r[0];
|
|
|
|
|
$relid = intval( $r[1] );
|
|
|
|
|
$indkeys = explode( ' ', $indkey );
|
|
|
|
|
|
|
|
|
|
$colnames = array();
|
|
|
|
|
foreach ( $indkeys as $rid ) {
|
|
|
|
|
$query = <<<END
|
|
|
|
|
SELECT attname FROM pg_class, pg_attribute
|
|
|
|
|
WHERE attrelid=$relid
|
|
|
|
|
AND attnum=%d
|
|
|
|
|
AND attrelid=pg_class.oid
|
|
|
|
|
END;
|
|
|
|
|
$r2 = $this->db->query( sprintf( $query, $rid ) );
|
|
|
|
|
if ( !$r2 ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if ( !( $row2 = $this->db->fetchRow( $r2 ) ) ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
$colnames[] = $row2[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $colnames;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fkeyDeltype( $fkey ) {
|
|
|
|
|
$q = <<<END
|
|
|
|
|
SELECT confdeltype FROM pg_constraint, pg_namespace
|
|
|
|
|
WHERE connamespace=pg_namespace.oid
|
|
|
|
|
AND nspname=%s
|
|
|
|
|
AND conname=%s;
|
|
|
|
|
END;
|
|
|
|
|
$r = $this->db->query(
|
|
|
|
|
sprintf(
|
|
|
|
|
$q,
|
2012-03-09 17:24:57 +00:00
|
|
|
$this->db->addQuotes( $this->db->getCoreSchema() ),
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->addQuotes( $fkey )
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
if ( !( $row = $this->db->fetchRow( $r ) ) ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
return $row[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ruleDef( $table, $rule ) {
|
2013-10-08 11:43:42 +00:00
|
|
|
$q = <<<END
|
2010-08-22 08:07:26 +00:00
|
|
|
SELECT definition FROM pg_rules
|
|
|
|
|
WHERE schemaname = %s
|
|
|
|
|
AND tablename = %s
|
|
|
|
|
AND rulename = %s
|
|
|
|
|
END;
|
|
|
|
|
$r = $this->db->query(
|
|
|
|
|
sprintf(
|
|
|
|
|
$q,
|
2012-03-09 17:24:57 +00:00
|
|
|
$this->db->addQuotes( $this->db->getCoreSchema() ),
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->addQuotes( $table ),
|
|
|
|
|
$this->db->addQuotes( $rule )
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
$row = $this->db->fetchRow( $r );
|
|
|
|
|
if ( !$row ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
$d = $row[0];
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
return $d;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
protected function addSequence( $table, $pkey, $ns ) {
|
2010-08-22 08:07:26 +00:00
|
|
|
if ( !$this->db->sequenceExists( $ns ) ) {
|
2010-10-01 15:11:06 +00:00
|
|
|
$this->output( "Creating sequence $ns\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "CREATE SEQUENCE $ns" );
|
2013-04-20 21:11:46 +00:00
|
|
|
if ( $pkey !== false ) {
|
2013-02-03 19:28:43 +00:00
|
|
|
$this->setDefault( $table, $pkey, '"nextval"(\'"' . $ns . '"\'::"regclass")' );
|
2012-03-22 02:42:44 +00:00
|
|
|
}
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function renameSequence( $old, $new ) {
|
2011-11-20 17:54:47 +00:00
|
|
|
if ( $this->db->sequenceExists( $new ) ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...sequence $new already exists.\n" );
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2011-11-20 17:54:47 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2010-08-22 08:07:26 +00:00
|
|
|
if ( $this->db->sequenceExists( $old ) ) {
|
2010-10-01 15:11:06 +00:00
|
|
|
$this->output( "Renaming sequence $old to $new\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "ALTER SEQUENCE $old RENAME TO $new" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
protected function renameTable( $old, $new, $patch = false ) {
|
2010-12-01 20:15:45 +00:00
|
|
|
if ( $this->db->tableExists( $old ) ) {
|
|
|
|
|
$this->output( "Renaming table $old to $new\n" );
|
2012-03-14 20:20:53 +00:00
|
|
|
$old = $this->db->realTableName( $old, "quoted" );
|
|
|
|
|
$new = $this->db->realTableName( $new, "quoted" );
|
2011-02-23 16:42:42 +00:00
|
|
|
$this->db->query( "ALTER TABLE $old RENAME TO $new" );
|
2013-04-20 21:11:46 +00:00
|
|
|
if ( $patch !== false ) {
|
2012-03-22 02:42:44 +00:00
|
|
|
$this->applyPatch( $patch );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-03 06:12:06 +00:00
|
|
|
protected function renameIndex(
|
|
|
|
|
$table, $old, $new, $skipBothIndexExistWarning = false, $a = false, $b = false
|
|
|
|
|
) {
|
|
|
|
|
// First requirement: the table must exist
|
|
|
|
|
if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
|
|
|
|
|
$this->output( "...skipping: '$table' table doesn't exist yet.\n" );
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2013-02-03 06:12:06 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Second requirement: the new index must be missing
|
|
|
|
|
if ( $this->db->indexExists( $table, $new, __METHOD__ ) ) {
|
|
|
|
|
$this->output( "...index $new already set on $table table.\n" );
|
|
|
|
|
if ( !$skipBothIndexExistWarning
|
2013-10-08 11:43:42 +00:00
|
|
|
&& $this->db->indexExists( $table, $old, __METHOD__ )
|
|
|
|
|
) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->output( "...WARNING: $old still exists, despite it has been " .
|
|
|
|
|
"renamed into $new (which also exists).\n" .
|
2013-02-03 06:12:06 +00:00
|
|
|
" $old should be manually removed if not needed anymore.\n" );
|
|
|
|
|
}
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2013-02-03 06:12:06 +00:00
|
|
|
return;
|
2010-12-01 20:15:45 +00:00
|
|
|
}
|
2013-02-03 06:12:06 +00:00
|
|
|
|
|
|
|
|
// Third requirement: the old index must exist
|
|
|
|
|
if ( !$this->db->indexExists( $table, $old, __METHOD__ ) ) {
|
|
|
|
|
$this->output( "...skipping: index $old doesn't exist.\n" );
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2013-02-03 06:12:06 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->db->query( "ALTER INDEX $old RENAME TO $new" );
|
2010-12-01 20:15:45 +00:00
|
|
|
}
|
|
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
protected function addPgField( $table, $field, $type ) {
|
|
|
|
|
$fi = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( !is_null( $fi ) ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...column '$table.$field' already exists\n" );
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
return;
|
|
|
|
|
} else {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Adding column '$table.$field'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "ALTER TABLE $table ADD $field $type" );
|
|
|
|
|
}
|
2010-08-15 18:55:08 +00:00
|
|
|
}
|
|
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
protected function changeField( $table, $field, $newtype, $default ) {
|
|
|
|
|
$fi = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( is_null( $fi ) ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...ERROR: expected column $table.$field to exist\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
exit( 1 );
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-20 21:11:46 +00:00
|
|
|
if ( $fi->type() === $newtype ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...column '$table.$field' is already of type '$newtype'\n" );
|
2013-04-20 21:11:46 +00:00
|
|
|
} else {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Changing column type of '$table.$field' from '{$fi->type()}' to '$newtype'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$sql = "ALTER TABLE $table ALTER $field TYPE $newtype";
|
|
|
|
|
if ( strlen( $default ) ) {
|
|
|
|
|
$res = array();
|
|
|
|
|
if ( preg_match( '/DEFAULT (.+)/', $default, $res ) ) {
|
|
|
|
|
$sqldef = "ALTER TABLE $table ALTER $field SET DEFAULT $res[1]";
|
|
|
|
|
$this->db->query( $sqldef );
|
|
|
|
|
$default = preg_replace( '/\s*DEFAULT .+/', '', $default );
|
|
|
|
|
}
|
|
|
|
|
$sql .= " USING $default";
|
|
|
|
|
}
|
|
|
|
|
$this->db->query( $sql );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-05 18:20:52 +00:00
|
|
|
protected function changeFieldPurgeTable( $table, $field, $newtype, $default ) {
|
|
|
|
|
## For a cache table, empty it if the field needs to be changed, because the old contents
|
|
|
|
|
## may be corrupted. If the column is already the desired type, refrain from purging.
|
|
|
|
|
$fi = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( is_null( $fi ) ) {
|
|
|
|
|
$this->output( "...ERROR: expected column $table.$field to exist\n" );
|
|
|
|
|
exit( 1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $fi->type() === $newtype ) {
|
|
|
|
|
$this->output( "...column '$table.$field' is already of type '$newtype'\n" );
|
|
|
|
|
} else {
|
|
|
|
|
$this->output( "Purging data from cache table '$table'\n" );
|
2014-07-19 21:12:10 +00:00
|
|
|
$this->db->query( "DELETE from $table" );
|
2014-05-05 18:20:52 +00:00
|
|
|
$this->output( "Changing column type of '$table.$field' from '{$fi->type()}' to '$newtype'\n" );
|
|
|
|
|
$sql = "ALTER TABLE $table ALTER $field TYPE $newtype";
|
|
|
|
|
if ( strlen( $default ) ) {
|
|
|
|
|
$res = array();
|
|
|
|
|
if ( preg_match( '/DEFAULT (.+)/', $default, $res ) ) {
|
|
|
|
|
$sqldef = "ALTER TABLE $table ALTER $field SET DEFAULT $res[1]";
|
|
|
|
|
$this->db->query( $sqldef );
|
|
|
|
|
$default = preg_replace( '/\s*DEFAULT .+/', '', $default );
|
|
|
|
|
}
|
|
|
|
|
$sql .= " USING $default";
|
|
|
|
|
}
|
|
|
|
|
$this->db->query( $sql );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
protected function setDefault( $table, $field, $default ) {
|
|
|
|
|
|
|
|
|
|
$info = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( $info->defaultValue() !== $default ) {
|
|
|
|
|
$this->output( "Changing '$table.$field' default value\n" );
|
|
|
|
|
$this->db->query( "ALTER TABLE $table ALTER $field SET DEFAULT " . $default );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-24 10:01:51 +00:00
|
|
|
protected function changeNullableField( $table, $field, $null ) {
|
2010-08-22 08:07:26 +00:00
|
|
|
$fi = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( is_null( $fi ) ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...ERROR: expected column $table.$field to exist\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
exit( 1 );
|
|
|
|
|
}
|
2010-11-21 19:56:51 +00:00
|
|
|
if ( $fi->isNullable() ) {
|
2010-08-22 08:07:26 +00:00
|
|
|
# # It's NULL - does it need to be NOT NULL?
|
|
|
|
|
if ( 'NOT NULL' === $null ) {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Changing '$table.$field' to not allow NULLs\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "ALTER TABLE $table ALTER $field SET NOT NULL" );
|
|
|
|
|
} else {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...column '$table.$field' is already set as NULL\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
# # It's NOT NULL - does it need to be NULL?
|
|
|
|
|
if ( 'NULL' === $null ) {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Changing '$table.$field' to allow NULLs\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "ALTER TABLE $table ALTER $field DROP NOT NULL" );
|
2013-10-08 11:43:42 +00:00
|
|
|
} else {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...column '$table.$field' is already set as NOT NULL\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function addPgIndex( $table, $index, $type ) {
|
|
|
|
|
if ( $this->db->indexExists( $table, $index ) ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...index '$index' on table '$table' already exists\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Creating index '$index' on table '$table' $type\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "CREATE INDEX $index ON $table $type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function addPgExtIndex( $table, $index, $type ) {
|
2010-08-22 08:32:29 +00:00
|
|
|
if ( $this->db->indexExists( $table, $index ) ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...index '$index' on table '$table' already exists\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
|
|
|
|
if ( preg_match( '/^\(/', $type ) ) {
|
2012-07-08 08:00:36 +00:00
|
|
|
$this->output( "Creating index '$index' on table '$table'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "CREATE INDEX $index ON $table $type" );
|
|
|
|
|
} else {
|
2012-07-08 08:00:36 +00:00
|
|
|
$this->applyPatch( $type, true, "Creating index '$index' on table '$table'" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 20:27:11 +00:00
|
|
|
protected function dropFkey( $table, $field ) {
|
|
|
|
|
$fi = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( is_null( $fi ) ) {
|
|
|
|
|
$this->output( "WARNING! Column '$table.$field' does not exist but it should! " .
|
|
|
|
|
"Please report this.\n" );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$conname = $fi->conname();
|
|
|
|
|
if ( $fi->conname() ) {
|
|
|
|
|
$this->output( "Dropping foreign key constraint on '$table.$field'\n" );
|
|
|
|
|
$conclause = "CONSTRAINT \"$conname\"";
|
|
|
|
|
$command = "ALTER TABLE $table DROP CONSTRAINT $conname";
|
|
|
|
|
$this->db->query( $command );
|
|
|
|
|
} else {
|
2015-02-18 05:22:40 +00:00
|
|
|
$this->output( "...foreign key constraint on '$table.$field' already does not exist\n" );
|
2014-12-08 20:27:11 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
protected function changeFkeyDeferrable( $table, $field, $clause ) {
|
|
|
|
|
$fi = $this->db->fieldInfo( $table, $field );
|
|
|
|
|
if ( is_null( $fi ) ) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->output( "WARNING! Column '$table.$field' does not exist but it should! " .
|
|
|
|
|
"Please report this.\n" );
|
2013-10-08 11:43:42 +00:00
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ( $fi->is_deferred() && $fi->is_deferrable() ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Altering column '$table.$field' to be DEFERRABLE INITIALLY DEFERRED\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$conname = $fi->conname();
|
2012-03-28 21:23:13 +00:00
|
|
|
if ( $fi->conname() ) {
|
|
|
|
|
$conclause = "CONSTRAINT \"$conname\"";
|
|
|
|
|
$command = "ALTER TABLE $table DROP CONSTRAINT $conname";
|
|
|
|
|
$this->db->query( $command );
|
|
|
|
|
} else {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->output( "Column '$table.$field' does not have a foreign key " .
|
|
|
|
|
"constraint, will be added\n" );
|
2012-03-28 21:23:13 +00:00
|
|
|
$conclause = "";
|
|
|
|
|
}
|
2013-10-23 12:16:03 +00:00
|
|
|
$command =
|
|
|
|
|
"ALTER TABLE $table ADD $conclause " .
|
|
|
|
|
"FOREIGN KEY ($field) REFERENCES $clause DEFERRABLE INITIALLY DEFERRED";
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( $command );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function convertArchive2() {
|
|
|
|
|
if ( $this->db->tableExists( "archive2" ) ) {
|
|
|
|
|
if ( $this->db->ruleExists( 'archive', 'archive_insert' ) ) {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Dropping rule 'archive_insert'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( 'DROP RULE archive_insert ON archive' );
|
|
|
|
|
}
|
|
|
|
|
if ( $this->db->ruleExists( 'archive', 'archive_delete' ) ) {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Dropping rule 'archive_delete'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( 'DROP RULE archive_delete ON archive' );
|
|
|
|
|
}
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->applyPatch(
|
|
|
|
|
'patch-remove-archive2.sql',
|
|
|
|
|
false,
|
|
|
|
|
"Converting 'archive2' back to normal archive table"
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...obsolete table 'archive2' does not exist\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function checkOiDeleted() {
|
|
|
|
|
if ( $this->db->fieldInfo( 'oldimage', 'oi_deleted' )->type() !== 'smallint' ) {
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Changing 'oldimage.oi_deleted' to type 'smallint'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "ALTER TABLE oldimage ALTER oi_deleted DROP DEFAULT" );
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->db->query(
|
|
|
|
|
"ALTER TABLE oldimage ALTER oi_deleted TYPE SMALLINT USING (oi_deleted::smallint)" );
|
2010-08-22 08:07:26 +00:00
|
|
|
$this->db->query( "ALTER TABLE oldimage ALTER oi_deleted SET DEFAULT 0" );
|
|
|
|
|
} else {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...column 'oldimage.oi_deleted' is already of type 'smallint'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function checkOiNameConstraint() {
|
|
|
|
|
if ( $this->db->hasConstraint( "oldimage_oi_name_fkey_cascaded" ) ) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->output( "...table 'oldimage' has correct cascading delete/update " .
|
|
|
|
|
"foreign key to image\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
|
|
|
|
if ( $this->db->hasConstraint( "oldimage_oi_name_fkey" ) ) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->db->query(
|
|
|
|
|
"ALTER TABLE oldimage DROP CONSTRAINT oldimage_oi_name_fkey" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
if ( $this->db->hasConstraint( "oldimage_oi_name_fkey_cascade" ) ) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->db->query(
|
|
|
|
|
"ALTER TABLE oldimage DROP CONSTRAINT oldimage_oi_name_fkey_cascade" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
2011-02-04 20:05:05 +00:00
|
|
|
$this->output( "Making foreign key on table 'oldimage' (to image) a cascade delete/update\n" );
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->db->query(
|
|
|
|
|
"ALTER TABLE oldimage ADD CONSTRAINT oldimage_oi_name_fkey_cascaded " .
|
|
|
|
|
"FOREIGN KEY (oi_name) REFERENCES image(img_name) " .
|
|
|
|
|
"ON DELETE CASCADE ON UPDATE CASCADE" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function checkPageDeletedTrigger() {
|
|
|
|
|
if ( !$this->db->triggerExists( 'page', 'page_deleted' ) ) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->applyPatch(
|
|
|
|
|
'patch-page_deleted.sql',
|
|
|
|
|
false,
|
|
|
|
|
"Adding function and trigger 'page_deleted' to table 'page'"
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...table 'page' has 'page_deleted' trigger\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-05 15:08:10 +00:00
|
|
|
protected function dropIndex( $table, $index, $patch = '', $fullpath = false ) {
|
2012-03-22 02:42:44 +00:00
|
|
|
if ( $this->db->indexExists( $table, $index ) ) {
|
|
|
|
|
$this->output( "Dropping obsolete index '$index'\n" );
|
2013-04-13 11:36:24 +00:00
|
|
|
$this->db->query( "DROP INDEX \"" . $index . "\"" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
protected function checkIndex( $index, $should_be, $good_def ) {
|
|
|
|
|
$pu = $this->db->indexAttributes( $index );
|
|
|
|
|
if ( !empty( $pu ) && $pu != $should_be ) {
|
|
|
|
|
$this->output( "Dropping obsolete version of index '$index'\n" );
|
2013-04-13 11:36:24 +00:00
|
|
|
$this->db->query( "DROP INDEX \"" . $index . "\"" );
|
2012-03-22 02:42:44 +00:00
|
|
|
$pu = array();
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
2012-03-22 02:42:44 +00:00
|
|
|
$this->output( "...no need to drop index '$index'\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
if ( empty( $pu ) ) {
|
|
|
|
|
$this->output( "Creating index '$index'\n" );
|
|
|
|
|
$this->db->query( $good_def );
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
2012-03-22 02:42:44 +00:00
|
|
|
$this->output( "...index '$index' exists\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function checkRevUserFkey() {
|
|
|
|
|
if ( $this->fkeyDeltype( 'revision_rev_user_fkey' ) == 'r' ) {
|
2012-03-14 00:36:11 +00:00
|
|
|
$this->output( "...constraint 'revision_rev_user_fkey' is ON DELETE RESTRICT\n" );
|
2010-08-22 08:07:26 +00:00
|
|
|
} else {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->applyPatch(
|
|
|
|
|
'patch-revision_rev_user_fkey.sql',
|
|
|
|
|
false,
|
|
|
|
|
"Changing constraint 'revision_rev_user_fkey' to ON DELETE RESTRICT"
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function checkIwlPrefix() {
|
|
|
|
|
if ( $this->db->indexExists( 'iwlinks', 'iwl_prefix' ) ) {
|
2013-10-23 12:16:03 +00:00
|
|
|
$this->applyPatch(
|
|
|
|
|
'patch-rename-iwl_prefix.sql',
|
|
|
|
|
false,
|
|
|
|
|
"Replacing index 'iwl_prefix' with 'iwl_prefix_title_from'"
|
|
|
|
|
);
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-22 02:42:44 +00:00
|
|
|
protected function addInterwikiType() {
|
2012-07-08 08:00:36 +00:00
|
|
|
$this->applyPatch( 'patch-add_interwiki.sql', false, "Refreshing add_interwiki()" );
|
2012-03-22 02:42:44 +00:00
|
|
|
}
|
|
|
|
|
|
2010-08-22 08:07:26 +00:00
|
|
|
protected function tsearchFixes() {
|
|
|
|
|
# Tweak the page_title tsearch2 trigger to filter out slashes
|
|
|
|
|
# This is create or replace, so harmless to call if not needed
|
2012-07-08 08:00:36 +00:00
|
|
|
$this->applyPatch( 'patch-ts2pagetitle.sql', false, "Refreshing ts2_page_title()" );
|
2010-08-22 08:07:26 +00:00
|
|
|
|
2010-12-14 12:47:37 +00:00
|
|
|
# If the server is 8.3 or higher, rewrite the tsearch2 triggers
|
|
|
|
|
# in case they have the old 'default' versions
|
2010-08-22 08:07:26 +00:00
|
|
|
# Gather version numbers in case we need them
|
|
|
|
|
if ( $this->db->getServerVersion() >= 8.3 ) {
|
2012-07-08 08:00:36 +00:00
|
|
|
$this->applyPatch( 'patch-tsearch2funcs.sql', false, "Rewriting tsearch2 triggers" );
|
2010-08-22 08:07:26 +00:00
|
|
|
}
|
2010-08-15 18:55:08 +00:00
|
|
|
}
|
2014-08-12 06:35:35 +00:00
|
|
|
|
|
|
|
|
protected function rebuildTextSearch() {
|
|
|
|
|
if ( $this->updateRowExists( 'patch-textsearch_bug66650.sql' ) ) {
|
|
|
|
|
$this->output( "...bug 66650 already fixed or not applicable.\n" );
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
$this->applyPatch( 'patch-textsearch_bug66650.sql', false, "Rebuilding text search for bug 66650" );
|
|
|
|
|
}
|
2010-08-15 18:55:08 +00:00
|
|
|
}
|