From: saper Date: Thu, 22 Mar 2012 02:42:44 +0000 (+0100) Subject: Fix PostgreSQL updater to produce 1.19 schema X-Git-Tag: 1.31.0-rc.0~23944^2 X-Git-Url: http://git.cyclocoop.org/%24image?a=commitdiff_plain;h=f752cf80423615b380cf5612a3f1f68a6b9d0173;p=lhc%2Fweb%2Fwiklou.git Fix PostgreSQL updater to produce 1.19 schema * PostgresField now reports column default value * DatabasePostgres::indexAttributes reports index details * Perform schema update in one transaction With this change we can sucessfully update MediaWiki 1.7.3 schema to trunk^Wmaster Patch set 2: Rebased against master. PLEASE check carefully to make sure I got those conflicted files right. Conflicts: includes/db/DatabasePostgres.php includes/installer/PostgresUpdater.php Change-Id: Iebb6855e8f6f44470bbb1dc5ab9ac1abb513adfe --- diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php index 6e0a1451fe..471dffa7fd 100644 --- a/includes/db/DatabasePostgres.php +++ b/includes/db/DatabasePostgres.php @@ -19,6 +19,8 @@ class PostgresField implements Field { $q = <<realTableName( 'mwuser', $format ); + return 'mwuser'; case 'text': - return $this->realTableName( 'pagecontent', $format ); + return 'pagecontent'; default: - return $this->realTableName( $name, $format ); + return parent::tableName( $name, $format ); } } - /* Don't cheat on installer */ - function realTableName( $name, $format = 'quoted' ) { - return parent::tableName( $name, $format ); - } - /** * Return the next in a sequence, save the value for retrieval via insertId() * @return null @@ -994,7 +992,7 @@ class DatabasePostgres extends DatabaseBase { if ( !$schema ) { $schema = $this->getCoreSchema(); } - $table = $this->realTableName( $table, 'raw' ); + $table = $this->tableName( $table, 'raw' ); $etable = $this->addQuotes( $table ); $eschema = $this->addQuotes( $schema ); $SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n " diff --git a/includes/installer/DatabaseUpdater.php b/includes/installer/DatabaseUpdater.php index 6ff0af9a49..fee4b2a2cc 100644 --- a/includes/installer/DatabaseUpdater.php +++ b/includes/installer/DatabaseUpdater.php @@ -272,6 +272,7 @@ abstract class DatabaseUpdater { public function doUpdates( $what = array( 'core', 'extensions', 'purge', 'stats' ) ) { global $wgLocalisationCacheConf, $wgVersion; + $this->db->begin( __METHOD__ ); $what = array_flip( $what ); if ( isset( $what['core'] ) ) { $this->runUpdates( $this->getCoreUpdateList(), false ); @@ -294,6 +295,7 @@ abstract class DatabaseUpdater { $this->rebuildLocalisationCache(); } } + $this->db->commit( __METHOD__ ); } /** diff --git a/includes/installer/PostgresInstaller.php b/includes/installer/PostgresInstaller.php index cd83c463ee..5144686cfb 100644 --- a/includes/installer/PostgresInstaller.php +++ b/includes/installer/PostgresInstaller.php @@ -541,7 +541,7 @@ class PostgresInstaller extends DatabaseInstaller { */ $conn = $status->value; - if( $conn->tableExists( 'user' ) ) { + if( $conn->tableExists( 'archive' ) ) { $status->warning( 'config-install-tables-exist' ); $this->enableLB(); return $status; diff --git a/includes/installer/PostgresUpdater.php b/includes/installer/PostgresUpdater.php index f5f8c41b14..1bb3b9bfb0 100644 --- a/includes/installer/PostgresUpdater.php +++ b/includes/installer/PostgresUpdater.php @@ -29,8 +29,11 @@ class PostgresUpdater extends DatabaseUpdater { return array( # rename tables 1.7.3 # r15791 Change reserved word table names "user" and "text" - array( 'renameTable', 'user', 'mwuser'), - array( 'renameTable', 'text', 'pagecontent'), + array( 'renameTable', 'user', 'mwuser' ), + array( 'renameTable', 'text', 'pagecontent' ), + array( 'renameIndex', 'mwuser', 'user_pkey', 'mwuser_pkey'), + array( 'renameIndex', 'mwuser', 'user_user_name_key', 'mwuser_user_name_key' ), + array( 'renameIndex', 'pagecontent','text_pkey', 'pagecontent_pkey' ), # new sequences array( 'addSequence', 'logging_log_id_seq' ), @@ -40,12 +43,19 @@ class PostgresUpdater extends DatabaseUpdater { 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', 'category_id_seq', 'category_cat_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' ), + # since r58263 + array( 'renameSequence', 'category_id_seq', 'category_cat_id_seq'), + + # 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' ), + # new tables array( 'addTable', 'category', 'patch-category.sql' ), array( 'addTable', 'page', 'patch-page.sql' ), @@ -69,11 +79,13 @@ class PostgresUpdater extends DatabaseUpdater { array( 'addTable', 'uploadstash', 'patch-uploadstash.sql' ), array( 'addTable', 'user_former_groups','patch-user_former_groups.sql' ), array( 'addTable', 'config', 'patch-config.sql' ), + array( 'addTable', 'external_user','patch-external_user.sql' ), # Needed before new field array( 'convertArchive2' ), # new fields + 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' ), @@ -177,6 +189,11 @@ class PostgresUpdater extends DatabaseUpdater { array( 'changeNullableField', 'oldimage', 'oi_timestamp', 'NULL' ), array( 'changeNullableField', 'oldimage', 'oi_major_mime', 'NULL' ), array( 'changeNullableField', 'oldimage', 'oi_minor_mime', 'NULL' ), + array( 'setDefault', 'image', 'img_metadata', '\'\x\'::bytea'), + array( 'changeNullableField', 'image', 'img_metadata', 'NOT NULL'), + array( 'setDefault', 'filearchive', 'fa_metadata', '\'\x\'::bytea'), + array( 'changeNullableField', 'filearchive', 'fa_metadata', 'NOT NULL'), + array( 'changeNullableField', 'recentchanges', 'rc_cur_id', 'NULL' ), array( 'checkOiDeleted' ), @@ -195,12 +212,78 @@ class PostgresUpdater extends DatabaseUpdater { array( 'addPgIndex', 'iwlinks', 'iwl_prefix_title_from', '(iwl_prefix, iwl_title, iwl_from)' ), array( 'addPgIndex', 'job', 'job_timestamp_idx', '(job_timestamp)' ), + array( 'checkIndex', 'pagelink_unique', array( + array('pl_from', 'int4_ops', 'btree', 0), + array('pl_namespace', 'int2_ops', 'btree', 0), + array('pl_title', 'text_ops', 'btree', 0), + ), + 'CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title)' ), + array( 'checkIndex', 'cl_sortkey', array( + array('cl_to', 'text_ops', 'btree', 0), + array('cl_sortkey', 'text_ops', 'btree', 0), + array('cl_from', 'int4_ops', 'btree', 0), + ), + 'CREATE INDEX cl_sortkey ON "categorylinks" USING "btree" ("cl_to", "cl_sortkey", "cl_from")' ), + array( 'checkIndex', 'logging_times', array( + array('log_timestamp', 'timestamptz_ops', 'btree', 0), + ), + 'CREATE INDEX "logging_times" ON "logging" USING "btree" ("log_timestamp")' ), + array( 'dropIndex', 'oldimage', 'oi_name' ), + array( 'checkIndex', 'oi_name_archive_name', array( + array('oi_name', 'text_ops', 'btree', 0), + array('oi_archive_name', 'text_ops', 'btree', 0), + ), + 'CREATE INDEX "oi_name_archive_name" ON "oldimage" USING "btree" ("oi_name", "oi_archive_name")' ), + array( 'checkIndex', 'oi_name_timestamp', array( + array('oi_name', 'text_ops', 'btree', 0), + array('oi_timestamp', 'timestamptz_ops', 'btree', 0), + ), + 'CREATE INDEX "oi_name_timestamp" ON "oldimage" USING "btree" ("oi_name", "oi_timestamp")' ), + array( 'checkIndex', 'page_main_title', array( + array('page_title', 'text_pattern_ops', 'btree', 0), + ), + 'CREATE INDEX "page_main_title" ON "page" USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 0)' ), + array( 'checkIndex', 'page_mediawiki_title', array( + array('page_title', 'text_pattern_ops', 'btree', 0), + ), + 'CREATE INDEX "page_mediawiki_title" ON "page" USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 8)' ), + array( 'checkIndex', 'page_project_title', array( + array('page_title', 'text_pattern_ops', 'btree', 0), + ), + 'CREATE INDEX "page_project_title" ON "page" USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 4)' ), + array( 'checkIndex', 'page_talk_title', array( + array('page_title', 'text_pattern_ops', 'btree', 0), + ), + 'CREATE INDEX "page_talk_title" ON "page" USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 1)' ), + array( 'checkIndex', 'page_user_title', array( + array('page_title', 'text_pattern_ops', 'btree', 0), + ), + 'CREATE INDEX "page_user_title" ON "page" USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 2)' ), + array( 'checkIndex', 'page_utalk_title', array( + array('page_title', 'text_pattern_ops', 'btree', 0), + ), + 'CREATE INDEX "page_utalk_title" ON "page" USING "btree" ("page_title" "text_pattern_ops") WHERE ("page_namespace" = 3)' ), + array( 'checkIndex', 'ts2_page_text', array( + array('textvector', 'tsvector_ops', 'gist', 0), + ), + 'CREATE INDEX "ts2_page_text" ON "pagecontent" USING "gist" ("textvector")' ), + array( 'checkIndex', 'ts2_page_title', array( + array('titlevector', 'tsvector_ops', 'gist', 0), + ), + 'CREATE INDEX "ts2_page_title" ON "page" USING "gist" ("titlevector")' ), + array( 'checkOiNameConstraint' ), array( 'checkPageDeletedTrigger' ), - array( 'checkRcCurIdNullable' ), - array( 'checkPagelinkUniqueIndex' ), array( 'checkRevUserFkey' ), - array( 'checkIpbAdress' ), + array( 'dropIndex', 'ipblocks', 'ipb_address'), + array( 'checkIndex', 'ipb_address_unique', array( + array('ipb_address', 'text_ops', 'btree', 0), + array('ipb_user', 'int4_ops', 'btree', 0), + array('ipb_auto', 'int2_ops', 'btree', 0), + array('ipb_anon_only', 'int2_ops', 'btree', 0), + ), + 'CREATE UNIQUE INDEX ipb_address_unique ON ipblocks (ipb_address,ipb_user,ipb_auto,ipb_anon_only)' ), + array( 'checkIwlPrefix' ), # All FK columns should be deferred @@ -232,6 +315,8 @@ class PostgresUpdater extends DatabaseUpdater { array( 'changeFkeyDeferrable', 'user_properties', 'up_user', 'mwuser(user_id) ON DELETE CASCADE' ), array( 'changeFkeyDeferrable', 'watchlist', 'wl_user', 'mwuser(user_id) ON DELETE CASCADE' ), + # r81574 + array( 'addInterwikiType' ), # end array( 'tsearchFixes' ), ); @@ -392,10 +477,13 @@ END; return $d; } - protected function addSequence( $ns ) { + protected function addSequence( $table, $pkey, $ns ) { if ( !$this->db->sequenceExists( $ns ) ) { $this->output( "Creating sequence $ns\n" ); $this->db->query( "CREATE SEQUENCE $ns" ); + if( $pkey !== false ) { + $this->setDefault( $table, $pkey, '"nextval"(\'"' . $ns . '"\'::"regclass")' ); + } } } @@ -410,12 +498,22 @@ END; } } - protected function renameTable( $old, $new ) { + protected function renameTable( $old, $new, $patch = false ) { if ( $this->db->tableExists( $old ) ) { $this->output( "Renaming table $old to $new\n" ); $old = $this->db->realTableName( $old, "quoted" ); $new = $this->db->realTableName( $new, "quoted" ); $this->db->query( "ALTER TABLE $old RENAME TO $new" ); + if( $patch !== false ) { + $this->applyPatch( $patch ); + } + } + } + + protected function renameIndex( $table, $old, $new ) { + if ( $this->db->indexExists( $table, $old ) ) { + $this->output( "Renaming index $old to $new\n" ); + $this->db->query( "ALTER INDEX $old RENAME TO $new" ); } } @@ -451,13 +549,20 @@ END; } $sql .= " USING $default"; } - $this->db->begin( __METHOD__ ); $this->db->query( $sql ); - $this->db->commit( __METHOD__ ); } } - protected function changeNullableField( $table, $field, $null ) { + 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 ); + } + } + + protected function changeNullableField( $table, $field, $null) { $fi = $this->db->fieldInfo( $table, $field ); if ( is_null( $fi ) ) { $this->output( "...ERROR: expected column $table.$field to exist\n" ); @@ -581,31 +686,28 @@ END; } } - protected function checkRcCurIdNullable(){ - $fi = $this->db->fieldInfo( 'recentchanges', 'rc_cur_id' ); - if ( !$fi->isNullable() ) { - $this->output( "Removing NOT NULL constraint from 'recentchanges.rc_cur_id'\n" ); - $this->applyPatch( 'patch-rc_cur_id-not-null.sql' ); - } else { - $this->output( "...column 'recentchanges.rc_cur_id' has a NOT NULL constraint\n" ); + protected function dropIndex( $table, $index ) { + if ( $this->db->indexExists( $table, $index ) ) { + $this->output( "Dropping obsolete index '$index'\n" ); + $this->db->query( "DROP INDEX \"". $index ."\"" ); } } - protected function checkPagelinkUniqueIndex() { - $pu = $this->describeIndex( 'pagelink_unique' ); - if ( !is_null( $pu ) && ( $pu[0] != 'pl_from' || $pu[1] != 'pl_namespace' || $pu[2] != 'pl_title' ) ) { - $this->output( "Dropping obsolete version of index 'pagelink_unique index'\n" ); - $this->db->query( 'DROP INDEX pagelink_unique' ); - $pu = null; + 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" ); + $this->db->query( "DROP INDEX \"". $index ."\"" ); + $pu = array(); } else { - $this->output( "...obsolete version of index 'pagelink_unique index' does not exist\n" ); + $this->output( "...no need to drop index '$index'\n" ); } - if ( is_null( $pu ) ) { - $this->output( "Creating index 'pagelink_unique index'\n" ); - $this->db->query( 'CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title)' ); + if ( empty( $pu ) ) { + $this->output( "Creating index '$index'\n" ); + $this->db->query( $good_def ); } else { - $this->output( "...index 'pagelink_unique_index' already exists\n" ); + $this->output( "...index '$index' exists\n" ); } } @@ -618,19 +720,6 @@ END; } } - protected function checkIpbAdress() { - if ( $this->db->indexExists( 'ipblocks', 'ipb_address' ) ) { - $this->output( "Removing deprecated index 'ipb_address'...\n" ); - $this->db->query( 'DROP INDEX ipb_address' ); - } - if ( $this->db->indexExists( 'ipblocks', 'ipb_address_unique' ) ) { - $this->output( "...have ipb_address_unique\n" ); - } else { - $this->output( "Adding ipb_address_unique index\n" ); - $this->applyPatch( 'patch-ipb_address_unique.sql' ); - } - } - protected function checkIwlPrefix() { if ( $this->db->indexExists( 'iwlinks', 'iwl_prefix' ) ) { $this->output( "Replacing index 'iwl_prefix' with 'iwl_prefix_from_title'...\n" ); @@ -638,6 +727,11 @@ END; } } + protected function addInterwikiType() { + $this->output( "Refreshing add_interwiki()...\n" ); + $this->applyPatch( 'patch-add_interwiki.sql' ); + } + 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 diff --git a/maintenance/postgres/archives/patch-add_interwiki.sql b/maintenance/postgres/archives/patch-add_interwiki.sql new file mode 100644 index 0000000000..6c08af7a8d --- /dev/null +++ b/maintenance/postgres/archives/patch-add_interwiki.sql @@ -0,0 +1,14 @@ +DROP FUNCTION IF EXISTS add_interwiki(TEXT,INT,CHARACTER) CASCADE; +CREATE OR REPLACE FUNCTION "add_interwiki" (TEXT,INT,SMALLINT) RETURNS INT LANGUAGE SQL AS +$mw$ + INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES ($1,$2,$3); + SELECT 1; +$mw$; + +DROP FUNCTION IF EXISTS add_interwiki(TEXT,INT,CHARACTER) CASCADE; +CREATE OR REPLACE FUNCTION "add_interwiki" (TEXT,INT,SMALLINT) RETURNS INT LANGUAGE SQL AS +$mw$ + INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES ($1,$2,$3); + SELECT 1; +$mw$; + diff --git a/maintenance/postgres/archives/patch-category.sql b/maintenance/postgres/archives/patch-category.sql index 5e0d620f5c..266b1d00e1 100644 --- a/maintenance/postgres/archives/patch-category.sql +++ b/maintenance/postgres/archives/patch-category.sql @@ -1,8 +1,8 @@ -CREATE SEQUENCE category_id_seq; +CREATE SEQUENCE category_cat_id_seq; CREATE TABLE category ( - cat_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('category_id_seq'), + cat_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('category_cat_id_seq'), cat_title TEXT NOT NULL, cat_pages INTEGER NOT NULL DEFAULT 0, cat_subcats INTEGER NOT NULL DEFAULT 0, diff --git a/maintenance/postgres/archives/patch-external_user.sql b/maintenance/postgres/archives/patch-external_user.sql new file mode 100644 index 0000000000..242e4fafa4 --- /dev/null +++ b/maintenance/postgres/archives/patch-external_user.sql @@ -0,0 +1,14 @@ +CREATE TABLE external_user ( + eu_local_id INTEGER NOT NULL PRIMARY KEY, + eu_external_id TEXT +); + +CREATE UNIQUE INDEX eu_external_id ON external_user (eu_external_id); + +CREATE TABLE external_user ( + eu_local_id INTEGER NOT NULL PRIMARY KEY, + eu_external_id TEXT +); + +CREATE UNIQUE INDEX eu_external_id ON external_user (eu_external_id); + diff --git a/maintenance/postgres/archives/patch-ipb_address_unique.sql b/maintenance/postgres/archives/patch-ipb_address_unique.sql index e618f99ccf..e69de29bb2 100644 --- a/maintenance/postgres/archives/patch-ipb_address_unique.sql +++ b/maintenance/postgres/archives/patch-ipb_address_unique.sql @@ -1 +0,0 @@ -CREATE UNIQUE INDEX ipb_address_unique ON ipblocks (ipb_address,ipb_user,ipb_auto,ipb_anon_only); diff --git a/maintenance/postgres/archives/patch-log_search.sql b/maintenance/postgres/archives/patch-log_search.sql index 20a61fd767..4c0b3c61f6 100644 --- a/maintenance/postgres/archives/patch-log_search.sql +++ b/maintenance/postgres/archives/patch-log_search.sql @@ -5,5 +5,5 @@ CREATE TABLE log_search ( ls_log_id INTEGER NOT NULL DEFAULT 0 ); -ALTER TABLE log_search ADD CONSTRAINT log_search_pk PRIMARY KEY(ls_field, ls_value, ls_log_id); +ALTER TABLE log_search ADD CONSTRAINT log_search_pkey PRIMARY KEY(ls_field, ls_value, ls_log_id); CREATE INDEX ls_log_id ON log_search (ls_log_id); diff --git a/maintenance/postgres/archives/patch-module_deps.sql b/maintenance/postgres/archives/patch-module_deps.sql index 703dcdaf5b..bd7bb1f0bc 100644 --- a/maintenance/postgres/archives/patch-module_deps.sql +++ b/maintenance/postgres/archives/patch-module_deps.sql @@ -4,4 +4,4 @@ CREATE TABLE module_deps ( md_deps TEXT NOT NULL ); -CREATE UNIQUE INDEX md_module_skin_idx ON module_deps (md_module, md_skin); +CREATE UNIQUE INDEX md_module_skin ON module_deps (md_module, md_skin); diff --git a/maintenance/postgres/archives/patch-msg_resource.sql b/maintenance/postgres/archives/patch-msg_resource.sql index 00d8207341..68756d1af0 100644 --- a/maintenance/postgres/archives/patch-msg_resource.sql +++ b/maintenance/postgres/archives/patch-msg_resource.sql @@ -5,4 +5,4 @@ CREATE TABLE msg_resource ( mr_timestamp TIMESTAMPTZ NOT NULL ); -CREATE UNIQUE INDEX mr_resource_lang_idx ON msg_resource (mr_resource, mr_lang); +CREATE UNIQUE INDEX mr_resource_lang ON msg_resource (mr_resource, mr_lang); diff --git a/maintenance/postgres/archives/patch-msg_resource_links.sql b/maintenance/postgres/archives/patch-msg_resource_links.sql index e7b80219fa..88109da3c9 100644 --- a/maintenance/postgres/archives/patch-msg_resource_links.sql +++ b/maintenance/postgres/archives/patch-msg_resource_links.sql @@ -3,4 +3,4 @@ CREATE TABLE msg_resource_links ( mrl_message TEXT NOT NULL ); -CREATE UNIQUE INDEX mrl_message_resource_idx ON msg_resource_links (mrl_message, mrl_resource); +CREATE UNIQUE INDEX mrl_message_resource ON msg_resource_links (mrl_message, mrl_resource);