MediaWiki REL1_37
PostgresUpdater.php
Go to the documentation of this file.
1<?php
25
33
37 protected $db;
38
42 protected function getCoreUpdateList() {
43 return [
44 // Exception to the sequential updates. Renaming pagecontent and mwuser.
45 // Introduced in 1.36.
46 [ 'renameTable', 'pagecontent', 'text' ],
47 // Introduced in 1.37.
48 [ 'renameTable', 'mwuser', 'user' ],
49
50 // 1.28
51 [ 'addPgIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
52 '( rc_namespace, rc_type, rc_patrolled, rc_timestamp )' ],
53 [ 'addPgField', 'change_tag', 'ct_id',
54 "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('change_tag_ct_id_seq')" ],
55
56 // 1.29
57 [ 'addPgField', 'externallinks', 'el_index_60', "BYTEA NOT NULL DEFAULT ''" ],
58 [ 'addPgIndex', 'externallinks', 'el_index_60', '( el_index_60, el_id )' ],
59 [ 'addPgIndex', 'externallinks', 'el_from_index_60', '( el_from, el_index_60, el_id )' ],
60 [ 'addPgField', 'user_groups', 'ug_expiry', "TIMESTAMPTZ NULL" ],
61 [ 'addPgIndex', 'user_groups', 'user_groups_expiry', '( ug_expiry )' ],
62
63 // 1.30
64 [ 'addPgEnumValue', 'media_type', '3D' ],
65 [ 'setDefault', 'revision', 'rev_comment', '' ],
66 [ 'changeNullableField', 'revision', 'rev_comment', 'NOT NULL', true ],
67 [ 'setDefault', 'archive', 'ar_comment', '' ],
68 [ 'changeNullableField', 'archive', 'ar_comment', 'NOT NULL', true ],
69 [ 'addPgField', 'archive', 'ar_comment_id', 'INTEGER NOT NULL DEFAULT 0' ],
70 [ 'setDefault', 'ipblocks', 'ipb_reason', '' ],
71 [ 'addPgField', 'ipblocks', 'ipb_reason_id', 'INTEGER NOT NULL DEFAULT 0' ],
72 [ 'setDefault', 'image', 'img_description', '' ],
73 [ 'setDefault', 'oldimage', 'oi_description', '' ],
74 [ 'changeNullableField', 'oldimage', 'oi_description', 'NOT NULL', true ],
75 [ 'addPgField', 'oldimage', 'oi_description_id', 'INTEGER NOT NULL DEFAULT 0' ],
76 [ 'setDefault', 'filearchive', 'fa_deleted_reason', '' ],
77 [ 'changeNullableField', 'filearchive', 'fa_deleted_reason', 'NOT NULL', true ],
78 [ 'addPgField', 'filearchive', 'fa_deleted_reason_id', 'INTEGER NOT NULL DEFAULT 0' ],
79 [ 'setDefault', 'filearchive', 'fa_description', '' ],
80 [ 'addPgField', 'filearchive', 'fa_description_id', 'INTEGER NOT NULL DEFAULT 0' ],
81 [ 'setDefault', 'recentchanges', 'rc_comment', '' ],
82 [ 'changeNullableField', 'recentchanges', 'rc_comment', 'NOT NULL', true ],
83 [ 'addPgField', 'recentchanges', 'rc_comment_id', 'INTEGER NOT NULL DEFAULT 0' ],
84 [ 'setDefault', 'logging', 'log_comment', '' ],
85 [ 'changeNullableField', 'logging', 'log_comment', 'NOT NULL', true ],
86 [ 'addPgField', 'logging', 'log_comment_id', 'INTEGER NOT NULL DEFAULT 0' ],
87 [ 'setDefault', 'protected_titles', 'pt_reason', '' ],
88 [ 'changeNullableField', 'protected_titles', 'pt_reason', 'NOT NULL', true ],
89 [ 'addPgField', 'protected_titles', 'pt_reason_id', 'INTEGER NOT NULL DEFAULT 0' ],
90 [ 'addTable', 'comment', 'patch-comment-table.sql' ],
91 [ 'addTable', 'revision_comment_temp', 'patch-revision_comment_temp-table.sql' ],
92
93 // This field was added in 1.31, but is put here so it can be used by 'migrateComments'
94 [ 'addPgField', 'image', 'img_description_id', 'INTEGER NOT NULL DEFAULT 0' ],
95
96 [ 'migrateComments' ],
97 [ 'addIndex', 'site_stats', 'site_stats_pkey', 'patch-site_stats-pk.sql' ],
98 [ 'addTable', 'ip_changes', 'patch-ip_changes.sql' ],
99
100 // 1.31
101 [ 'addTable', 'slots', 'patch-slots-table.sql' ],
102 [ 'dropPgIndex', 'slots', 'slot_role_inherited' ],
103 [ 'dropPgField', 'slots', 'slot_inherited' ],
104 [ 'addPgField', 'slots', 'slot_origin', 'INTEGER NOT NULL' ],
105 [
106 'addPgIndex',
107 'slots',
108 'slot_revision_origin_role',
109 '( slot_revision_id, slot_origin, slot_role_id )',
110 ],
111 [ 'addTable', 'content', 'patch-content-table.sql' ],
112 [ 'addTable', 'content_models', 'patch-content_models-table.sql' ],
113 [ 'addTable', 'slot_roles', 'patch-slot_roles-table.sql' ],
114 [ 'migrateArchiveText' ],
115 [ 'addTable', 'actor', 'patch-actor-table.sql' ],
116 [ 'addTable', 'revision_actor_temp', 'patch-revision_actor_temp-table.sql' ],
117 [ 'setDefault', 'revision', 'rev_user', 0 ],
118 [ 'setDefault', 'revision', 'rev_user_text', '' ],
119 [ 'setDefault', 'archive', 'ar_user', 0 ],
120 [ 'changeNullableField', 'archive', 'ar_user', 'NOT NULL', true ],
121 [ 'setDefault', 'archive', 'ar_user_text', '' ],
122 [ 'addPgField', 'archive', 'ar_actor', 'INTEGER NOT NULL DEFAULT 0' ],
123 [ 'setDefault', 'ipblocks', 'ipb_by', 0 ],
124 [ 'addPgField', 'ipblocks', 'ipb_by_actor', 'INTEGER NOT NULL DEFAULT 0' ],
125 [ 'setDefault', 'image', 'img_user', 0 ],
126 [ 'changeNullableField', 'image', 'img_user', 'NOT NULL', true ],
127 [ 'setDefault', 'image', 'img_user_text', '' ],
128 [ 'addPgField', 'image', 'img_actor', 'INTEGER NOT NULL DEFAULT 0' ],
129 [ 'setDefault', 'oldimage', 'oi_user', 0 ],
130 [ 'changeNullableField', 'oldimage', 'oi_user', 'NOT NULL', true ],
131 [ 'setDefault', 'oldimage', 'oi_user_text', '' ],
132 [ 'addPgField', 'oldimage', 'oi_actor', 'INTEGER NOT NULL DEFAULT 0' ],
133 [ 'setDefault', 'filearchive', 'fa_user', 0 ],
134 [ 'changeNullableField', 'filearchive', 'fa_user', 'NOT NULL', true ],
135 [ 'setDefault', 'filearchive', 'fa_user_text', '' ],
136 [ 'addPgField', 'filearchive', 'fa_actor', 'INTEGER NOT NULL DEFAULT 0' ],
137 [ 'setDefault', 'recentchanges', 'rc_user', 0 ],
138 [ 'changeNullableField', 'recentchanges', 'rc_user', 'NOT NULL', true ],
139 [ 'setDefault', 'recentchanges', 'rc_user_text', '' ],
140 [ 'addPgField', 'recentchanges', 'rc_actor', 'INTEGER NOT NULL DEFAULT 0' ],
141 [ 'setDefault', 'logging', 'log_user', 0 ],
142 [ 'changeNullableField', 'logging', 'log_user', 'NOT NULL', true ],
143 [ 'addPgField', 'logging', 'log_actor', 'INTEGER NOT NULL DEFAULT 0' ],
144 [ 'addPgIndex', 'logging', 'logging_actor_time_backwards', '( log_timestamp, log_actor )' ],
145 [ 'addPgIndex', 'logging', 'logging_actor_type_time', '( log_actor, log_type, log_timestamp )' ],
146 [ 'addPgIndex', 'logging', 'logging_actor_time', '( log_actor, log_timestamp )' ],
147 [ 'migrateActors' ],
148 [ 'modifyTable', 'site_stats', 'patch-site_stats-modify.sql' ],
149 [ 'populateArchiveRevId' ],
150 [ 'dropPgIndex', 'recentchanges', 'rc_namespace_title' ],
151 [
152 'addPgIndex',
153 'recentchanges',
154 'rc_namespace_title_timestamp', '( rc_namespace, rc_title, rc_timestamp )'
155 ],
156 [ 'setSequenceOwner', 'user', 'user_id', 'user_user_id_seq' ],
157 [ 'setSequenceOwner', 'actor', 'actor_id', 'actor_actor_id_seq' ],
158 [ 'setSequenceOwner', 'page', 'page_id', 'page_page_id_seq' ],
159 [ 'setSequenceOwner', 'revision', 'rev_id', 'revision_rev_id_seq' ],
160 [ 'setSequenceOwner', 'ip_changes', 'ipc_rev_id', 'ip_changes_ipc_rev_id_seq' ],
161 [ 'setSequenceOwner', 'text', 'old_id', 'text_old_id_seq' ],
162 [ 'setSequenceOwner', 'comment', 'comment_id', 'comment_comment_id_seq' ],
163 [ 'setSequenceOwner', 'page_restrictions', 'pr_id', 'page_restrictions_pr_id_seq' ],
164 [ 'setSequenceOwner', 'archive', 'ar_id', 'archive_ar_id_seq' ],
165 [ 'setSequenceOwner', 'content', 'content_id', 'content_content_id_seq' ],
166 [ 'setSequenceOwner', 'slot_roles', 'role_id', 'slot_roles_role_id_seq' ],
167 [ 'setSequenceOwner', 'content_models', 'model_id', 'content_models_model_id_seq' ],
168 [ 'setSequenceOwner', 'externallinks', 'el_id', 'externallinks_el_id_seq' ],
169 [ 'setSequenceOwner', 'ipblocks', 'ipb_id', 'ipblocks_ipb_id_seq' ],
170 [ 'setSequenceOwner', 'filearchive', 'fa_id', 'filearchive_fa_id_seq' ],
171 [ 'setSequenceOwner', 'uploadstash', 'us_id', 'uploadstash_us_id_seq' ],
172 [ 'setSequenceOwner', 'recentchanges', 'rc_id', 'recentchanges_rc_id_seq' ],
173 [ 'setSequenceOwner', 'watchlist', 'wl_id', 'watchlist_wl_id_seq' ],
174 [ 'setSequenceOwner', 'logging', 'log_id', 'logging_log_id_seq' ],
175 [ 'setSequenceOwner', 'job', 'job_id', 'job_job_id_seq' ],
176 [ 'setSequenceOwner', 'category', 'cat_id', 'category_cat_id_seq' ],
177 [ 'setSequenceOwner', 'change_tag', 'ct_id', 'change_tag_ct_id_seq' ],
178 [ 'setSequenceOwner', 'sites', 'site_id', 'sites_site_id_seq' ],
179
180 // 1.32
181 [ 'addTable', 'change_tag_def', 'patch-change_tag_def.sql' ],
182 [ 'populateExternallinksIndex60' ],
183 [ 'dropDefault', 'externallinks', 'el_index_60' ],
184 [ 'runMaintenance', DeduplicateArchiveRevId::class, 'maintenance/deduplicateArchiveRevId.php' ],
185 [ 'addPgField', 'change_tag', 'ct_tag_id', 'INTEGER NULL' ],
186 [
187 'addPgIndex',
188 'change_tag',
189 'change_tag_tag_id_id',
190 '( ct_tag_id, ct_rc_id, ct_rev_id, ct_log_id )'
191 ],
192 [ 'addPgIndex', 'archive', 'ar_revid_uniq', '(ar_rev_id)', 'unique' ],
193 [ 'dropPgIndex', 'archive', 'ar_revid' ], // Probably doesn't exist, but do it anyway.
194 [ 'populateContentTables' ],
195 [ 'addPgIndex', 'logging', 'log_type_action', '( log_type, log_action, log_timestamp )' ],
196 [ 'dropPgIndex', 'page_props', 'page_props_propname' ],
197 [ 'addIndex', 'interwiki', 'interwiki_pkey', 'patch-interwiki-pk.sql' ],
198 [ 'addIndex', 'protected_titles', 'protected_titles_pkey', 'patch-protected_titles-pk.sql' ],
199 [ 'addIndex', 'site_identifiers', 'site_identifiers_pkey', 'patch-site_identifiers-pk.sql' ],
200 [ 'addPgIndex', 'recentchanges', 'rc_this_oldid', '(rc_this_oldid)' ],
201 [ 'dropTable', 'transcache' ],
202 [ 'runMaintenance', PopulateChangeTagDef::class, 'maintenance/populateChangeTagDef.php' ],
203 [ 'dropIndex', 'change_tag', 'change_tag_rc_tag', 'patch-change_tag-change_tag_rc_tag_id.sql' ],
204 [ 'addPgField', 'ipblocks', 'ipb_sitewide', 'SMALLINT NOT NULL DEFAULT 1' ],
205 [ 'addTable', 'ipblocks_restrictions', 'patch-ipblocks_restrictions-table.sql' ],
206 [ 'migrateImageCommentTemp' ],
207 [ 'dropPgField', 'category', 'cat_hidden' ],
208 [ 'dropPgField', 'site_stats', 'ss_admins' ],
209 [ 'dropPgField', 'recentchanges', 'rc_cur_time' ],
210
211 // 1.33
212 [ 'dropField', 'change_tag', 'ct_tag', 'patch-drop-ct_tag.sql' ],
213 [ 'dropTable', 'valid_tag' ],
214 [ 'dropTable', 'tag_summary' ],
215 [ 'dropPgField', 'archive', 'ar_comment' ],
216 [ 'dropDefault', 'archive', 'ar_comment_id' ],
217 [ 'dropPgField', 'ipblocks', 'ipb_reason' ],
218 [ 'dropDefault', 'ipblocks', 'ipb_reason_id' ],
219 [ 'dropPgField', 'image', 'img_description' ],
220 [ 'dropDefault', 'image', 'img_description_id' ],
221 [ 'dropPgField', 'oldimage', 'oi_description' ],
222 [ 'dropDefault', 'oldimage', 'oi_description_id' ],
223 [ 'dropPgField', 'filearchive', 'fa_deleted_reason' ],
224 [ 'dropDefault', 'filearchive', 'fa_deleted_reason_id' ],
225 [ 'dropPgField', 'filearchive', 'fa_description' ],
226 [ 'dropDefault', 'filearchive', 'fa_description_id' ],
227 [ 'dropPgField', 'recentchanges', 'rc_comment' ],
228 [ 'dropDefault', 'recentchanges', 'rc_comment_id' ],
229 [ 'dropPgField', 'logging', 'log_comment' ],
230 [ 'dropDefault', 'logging', 'log_comment_id' ],
231 [ 'dropPgField', 'protected_titles', 'pt_reason' ],
232 [ 'dropDefault', 'protected_titles', 'pt_reason_id' ],
233
234 // 1.34
235 [ 'dropPgIndex', 'archive', 'archive_user_text' ],
236 [ 'dropPgField', 'archive', 'ar_user' ],
237 [ 'dropPgField', 'archive', 'ar_user_text' ],
238 [ 'dropDefault', 'archive', 'ar_actor' ],
239 [ 'dropPgField', 'ipblocks', 'ipb_by' ],
240 [ 'dropPgField', 'ipblocks', 'ipb_by_text' ],
241 [ 'dropDefault', 'ipblocks', 'ipb_by_actor' ],
242 [ 'dropPgField', 'image', 'img_user' ],
243 [ 'dropPgField', 'image', 'img_user_text' ],
244 [ 'dropDefault', 'image', 'img_actor' ],
245 [ 'dropPgField', 'oldimage', 'oi_user' ],
246 [ 'dropPgField', 'oldimage', 'oi_user_text' ],
247 [ 'dropDefault', 'oldimage', 'oi_actor' ],
248 [ 'dropPgField', 'filearchive', 'fa_user' ],
249 [ 'dropPgField', 'filearchive', 'fa_user_text' ],
250 [ 'dropDefault', 'filearchive', 'fa_actor' ],
251 [ 'dropPgField', 'recentchanges', 'rc_user' ],
252 [ 'dropPgField', 'recentchanges', 'rc_user_text' ],
253 [ 'dropDefault', 'recentchanges', 'rc_actor' ],
254 [ 'dropPgIndex', 'logging', 'logging_user_time' ],
255 [ 'dropPgIndex', 'logging', 'logging_user_type_time' ],
256 [ 'dropPgIndex', 'logging', 'logging_user_text_type_time' ],
257 [ 'dropPgIndex', 'logging', 'logging_user_text_time' ],
258 [ 'dropPgField', 'logging', 'log_user' ],
259 [ 'dropPgField', 'logging', 'log_user_text' ],
260 [ 'dropDefault', 'logging', 'log_actor' ],
261
262 // 1.35
263 [ 'addIndex', 'redirect', 'redirect_pkey', 'patch-redirect-pk.sql' ],
264 [ 'addTable', 'watchlist_expiry', 'patch-watchlist_expiry.sql' ],
265 [ 'setSequenceOwner', 'watchlist_expiry', 'we_item', 'watchlist_expiry_we_item_seq' ],
266 [ 'setDefault', 'user_newtalk', 'user_ip', '' ],
267 [ 'changeNullableField', 'user_newtalk', 'user_ip', 'NOT NULL', true ],
268 [ 'setDefault', 'user_newtalk', 'user_id', 0 ],
269 [ 'renameIndex', 'revision_actor_temp', 'rev_actor_timestamp', 'revactor_actor_timestamp' ],
270 [ 'renameIndex', 'revision_actor_temp',
271 'rev_page_actor_timestamp', 'revactor_page_actor_timestamp' ],
272 [ 'dropPgIndex', 'revision', 'rev_user_idx' ],
273 [ 'dropPgIndex', 'revision', 'rev_user_text_idx' ],
274 [ 'dropPgIndex', 'revision', 'rev_text_id_idx' ],
275 [ 'dropPgField', 'revision', 'rev_user' ],
276 [ 'dropPgField', 'revision', 'rev_user_text' ],
277 [ 'dropPgField', 'revision', 'rev_comment' ],
278 [ 'dropPgField', 'revision', 'rev_text_id' ],
279 [ 'dropPgField', 'revision', 'rev_content_model' ],
280 [ 'dropPgField', 'revision', 'rev_content_format' ],
281 [ 'addPgField', 'revision', 'rev_comment_id', 'INTEGER NOT NULL DEFAULT 0' ],
282 [ 'addPgField', 'revision', 'rev_actor', 'INTEGER NOT NULL DEFAULT 0' ],
283 [ 'addPgIndex', 'revision', 'rev_actor_timestamp', '(rev_actor,rev_timestamp,rev_id)' ],
284 [ 'addPgIndex', 'revision', 'rev_page_actor_timestamp', '(rev_page,rev_actor,rev_timestamp)' ],
285 [ 'dropPgField', 'archive', 'ar_text_id' ],
286 [ 'dropPgField', 'archive', 'ar_content_model' ],
287 [ 'dropPgField', 'archive', 'ar_content_format' ],
288 [ 'changeField', 'updatelog', 'ul_key', 'varchar(255)', '' ],
289 [ 'changeField', 'updatelog', 'ul_value', 'TEXT', '' ],
290 [ 'changeField', 'site_identifiers', 'si_type', 'TEXT', '' ],
291 [ 'changeField', 'site_identifiers', 'si_key', 'TEXT', '' ],
292 [ 'changeField', 'actor', 'actor_id', 'BIGINT', '' ],
293 [ 'changeField', 'actor', 'actor_name', 'TEXT', '' ],
294 [ 'changeField', 'user_former_groups', 'ufg_group', 'TEXT', '' ],
295 [ 'dropFkey', 'user_former_groups', 'ufg_user' ],
296 [ 'checkIndex', 'ipb_address_unique', [
297 [ 'ipb_address', 'text_ops', 'btree', 0 ],
298 [ 'ipb_user', 'int4_ops', 'btree', 0 ],
299 [ 'ipb_auto', 'int2_ops', 'btree', 0 ],
300 ],
301 'CREATE UNIQUE INDEX ipb_address_unique ' .
302 'ON ipblocks (ipb_address,ipb_user,ipb_auto)' ],
303
304 // 1.36
305 [ 'setDefault', 'bot_passwords', 'bp_token', '' ],
306 [ 'changeField', 'comment', 'comment_id', 'BIGINT', '' ],
307 [ 'changeField', 'slots', 'slot_revision_id', 'BIGINT', '' ],
308 [ 'changeField', 'slots', 'slot_content_id', 'BIGINT', '' ],
309 [ 'changeField', 'slots', 'slot_origin', 'BIGINT', '' ],
310 [ 'changeField', 'site_stats', 'ss_total_edits', 'BIGINT', '' ],
311 [ 'changeField', 'site_stats', 'ss_good_articles', 'BIGINT', '' ],
312 [ 'changeField', 'site_stats', 'ss_total_pages', 'BIGINT', '' ],
313 [ 'changeField', 'site_stats', 'ss_users', 'BIGINT', '' ],
314 [ 'changeField', 'site_stats', 'ss_active_users', 'BIGINT', '' ],
315 [ 'changeField', 'site_stats', 'ss_images', 'BIGINT', '' ],
316 [ 'dropFkey', 'user_properties', 'up_user' ],
317 [ 'addIndex', 'user_properties', 'user_properties_pkey', 'patch-user_properties-pk.sql' ],
318 [ 'changeField', 'log_search', 'ls_value', 'VARCHAR(255)', '' ],
319 [ 'changeField', 'content', 'content_id', 'BIGINT', '' ],
320 [ 'changeField', 'l10n_cache', 'lc_value', 'TEXT', '' ],
321 [ 'changeField', 'l10n_cache', 'lc_key', 'VARCHAR(255)', '' ],
322 [ 'addIndex', 'l10n_cache', 'l10n_cache_pkey', 'patch-l10n_cache-pk.sql' ],
323 [ 'addIndex', 'module_deps', 'module_deps_pkey', 'patch-module_deps-pk.sql' ],
324 [ 'changeField', 'redirect', 'rd_namespace', 'INT', 'rd_namespace::INT DEFAULT 0' ],
325 [ 'setDefault', 'redirect', 'rd_title', '' ],
326 [ 'setDefault', 'redirect', 'rd_from', 0 ],
327 [ 'dropFkey', 'redirect', 'rd_from' ],
328 [ 'changeField', 'redirect', 'rd_interwiki', 'VARCHAR(32)', '' ],
329 [ 'dropFkey', 'pagelinks', 'pl_from' ],
330 [ 'changeField', 'pagelinks', 'pl_namespace', 'INT', 'pl_namespace::INT DEFAULT 0' ],
331 [ 'setDefault', 'pagelinks', 'pl_title', '' ],
332 [ 'addPgIndex', 'pagelinks', 'pl_namespace', '(pl_namespace,pl_title,pl_from)' ],
333 [ 'addPgIndex', 'pagelinks', 'pl_backlinks_namespace',
334 '(pl_from_namespace,pl_namespace,pl_title,pl_from)' ],
335 [ 'dropPgIndex', 'pagelinks', 'pagelink_unique' ],
336 [ 'dropPgIndex', 'pagelinks', 'pagelinks_title' ],
337 [ 'dropFkey', 'templatelinks', 'tl_from' ],
338 [ 'changeField', 'templatelinks', 'tl_namespace', 'INT', 'tl_namespace::INT DEFAULT 0' ],
339 [ 'setDefault', 'templatelinks', 'tl_title', '' ],
340 [ 'addPgIndex', 'templatelinks', 'tl_namespace', '(tl_namespace,tl_title,tl_from)' ],
341 [ 'addPgIndex', 'templatelinks', 'tl_backlinks_namespace',
342 '(tl_from_namespace,tl_namespace,tl_title,tl_from)' ],
343 [ 'dropPgIndex', 'templatelinks', 'templatelinks_unique' ],
344 [ 'dropPgIndex', 'templatelinks', 'templatelinks_from' ],
345 [ 'dropFkey', 'imagelinks', 'il_from' ],
346 [ 'setDefault', 'imagelinks', 'il_to', '' ],
347 [ 'addPgIndex', 'imagelinks', 'il_to', '(il_to, il_from)' ],
348 [ 'addPgIndex', 'imagelinks', 'il_backlinks_namespace',
349 '(il_from_namespace, il_to, il_from)' ],
350 [ 'dropPgIndex', 'imagelinks', 'il_from' ],
351 [ 'dropFkey', 'langlinks', 'll_from' ],
352 [ 'addIndex', 'langlinks', 'langlinks_pkey', 'patch-langlinks-pk.sql' ],
353 [ 'renameIndex', 'langlinks', 'langlinks_lang_title', 'll_lang' ],
354 [ 'setDefault', 'langlinks', 'll_lang', '' ],
355 [ 'setDefault', 'langlinks', 'll_from', 0 ],
356 [ 'setDefault', 'langlinks', 'll_title', '' ],
357 [ 'changeNullableField', 'langlinks', 'll_lang', 'NOT NULL', true ],
358 [ 'changeNullableField', 'langlinks', 'll_title', 'NOT NULL', true ],
359 [ 'addIndex', 'iwlinks', 'iwlinks_pkey', 'patch-iwlinks-pk.sql' ],
360 [ 'renameIndex', 'category', 'category_title', 'cat_title' ],
361 [ 'renameIndex', 'category', 'category_pages', 'cat_pages' ],
362 [ 'dropSequence', 'watchlist_expiry', 'watchlist_expiry_we_item_seq' ],
363 [ 'changeField', 'change_tag_def', 'ctd_count', 'BIGINT', 'ctd_count::BIGINT DEFAULT 0' ],
364 [ 'dropDefault', 'change_tag_def', 'ctd_user_defined' ],
365 [ 'dropFkey', 'ipblocks_restrictions', 'ir_ipb_id' ],
366 [ 'setDefault', 'querycache', 'qc_value', 0 ],
367 [ 'changeField', 'querycache', 'qc_namespace', 'INT', 'qc_namespace::INT DEFAULT 0' ],
368 [ 'setDefault', 'querycache', 'qc_title', '' ],
369 [ 'renameIndex', 'querycache', 'querycache_type_value', 'qc_type' ],
370 [ 'renameIndex', 'querycachetwo', 'querycachetwo_type_value', 'qcc_type' ],
371 [ 'renameIndex', 'querycachetwo', 'querycachetwo_title', 'qcc_title' ],
372 [ 'renameIndex', 'querycachetwo', 'querycachetwo_titletwo', 'qcc_titletwo' ],
373 [ 'dropFkey', 'page_restrictions', 'pr_page' ],
374 [ 'addPgIndex', 'page_restrictions', 'pr_pagetype', '(pr_page, pr_type)', true ],
375 [ 'addPgIndex', 'page_restrictions', 'pr_typelevel', '(pr_type, pr_level)' ],
376 [ 'addPgIndex', 'page_restrictions', 'pr_level', '(pr_level)' ],
377 [ 'addPgIndex', 'page_restrictions', 'pr_cascade', '(pr_cascade)' ],
378 [ 'changePrimaryKey', 'page_restrictions', [ 'pr_id' ], 'page_restrictions_pk' ] ,
379 [ 'changeNullableField', 'page_restrictions', 'pr_page', 'NOT NULL', true ],
380 [ 'dropFkey', 'user_groups', 'ug_user' ],
381 [ 'setDefault', 'user_groups', 'ug_user', 0 ],
382 [ 'setDefault', 'user_groups', 'ug_group', '' ],
383 [ 'renameIndex', 'user_groups', 'user_groups_group', 'ug_group' ],
384 [ 'renameIndex', 'user_groups', 'user_groups_expiry', 'ug_expiry' ],
385 [ 'setDefault', 'querycache_info', 'qci_type', '' ],
386 [ 'setDefault', 'querycache_info', 'qci_timestamp', '1970-01-01 00:00:00+00' ],
387 [ 'changeNullableField', 'querycache_info', 'qci_type', 'NOT NULL', true ],
388 [ 'changeNullableField', 'querycache_info', 'qci_timestamp', 'NOT NULL', true ],
389 [ 'addIndex', 'querycache_info', 'querycache_info_pkey', 'patch-querycache_info-pk.sql' ],
390 [ 'setDefault', 'watchlist', 'wl_title', '' ],
391 [ 'changeField', 'watchlist', 'wl_namespace', 'INT', 'wl_namespace::INT DEFAULT 0' ],
392 [ 'dropFkey', 'watchlist', 'wl_user' ],
393 [ 'dropPgIndex', 'watchlist', 'wl_user_namespace_title' ],
394 [ 'addPgIndex', 'watchlist', 'namespace_title', '(wl_namespace, wl_title)' ],
395 [ 'checkIndex', 'wl_user', [
396 [ 'wl_user', 'text_ops', 'btree', 1 ],
397 [ 'wl_namespace', 'int4_ops', 'btree', 1 ],
398 [ 'wl_title', 'text_ops', 'btree', 1 ],
399 ],
400 'CREATE UNIQUE INDEX "wl_user" ON "watchlist" (wl_user, wl_namespace, wl_title) ' ],
401 [ 'changeField', 'sites', 'site_domain', 'VARCHAR(255)', '' ],
402 [ 'renameIndex', 'sites', 'site_global_key', 'sites_global_key' ],
403 [ 'renameIndex', 'sites', 'site_type', 'sites_type' ],
404 [ 'renameIndex', 'sites', 'site_group', 'sites_group' ],
405 [ 'renameIndex', 'sites', 'site_source', 'sites_source' ],
406 [ 'renameIndex', 'sites', 'site_language', 'sites_language' ],
407 [ 'renameIndex', 'sites', 'site_protocol', 'sites_protocol' ],
408 [ 'renameIndex', 'sites', 'site_domain', 'sites_domain' ],
409 [ 'renameIndex', 'sites', 'site_forward', 'sites_forward' ],
410 [ 'dropFkey', 'user_newtalk', 'user_id ' ],
411 [ 'renameIndex', 'user_newtalk', 'user_newtalk_id', 'un_user_id' ],
412 [ 'renameIndex', 'user_newtalk', 'user_newtalk_ip', 'un_user_ip' ],
413 [ 'changeField', 'interwiki', 'iw_prefix', 'VARCHAR(32)', '' ],
414 [ 'changeField', 'interwiki', 'iw_wikiid', 'VARCHAR(64)', '' ],
415 [ 'dropFkey', 'protected_titles', 'pt_user' ],
416 [ 'changeNullableField', 'protected_titles', 'pt_user', 'NOT NULL', true ],
417 [ 'changeNullableField', 'protected_titles', 'pt_expiry', 'NOT NULL', true ],
418 [ 'changeField', 'protected_titles', 'pt_reason_id', 'BIGINT', '' ],
419 [ 'dropDefault', 'protected_titles', 'pt_create_perm' ],
420 [ 'dropFkey', 'externallinks', 'el_from' ],
421 [ 'setDefault', 'externallinks', 'el_from', 0 ],
422 [ 'changeField', 'externallinks', 'el_index_60', 'TEXT', '' ],
423 [ 'renameIndex', 'externallinks', 'externallinks_from_to', 'el_from' ],
424 [ 'renameIndex', 'externallinks', 'externallinks_index', 'el_index' ],
425 [ 'addPgIndex', 'externallinks', 'el_to', '(el_to, el_from)' ],
426 [ 'dropSequence', 'ip_changes', 'ip_changes_ipc_rev_id_seq' ],
427 [ 'changeField', 'ip_changes', 'ipc_hex', 'TEXT', "ipc_hex::TEXT DEFAULT ''" ],
428 [ 'setDefault', 'ip_changes', 'ipc_rev_id', 0 ],
429 [ 'changeField', 'revision_comment_temp', 'revcomment_comment_id', 'BIGINT', '' ],
430 [ 'dropFkey', 'revision_actor_temp', 'revactor_page' ],
431 [ 'changeField', 'revision_actor_temp', 'revactor_actor', 'BIGINT', '' ],
432 [ 'changeNullableField', 'revision_actor_temp', 'revactor_page', 'NOT NULL', true ],
433 [ 'renameIndex', 'watchlist', 'namespace_title', 'wl_namespace_title' ],
434 [ 'dropFkey', 'page_props', 'pp_page' ],
435 // page_props primary key change moved from the Schema SQL file to here in 1.36
436 [ 'changePrimaryKey', 'page_props', [ 'pp_page', 'pp_propname' ], 'page_props_pk' ],
437 [ 'setDefault','job', 'job_cmd', '' ],
438 [ 'changeField', 'job', 'job_namespace', 'INTEGER', '' ],
439 [ 'dropPgIndex', 'job', 'job_cmd_namespace_title' ],
440 [ 'addPgIndex', 'job', 'job_cmd', '(job_cmd, job_namespace, job_title, job_params)' ],
441 [ 'renameIndex', 'job', 'job_timestamp_idx', 'job_timestamp' ],
442 [ 'changeField', 'slot_roles', 'role_id', 'INTEGER', '' ],
443 [ 'changeField', 'content_models', 'model_id', 'INTEGER', '' ],
444 [ 'renameIndex', 'page', 'page_len_idx', 'page_len' ],
445 [ 'renameIndex', 'page', 'page_random_idx', 'page_random' ],
446 [ 'renameIndex', 'page', 'page_unique_name', 'page_name_title' ],
447 [ 'addPGIndex', 'page', 'page_redirect_namespace_len', '(page_is_redirect, page_namespace, page_len)' ],
448 [ 'dropFkey', 'categorylinks', 'cl_from' ],
449 [ 'setDefault','categorylinks', 'cl_from', 0 ],
450 [ 'setDefault','categorylinks', 'cl_to', '' ],
451 [ 'setDefault','categorylinks', 'cl_sortkey', '' ],
452 [ 'setDefault','categorylinks', 'cl_collation', '' ],
453 [ 'changeNullableField', 'categorylinks', 'cl_sortkey', 'NOT NULL', true ],
454 [ 'addIndex', 'categorylinks', 'categorylinks_pkey', 'patch-categorylinks-pk.sql' ],
455 [ 'addPgIndex', 'categorylinks', 'cl_timestamp', '(cl_to, cl_timestamp)' ],
456 [ 'addPgIndex', 'categorylinks', 'cl_collation_ext', '(cl_collation, cl_to, cl_type, cl_from)' ],
457 [ 'checkIndex', 'cl_sortkey', [
458 [ 'cl_to', 'text_ops', 'btree', 1 ],
459 [ 'cl_type', 'text_ops', 'btree', 1 ],
460 [ 'cl_sortkey', 'text_ops', 'btree', 1 ],
461 [ 'cl_from', 'text_ops', 'btree', 1 ],
462 ],
463 'CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_type, cl_sortkey, cl_from)' ],
464 [ 'renameIndex', 'logging', 'logging_type_name', 'type_time' ],
465 [ 'renameIndex', 'logging', 'logging_actor_time_backwards', 'actor_time' ],
466 [ 'renameIndex', 'logging', 'logging_page_time', 'page_time' ],
467 [ 'renameIndex', 'logging', 'logging_times', 'times' ],
468 [ 'renameIndex', 'logging', 'logging_actor_type_time', 'log_actor_type_time' ],
469 [ 'renameIndex', 'logging', 'logging_page_id_time', 'log_page_id_time' ],
470 [ 'renameIndex', 'logging', 'logging_type_action', 'log_type_action' ],
471 [ 'changeNullableField', 'logging', 'log_params', 'NOT NULL', true ],
472 [ 'setDefault', 'logging', 'log_action', '' ],
473 [ 'setDefault', 'logging', 'log_type', '' ],
474 [ 'setDefault', 'logging', 'log_title', '' ],
475 [ 'setDefault', 'logging', 'log_timestamp', '1970-01-01 00:00:00+00' ],
476 [ 'changeField', 'logging', 'log_actor', 'BIGINT', '' ],
477 [ 'changeField', 'logging', 'log_comment_id', 'BIGINT', '' ],
478 [ 'changeField', 'logging', 'log_namespace', 'INT', 'log_namespace::INT DEFAULT 0' ],
479 [ 'dropPgIndex', 'logging', 'logging_actor_time' ],
480 [ 'changeField', 'uploadstash', 'us_key', 'VARCHAR(255)', '' ],
481 [ 'changeField', 'uploadstash', 'us_orig_path', 'VARCHAR(255)', '' ],
482 [ 'changeField', 'uploadstash', 'us_path', 'VARCHAR(255)', '' ],
483 [ 'changeField', 'uploadstash', 'us_source_type', 'VARCHAR(50)', '' ],
484 [ 'changeField', 'uploadstash', 'us_props', 'TEXT', '' ],
485 [ 'changeField', 'uploadstash', 'us_status', 'VARCHAR(50)', '' ],
486 [ 'changeField', 'uploadstash', 'us_sha1', 'VARCHAR(31)', '' ],
487 [ 'changeField', 'uploadstash', 'us_mime', 'VARCHAR(255)', '' ],
488 [ 'changeNullableField', 'uploadstash', 'us_key', 'NOT NULL', true ],
489 [ 'changeNullableField', 'uploadstash', 'us_user', 'NOT NULL', true ],
490 [ 'changeNullableField', 'uploadstash', 'us_orig_path', 'NOT NULL', true ],
491 [ 'changeNullableField', 'uploadstash', 'us_path', 'NOT NULL', true ],
492 [ 'changeNullableField', 'uploadstash', 'us_timestamp', 'NOT NULL', true ],
493 [ 'changeNullableField', 'uploadstash', 'us_status', 'NOT NULL', true ],
494 [ 'changeNullableField', 'uploadstash', 'us_size', 'NOT NULL', true ],
495 [ 'changeNullableField', 'uploadstash', 'us_sha1', 'NOT NULL', true ],
496 [ 'renameIndex', 'uploadstash', 'us_user_idx', 'us_user' ],
497 [ 'renameIndex', 'uploadstash', 'us_key_idx', 'us_key' ],
498 [ 'renameIndex', 'uploadstash', 'us_timestamp_idx', 'us_timestamp' ],
499 [ 'renameIndex', 'user_properties', 'user_properties_property', 'up_property' ],
500 [ 'renameIndex', 'sites', 'sites_global_key', 'site_global_key' ],
501 [ 'renameIndex', 'sites', 'sites_type', 'site_type' ],
502 [ 'renameIndex', 'sites', 'sites_group, ', 'site_group' ],
503 [ 'renameIndex', 'sites', 'sites_source', 'site_source' ],
504 [ 'renameIndex', 'sites', 'sites_language', 'site_language' ],
505 [ 'renameIndex', 'sites', 'sites_protocol', 'site_protocol' ],
506 [ 'renameIndex', 'sites', 'sites_domain', 'site_domain' ],
507 [ 'renameIndex', 'sites', 'sites_forward', 'site_forward' ],
508 [ 'renameIndex', 'logging', 'type_name', 'log_type_time' ],
509 [ 'renameIndex', 'logging', 'actor_time', 'log_actor_time' ],
510 [ 'renameIndex', 'logging', 'page_time', 'log_page_time' ],
511 [ 'renameIndex', 'logging', 'times', 'log_times' ],
512 [ 'setDefault', 'filearchive', 'fa_name', '' ],
513 [ 'setDefault', 'filearchive', 'fa_archive_name', '' ],
514 [ 'setDefault', 'filearchive', 'fa_storage_key', '' ],
515 [ 'dropFkey', 'filearchive', 'fa_deleted_user' ],
516 [ 'changeField', 'filearchive', 'fa_deleted_reason_id', 'BIGINT', '' ],
517 [ 'changeField', 'filearchive', 'fa_metadata', 'TEXT', '' ],
518 [ 'changeField', 'filearchive', 'fa_bits', 'INTEGER', '' ],
519 [ 'changeField', 'filearchive', 'fa_description_id', 'BIGINT', '' ],
520 [ 'changeField', 'filearchive', 'fa_actor', 'BIGINT', '' ],
521 [ 'renameIndex', 'filearchive', 'fa_name_time', 'fa_name' ],
522 [ 'renameIndex', 'filearchive', 'fa_dupe', 'fa_storage_group' ],
523 [ 'renameIndex', 'filearchive', 'fa_notime', 'fa_deleted_timestamp' ],
524 [ 'dropPgIndex', 'filearchive', 'fa_nouser' ],
525 [ 'addPgIndex', 'filearchive', 'fa_actor_timestamp', '(fa_actor, fa_timestamp)' ],
526 [ 'addPgIndex', 'ipblocks', 'ipb_expiry', '(ipb_expiry)' ],
527 [ 'addPgIndex', 'ipblocks', 'ipb_timestamp', '(ipb_timestamp)' ],
528 [ 'renameIndex', 'text', 'pagecontent_pkey', 'text_pkey' ],
529 [ 'changeNullableField', 'text', 'old_text', 'NOT NULL', true ],
530 [ 'changeNullableField', 'text', 'old_flags', 'NOT NULL', true ],
531 [ 'setDefault', 'oldimage', 'oi_name', '' ],
532 [ 'setDefault', 'oldimage', 'oi_archive_name', '' ],
533 [ 'setDefault', 'oldimage', 'oi_size', 0 ],
534 [ 'setDefault', 'oldimage', 'oi_width', 0 ],
535 [ 'setDefault', 'oldimage', 'oi_height', 0 ],
536 [ 'setDefault', 'oldimage', 'oi_bits', 0 ],
537 [ 'setDefault', 'oldimage', 'oi_name', '' ],
538 [ 'changeField', 'oldimage', 'oi_bits', 'INTEGER', '' ],
539 [ 'changeField', 'oldimage', 'oi_description_id', 'BIGINT', '' ],
540 [ 'changeField', 'oldimage', 'oi_actor', 'BIGINT', '' ],
541 [ 'changeField', 'oldimage', 'oi_metadata', 'TEXT', '' ],
542 [ 'dropDefault', 'oldimage', 'oi_metadata' ],
543 [ 'changeNullableField', 'oldimage', 'oi_minor_mime', 'NOT NULL', true ],
544 [ 'changeNullableField', 'oldimage', 'oi_minor_mime', 'NOT NULL', true ],
545 [ 'dropFkey', 'oldimage', 'oi_name' ],
546 [ 'addPgIndex', 'oldimage', 'oi_actor_timestamp', '(oi_actor, oi_timestamp)' ],
547 [ 'dropPgIndex', 'recentchanges', 'rc_timestamp_bot' ],
548 [ 'addPgIndex', 'recentchanges', 'rc_ns_actor', '(rc_namespace, rc_actor)' ],
549 [ 'addPgIndex', 'recentchanges', 'rc_actor', '(rc_actor, rc_timestamp)' ],
550 [ 'dropIndex', 'objectcache', 'keyname', 'patch-objectcache_keyname-pk.sql' ],
551 [ 'changeField', 'objectcache', 'value', 'TEXT', '' ],
552 [ 'changeNullableField', 'objectcache', 'value', 'NULL', true ],
553 [ 'dropFkey', 'ipblocks', 'ipb_user' ],
554 [ 'dropFkey', 'ipblocks', 'ipb_parent_block_id' ],
555 [ 'setDefault', 'ipblocks', 'ipb_user', 0 ],
556 [ 'changeNullableField', 'ipblocks', 'ipb_user', 'NOT NULL', true ],
557 [ 'changeNullableField', 'ipblocks', 'ipb_range_start', 'NOT NULL', true ],
558 [ 'changeNullableField', 'ipblocks', 'ipb_range_end', 'NOT NULL', true ],
559 [ 'changeField', 'ipblocks', 'ipb_by_actor', 'BIGINT', '' ],
560 [ 'changeField', 'ipblocks', 'ipb_reason_id', 'BIGINT', '' ],
561 [ 'renameIndex', 'archive', 'archive_name_title_timestamp', 'ar_name_title_timestamp' ],
562 [ 'dropPgIndex', 'archive', 'archive_actor' ],
563 [ 'addPgIndex', 'archive', 'ar_actor_timestamp', '(ar_actor,ar_timestamp)' ],
564 [ 'setDefault', 'image', 'img_name', '' ],
565 [ 'setDefault', 'image', 'img_size', 0 ],
566 [ 'setDefault', 'image', 'img_width', 0 ],
567 [ 'setDefault', 'image', 'img_height', 0 ],
568 [ 'setDefault', 'image', 'img_bits', 0 ],
569 [ 'changeField', 'image', 'img_bits', 'INTEGER', '' ],
570 [ 'changeField', 'image', 'img_description_id', 'BIGINT', '' ],
571 [ 'changeField', 'image', 'img_actor', 'BIGINT', '' ],
572 [ 'changeField', 'image', 'img_metadata', 'TEXT', '' ],
573 [ 'dropDefault', 'image', 'img_metadata' ],
574 [ 'changeNullableField', 'image', 'img_major_mime', 'NOT NULL', true ],
575 [ 'changeNullableField', 'image', 'img_minor_mime', 'NOT NULL', true ],
576 [ 'changeNullableField', 'image', 'img_timestamp', 'NOT NULL', true ],
577 [ 'renameIndex', 'image', 'img_size_idx', 'img_size' ],
578 [ 'renameIndex', 'image', 'img_timestamp_idx', 'img_timestamp' ],
579 [ 'addPgIndex', 'image', 'img_actor_timestamp', '(img_actor, img_timestamp)' ],
580 [ 'addPgIndex', 'image', 'img_media_mime', '(img_media_type, img_major_mime, img_minor_mime)' ],
581 [ 'renameIndex', 'site_identifiers', 'site_ids_site', 'si_site' ],
582 [ 'renameIndex', 'site_identifiers', 'site_ids_key', 'si_key' ],
583 [ 'changeField', 'recentchanges', 'rc_actor', 'BIGINT', '' ],
584 [ 'changeField', 'recentchanges', 'rc_comment_id', 'BIGINT', '' ],
585 [ 'changeField', 'recentchanges', 'rc_ip', 'TEXT', '' ],
586 [ 'changeField', 'recentchanges', 'rc_namespace', 'INTEGER', '' ],
587 [ 'setDefault', 'recentchanges', 'rc_title', '' ],
588 [ 'setDefault', 'recentchanges', 'rc_source', '' ],
589 [ 'setDefault', 'recentchanges', 'rc_ip', '' ],
590 [ 'setDefault', 'recentchanges', 'rc_namespace', 0 ],
591 [ 'setDefault', 'recentchanges', 'rc_cur_id', 0 ],
592 [ 'setDefault', 'recentchanges', 'rc_this_oldid', 0 ],
593 [ 'setDefault', 'recentchanges', 'rc_last_oldid', 0 ],
594 [ 'changeNullableField', 'recentchanges', 'rc_cur_id', 'NOT NULL', true ],
595 [ 'changeNullableField', 'recentchanges', 'rc_ip', 'NOT NULL', true ],
596 [ 'renameIndex', 'recentchanges', 'new_name_timestamp', 'rc_new_name_timestamp', false,
597 'patch-recentchanges-rc_new_name_timestamp.sql' ],
598 [ 'changeField', 'archive', 'ar_namespace', 'INTEGER', '' ],
599 [ 'setDefault', 'archive', 'ar_namespace', 0 ],
600 [ 'setDefault', 'archive', 'ar_title', '' ],
601 [ 'changeField', 'archive', 'ar_comment_id', 'BIGINT', '' ],
602 [ 'changeField', 'archive', 'ar_actor', 'BIGINT', '' ],
603 [ 'renameIndex', 'user', 'user_email_token_idx', 'user_email_token' ],
604 [ 'addPgIndex', 'user', 'user_email', '(user_email)' ],
605 [ 'addPgIndex', 'user', 'user_name', '(user_name)', true ],
606 [ 'changeField', 'page', 'page_namespace', 'INTEGER', '' ],
607 [ 'changeNullableField', 'page', 'page_touched', 'NOT NULL', true ],
608 [ 'changeField', 'page', 'page_random', 'FLOAT', '' ],
609 [ 'renameIndex', 'revision', 'revision_unique', 'rev_page_id' ],
610 [ 'renameIndex', 'revision', 'rev_timestamp_idx', 'rev_timestamp' ],
611 [ 'addPgIndex', 'revision', 'rev_page_timestamp', '(rev_page,rev_timestamp)' ],
612 [ 'changeNullableField', 'user', 'user_touched', 'NOT NULL', true ],
613
614 // 1.37
615 [ 'changeNullableField', 'user', 'user_token', 'NOT NULL', true ],
616 [ 'changeNullableField', 'user', 'user_real_name', 'NOT NULL', true ],
617 [ 'changeNullableField', 'user', 'user_email', 'NOT NULL', true ],
618 [ 'changeNullableField', 'user', 'user_newpassword', 'NOT NULL', true ],
619 [ 'changeNullableField', 'user', 'user_password', 'NOT NULL', true ],
620 [ 'setDefault', 'user', 'user_name', '' ],
621 [ 'setDefault', 'user', 'user_token', '' ],
622 [ 'setDefault', 'user', 'user_real_name', '' ],
623 [ 'dropConstraint', 'user', 'user_name', 'unique' ],
624 [ 'addField', 'objectcache', 'modtoken', 'patch-objectcache-modtoken.sql' ],
625 [ 'dropFkey', 'revision', 'rev_page' ],
626 [ 'changeNullableField', 'revision', 'rev_page', 'NOT NULL', true ],
627 [ 'changeField', 'revision', 'rev_comment_id', 'BIGINT', 'rev_comment_id::BIGINT DEFAULT 0' ],
628 [ 'changeField', 'revision', 'rev_actor', 'BIGINT', 'rev_actor::BIGINT DEFAULT 0' ],
629 [ 'checkIndex', 'rev_page_id', [
630 [ 'rev_page', 'int4_ops', 'btree', 1 ],
631 [ 'rev_id', 'int4_ops', 'btree', 1 ],
632 ],
633 'CREATE INDEX rev_page_id ON revision (rev_page,rev_id)' ],
634 [ 'addTable', 'searchindex', 'patch-searchindex-table.sql' ],
635 [ 'addPgIndex', 'oldimage', 'oi_timestamp', '(oi_timestamp)' ],
636 [ 'renameIndex', 'page', 'name_title', 'page_name_title' ],
637 [ 'renameIndex', 'change_tag', 'change_tag_rc_tag_id', 'ct_rc_tag_id' ],
638 [ 'renameIndex', 'change_tag', 'change_tag_log_tag_id', 'ct_log_tag_id' ],
639 [ 'renameIndex', 'change_tag', 'change_tag_rev_tag_id', 'ct_rev_tag_id' ],
640 [ 'renameIndex', 'change_tag', 'change_tag_tag_id_id', 'ct_tag_id_id' ],
641 ];
642 }
643
644 protected function describeTable( $table ) {
645 $q = <<<END
646SELECT attname, attnum FROM pg_namespace, pg_class, pg_attribute
647 WHERE pg_class.relnamespace = pg_namespace.oid
648 AND attrelid=pg_class.oid AND attnum > 0
649 AND relname=%s AND nspname=%s
650END;
651 $res = $this->db->query(
652 sprintf( $q,
653 $this->db->addQuotes( $table ),
654 $this->db->addQuotes( $this->db->getCoreSchema() )
655 ),
656 __METHOD__
657 );
658 if ( !$res ) {
659 return null;
660 }
661
662 $cols = [];
663 foreach ( $res as $r ) {
664 $cols[] = [
665 "name" => $r[0],
666 "ord" => $r[1],
667 ];
668 }
669
670 return $cols;
671 }
672
673 protected function describeIndex( $idx ) {
674 // first fetch the key (which is a list of columns ords) and
675 // the table the index applies to (an oid)
676 $q = <<<END
677SELECT indkey, indrelid FROM pg_namespace, pg_class, pg_index
678 WHERE nspname=%s
679 AND pg_class.relnamespace = pg_namespace.oid
680 AND relname=%s
681 AND indexrelid=pg_class.oid
682END;
683 $res = $this->db->query(
684 sprintf(
685 $q,
686 $this->db->addQuotes( $this->db->getCoreSchema() ),
687 $this->db->addQuotes( $idx )
688 ),
689 __METHOD__
690 );
691 if ( !$res ) {
692 return null;
693 }
694 $r = $this->db->fetchRow( $res );
695 if ( !$r ) {
696 return null;
697 }
698
699 $indkey = $r[0];
700 $relid = intval( $r[1] );
701 $indkeys = explode( ' ', $indkey );
702
703 $colnames = [];
704 foreach ( $indkeys as $rid ) {
705 $query = <<<END
706SELECT attname FROM pg_class, pg_attribute
707 WHERE attrelid=$relid
708 AND attnum=%d
709 AND attrelid=pg_class.oid
710END;
711 $r2 = $this->db->query( sprintf( $query, $rid ), __METHOD__ );
712 if ( !$r2 ) {
713 return null;
714 }
715 $row2 = $this->db->fetchRow( $r2 );
716 if ( !$row2 ) {
717 return null;
718 }
719 $colnames[] = $row2[0];
720 }
721
722 return $colnames;
723 }
724
725 protected function fkeyDeltype( $fkey ) {
726 $q = <<<END
727SELECT confdeltype FROM pg_constraint, pg_namespace
728 WHERE connamespace=pg_namespace.oid
729 AND nspname=%s
730 AND conname=%s;
731END;
732 $r = $this->db->query(
733 sprintf(
734 $q,
735 $this->db->addQuotes( $this->db->getCoreSchema() ),
736 $this->db->addQuotes( $fkey )
737 ),
738 __METHOD__
739 );
740 $row = $this->db->fetchRow( $r );
741 if ( !$row ) {
742 return null;
743 }
744
745 return $row[0];
746 }
747
748 protected function ruleDef( $table, $rule ) {
749 $q = <<<END
750SELECT definition FROM pg_rules
751 WHERE schemaname = %s
752 AND tablename = %s
753 AND rulename = %s
754END;
755 $r = $this->db->query(
756 sprintf(
757 $q,
758 $this->db->addQuotes( $this->db->getCoreSchema() ),
759 $this->db->addQuotes( $table ),
760 $this->db->addQuotes( $rule )
761 ),
762 __METHOD__
763 );
764 $row = $this->db->fetchRow( $r );
765 if ( !$row ) {
766 return null;
767 }
768 $d = $row[0];
769
770 return $d;
771 }
772
773 protected function addSequence( $table, $pkey, $ns ) {
774 if ( !$this->db->sequenceExists( $ns ) ) {
775 $this->output( "Creating sequence $ns\n" );
776 if ( $pkey !== false ) {
777 $table = $this->db->addIdentifierQuotes( $table );
778 $this->db->query( "CREATE SEQUENCE $ns OWNED BY $table.$pkey", __METHOD__ );
779 $this->setDefault( $table, $pkey, '"nextval"(\'"' . $ns . '"\'::"regclass")' );
780 } else {
781 $this->db->query( "CREATE SEQUENCE $ns", __METHOD__ );
782 }
783 }
784 }
785
786 protected function dropSequence( $table, $ns ) {
787 if ( $this->db->sequenceExists( $ns ) ) {
788 $this->output( "Dropping sequence $ns\n" );
789 $this->db->query( "DROP SEQUENCE $ns CASCADE", __METHOD__ );
790 }
791 }
792
793 protected function renameSequence( $old, $new ) {
794 if ( $this->db->sequenceExists( $new ) ) {
795 $this->output( "...sequence $new already exists.\n" );
796
797 return;
798 }
799 if ( $this->db->sequenceExists( $old ) ) {
800 $this->output( "Renaming sequence $old to $new\n" );
801 $this->db->query( "ALTER SEQUENCE $old RENAME TO $new", __METHOD__ );
802 }
803 }
804
805 protected function setSequenceOwner( $table, $pkey, $seq ) {
806 if ( $this->db->sequenceExists( $seq ) ) {
807 $this->output( "Setting sequence $seq owner to $table.$pkey\n" );
808 $table = $this->db->addIdentifierQuotes( $table );
809 $this->db->query( "ALTER SEQUENCE $seq OWNED BY $table.$pkey", __METHOD__ );
810 }
811 }
812
813 protected function renameTable( $old, $new, $patch = false ) {
814 if ( $this->db->tableExists( $old, __METHOD__ ) ) {
815 $this->output( "Renaming table $old to $new\n" );
816 $old = $this->db->addIdentifierQuotes( $old );
817 $new = $this->db->addIdentifierQuotes( $new );
818 $this->db->query( "ALTER TABLE $old RENAME TO $new", __METHOD__ );
819 if ( $patch !== false ) {
820 $this->applyPatch( $patch );
821 }
822 }
823 }
824
825 protected function renameIndex(
826 $table, $old, $new, $skipBothIndexExistWarning = false, $a = false, $b = false
827 ) {
828 // First requirement: the table must exist
829 if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
830 $this->output( "...skipping: '$table' table doesn't exist yet.\n" );
831
832 return true;
833 }
834
835 // Second requirement: the new index must be missing
836 if ( $this->db->indexExists( $table, $new, __METHOD__ ) ) {
837 $this->output( "...index $new already set on $table table.\n" );
838 if ( !$skipBothIndexExistWarning
839 && $this->db->indexExists( $table, $old, __METHOD__ )
840 ) {
841 $this->output( "...WARNING: $old still exists, despite it has been " .
842 "renamed into $new (which also exists).\n" .
843 " $old should be manually removed if not needed anymore.\n" );
844 }
845
846 return true;
847 }
848
849 // Third requirement: the old index must exist
850 if ( !$this->db->indexExists( $table, $old, __METHOD__ ) ) {
851 $this->output( "...skipping: index $old doesn't exist.\n" );
852
853 return true;
854 }
855
856 $this->db->query( "ALTER INDEX $old RENAME TO $new", __METHOD__ );
857 return true;
858 }
859
860 protected function dropPgField( $table, $field ) {
861 $fi = $this->db->fieldInfo( $table, $field );
862 if ( $fi === null ) {
863 $this->output( "...$table table does not contain $field field.\n" );
864 } else {
865 $this->output( "Dropping column '$table.$field'\n" );
866 $table = $this->db->addIdentifierQuotes( $table );
867 $this->db->query( "ALTER TABLE $table DROP COLUMN $field", __METHOD__ );
868 }
869 }
870
871 protected function addPgField( $table, $field, $type ) {
872 $fi = $this->db->fieldInfo( $table, $field );
873 if ( $fi !== null ) {
874 $this->output( "...column '$table.$field' already exists\n" );
875 } else {
876 $this->output( "Adding column '$table.$field'\n" );
877 $table = $this->db->addIdentifierQuotes( $table );
878 $this->db->query( "ALTER TABLE $table ADD $field $type", __METHOD__ );
879 }
880 }
881
882 protected function changeField( $table, $field, $newtype, $default ) {
883 $fi = $this->db->fieldInfo( $table, $field );
884 if ( $fi === null ) {
885 $this->output( "...ERROR: expected column $table.$field to exist\n" );
886 exit( 1 );
887 }
888
889 if ( $fi->type() === strtolower( $newtype ) ) {
890 $this->output( "...column '$table.$field' is already of type '$newtype'\n" );
891 } else {
892 $this->output( "Changing column type of '$table.$field' from '{$fi->type()}' to '$newtype'\n" );
893 $table = $this->db->addIdentifierQuotes( $table );
894 $sql = "ALTER TABLE $table ALTER $field TYPE $newtype";
895 if ( strlen( $default ) ) {
896 $res = [];
897 if ( preg_match( '/DEFAULT (.+)/', $default, $res ) ) {
898 $sqldef = "ALTER TABLE $table ALTER $field SET DEFAULT $res[1]";
899 $this->db->query( $sqldef, __METHOD__ );
900 $default = preg_replace( '/\s*DEFAULT .+/', '', $default );
901 }
902 $sql .= " USING $default";
903 }
904 $this->db->query( $sql, __METHOD__ );
905 }
906 }
907
908 protected function changeFieldPurgeTable( $table, $field, $newtype, $default ) {
909 # # For a cache table, empty it if the field needs to be changed, because the old contents
910 # # may be corrupted. If the column is already the desired type, refrain from purging.
911 $fi = $this->db->fieldInfo( $table, $field );
912 if ( $fi === null ) {
913 $this->output( "...ERROR: expected column $table.$field to exist\n" );
914 exit( 1 );
915 }
916
917 if ( $fi->type() === $newtype ) {
918 $this->output( "...column '$table.$field' is already of type '$newtype'\n" );
919 } else {
920 $this->output( "Purging data from cache table '$table'\n" );
921 $table = $this->db->addIdentifierQuotes( $table );
922 $this->db->query( "DELETE from $table", __METHOD__ );
923 $this->output( "Changing column type of '$table.$field' from '{$fi->type()}' to '$newtype'\n" );
924 $sql = "ALTER TABLE $table ALTER $field TYPE $newtype";
925 if ( strlen( $default ) ) {
926 $res = [];
927 if ( preg_match( '/DEFAULT (.+)/', $default, $res ) ) {
928 $sqldef = "ALTER TABLE $table ALTER $field SET DEFAULT $res[1]";
929 $this->db->query( $sqldef, __METHOD__ );
930 $default = preg_replace( '/\s*DEFAULT .+/', '', $default );
931 }
932 $sql .= " USING $default";
933 }
934 $this->db->query( $sql, __METHOD__ );
935 }
936 }
937
938 protected function setDefault( $table, $field, $default ) {
939 $info = $this->db->fieldInfo( $table, $field );
940 if ( $info && $info->defaultValue() !== $default ) {
941 $this->output( "Changing '$table.$field' default value\n" );
942 $table = $this->db->addIdentifierQuotes( $table );
943 $this->db->query( "ALTER TABLE $table ALTER $field SET DEFAULT "
944 . $this->db->addQuotes( $default ), __METHOD__ );
945 }
946 }
947
954 protected function dropDefault( $table, $field ) {
955 $info = $this->db->fieldInfo( $table, $field );
956 if ( $info->defaultValue() !== false ) {
957 $this->output( "Removing '$table.$field' default value\n" );
958 $table = $this->db->addIdentifierQuotes( $table );
959 $this->db->query( "ALTER TABLE $table ALTER $field DROP DEFAULT", __METHOD__ );
960 }
961 }
962
963 protected function changeNullableField( $table, $field, $null, $update = false ) {
964 $fi = $this->db->fieldInfo( $table, $field );
965 if ( $fi === null ) {
966 return;
967 }
968 if ( $fi->isNullable() ) {
969 # # It's NULL - does it need to be NOT NULL?
970 if ( $null === 'NOT NULL' ) {
971 $this->output( "Changing '$table.$field' to not allow NULLs\n" );
972 $table = $this->db->addIdentifierQuotes( $table );
973 if ( $update ) {
974 $this->db->query( "UPDATE $table SET $field = DEFAULT WHERE $field IS NULL", __METHOD__ );
975 }
976 $this->db->query( "ALTER TABLE $table ALTER $field SET NOT NULL", __METHOD__ );
977 } else {
978 $this->output( "...column '$table.$field' is already set as NULL\n" );
979 }
980 } else {
981 # # It's NOT NULL - does it need to be NULL?
982 if ( $null === 'NULL' ) {
983 $this->output( "Changing '$table.$field' to allow NULLs\n" );
984 $table = $this->db->addIdentifierQuotes( $table );
985 $this->db->query( "ALTER TABLE $table ALTER $field DROP NOT NULL", __METHOD__ );
986 } else {
987 $this->output( "...column '$table.$field' is already set as NOT NULL\n" );
988 }
989 }
990 }
991
992 protected function addPgIndex( $table, $index, $type, $unique = false ) {
993 if ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
994 $this->output( "...index '$index' on table '$table' already exists\n" );
995 } else {
996 $this->output( "Creating index '$index' on table '$table' $type\n" );
997 $table = $this->db->addIdentifierQuotes( $table );
998 $unique = $unique ? 'UNIQUE' : '';
999 $this->db->query( "CREATE $unique INDEX $index ON $table $type", __METHOD__ );
1000 }
1001 }
1002
1003 protected function addPgExtIndex( $table, $index, $type ) {
1004 if ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
1005 $this->output( "...index '$index' on table '$table' already exists\n" );
1006 } elseif ( preg_match( '/^\‍(/', $type ) ) {
1007 $this->output( "Creating index '$index' on table '$table'\n" );
1008 $table = $this->db->addIdentifierQuotes( $table );
1009 $this->db->query( "CREATE INDEX $index ON $table $type", __METHOD__ );
1010 } else {
1011 $this->applyPatch( $type, true, "Creating index '$index' on table '$table'" );
1012 }
1013 }
1014
1021 protected function addPgEnumValue( $type, $value ) {
1022 $row = $this->db->selectRow(
1023 [
1024 't' => 'pg_catalog.pg_type',
1025 'n' => 'pg_catalog.pg_namespace',
1026 'e' => 'pg_catalog.pg_enum',
1027 ],
1028 [ 't.typname', 't.typtype', 'e.enumlabel' ],
1029 [
1030 't.typname' => $type,
1031 'n.nspname' => $this->db->getCoreSchema(),
1032 ],
1033 __METHOD__,
1034 [],
1035 [
1036 'n' => [ 'JOIN', 't.typnamespace = n.oid' ],
1037 'e' => [ 'LEFT JOIN', [ 'e.enumtypid = t.oid', 'e.enumlabel' => $value ] ],
1038 ]
1039 );
1040
1041 if ( !$row ) {
1042 $this->output( "...Type $type does not exist, skipping modify enum.\n" );
1043 } elseif ( $row->typtype !== 'e' ) {
1044 $this->output( "...Type $type does not seem to be an enum, skipping modify enum.\n" );
1045 } elseif ( $row->enumlabel === $value ) {
1046 $this->output( "...Enum type $type already contains value '$value'.\n" );
1047 } else {
1048 $this->output( "...Adding value '$value' to enum type $type.\n" );
1049 $etype = $this->db->addIdentifierQuotes( $type );
1050 $evalue = $this->db->addQuotes( $value );
1051 $this->db->query( "ALTER TYPE $etype ADD VALUE $evalue", __METHOD__ );
1052 }
1053 }
1054
1055 protected function dropFkey( $table, $field ) {
1056 $fi = $this->db->fieldInfo( $table, $field );
1057 if ( $fi === null ) {
1058 $this->output( "WARNING! Column '$table.$field' does not exist but it should! " .
1059 "Please report this.\n" );
1060 return;
1061 }
1062
1063 if ( $this->dropConstraint( $table, $field, 'foreignkey', $fi->conname() ) ) {
1064 $this->output( "Dropping foreign key constraint on '$table.$field'\n" );
1065 } else {
1066 $this->output( "...foreign key constraint on '$table.$field' already does not exist\n" );
1067 }
1068 }
1069
1070 protected function changeFkeyDeferrable( $table, $field, $clause ) {
1071 $fi = $this->db->fieldInfo( $table, $field );
1072 if ( $fi === null ) {
1073 $this->output( "WARNING! Column '$table.$field' does not exist but it should! " .
1074 "Please report this.\n" );
1075
1076 return;
1077 }
1078 if ( $fi->is_deferred() && $fi->is_deferrable() ) {
1079 return;
1080 }
1081 $this->output( "Altering column '$table.$field' to be DEFERRABLE INITIALLY DEFERRED\n" );
1082
1083 $conname = $fi->conname();
1084 $conclause = "CONSTRAINT \"$conname\"";
1085
1086 if ( !$this->dropConstraint( $table, $field, 'foreignkey', $conname ) ) {
1087 $this->output( "Column '$table.$field' does not have a foreign key " .
1088 "constraint, will be added\n" );
1089 $conclause = "";
1090 }
1091
1092 $command =
1093 "ALTER TABLE $table ADD $conclause " .
1094 "FOREIGN KEY ($field) REFERENCES $clause DEFERRABLE INITIALLY DEFERRED";
1095 $this->db->query( $command, __METHOD__ );
1096 }
1097
1098 protected function dropPgIndex( $table, $index ) {
1099 if ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
1100 $this->output( "Dropping obsolete index '$index'\n" );
1101 $this->db->query( "DROP INDEX \"" . $index . "\"", __METHOD__ );
1102 }
1103 }
1104
1105 protected function checkIndex( $index, $should_be, $good_def ) {
1106 $pu = $this->db->indexAttributes( $index );
1107 if ( !empty( $pu ) && $pu != $should_be ) {
1108 $this->output( "Dropping obsolete version of index '$index'\n" );
1109 $this->db->query( "DROP INDEX \"" . $index . "\"", __METHOD__ );
1110 $pu = [];
1111 } else {
1112 $this->output( "...no need to drop index '$index'\n" );
1113 }
1114
1115 if ( empty( $pu ) ) {
1116 $this->output( "Creating index '$index'\n" );
1117 $this->db->query( $good_def, __METHOD__ );
1118 } else {
1119 $this->output( "...index '$index' exists\n" );
1120 }
1121 }
1122
1123 protected function changePrimaryKey( $table, $shouldBe, $constraintName = null ) {
1124 // https://wiki.postgresql.org/wiki/Retrieve_primary_key_columns
1125 $result = $this->db->query(
1126 "SELECT a.attname as column " .
1127 "FROM pg_index i " .
1128 "JOIN pg_attribute a ON a.attrelid = i.indrelid " .
1129 "AND a.attnum = ANY(i.indkey) " .
1130 "WHERE i.indrelid = '\"$table\"'::regclass " .
1131 "AND i.indisprimary",
1132 __METHOD__
1133 );
1134 $currentColumns = [];
1135 foreach ( $result as $row ) {
1136 $currentColumns[] = $row->column;
1137 }
1138
1139 if ( $currentColumns == $shouldBe ) {
1140 $this->output( "...no need to change primary key of '$table'\n" );
1141 return true;
1142 }
1143
1144 $this->dropConstraint( $table, '', 'primary', $constraintName );
1145
1146 $table = $this->db->addIdentifierQuotes( $table );
1147 $this->db->query(
1148 "ALTER TABLE $table" .
1149 " ADD PRIMARY KEY (" . implode( ',', $shouldBe ) . ');',
1150 __METHOD__
1151 );
1152 }
1153
1165 protected function dropConstraint( $table, $field, $type, $conname = null ) {
1166 if ( $conname === null ) {
1167 if ( $type == 'primary' ) {
1168 $conname = "{$table}_pkey";
1169 } else {
1170 $map = [ 'unique' => 'key', 'check' => 'check', 'foreignkey' => 'fkey' ];
1171 $conname = "{$table}_{$field}_{$map[$type]}";
1172 }
1173 }
1174
1175 if ( $this->db->constraintExists( $table, $conname ) ) {
1176 $table = $this->db->addIdentifierQuotes( $table );
1177 $this->db->query(
1178 "ALTER TABLE $table DROP CONSTRAINT $conname;",
1179 __METHOD__
1180 );
1181
1182 return true;
1183 }
1184
1185 return false;
1186 }
1187}
Class for handling database updates.
output( $str)
Output some text.
applyPatch( $path, $isFullPath=false, $msg=null)
Applies a SQL patch.
Class for handling updates to Postgres databases.
changeNullableField( $table, $field, $null, $update=false)
changePrimaryKey( $table, $shouldBe, $constraintName=null)
changeField( $table, $field, $newtype, $default)
renameTable( $old, $new, $patch=false)
renameIndex( $table, $old, $new, $skipBothIndexExistWarning=false, $a=false, $b=false)
Rename an index from an existing table.
dropDefault( $table, $field)
Drop a default value from a field.
ruleDef( $table, $rule)
dropSequence( $table, $ns)
addPgExtIndex( $table, $index, $type)
addSequence( $table, $pkey, $ns)
addPgEnumValue( $type, $value)
Add a value to an existing PostgreSQL enum type.
dropPgField( $table, $field)
renameSequence( $old, $new)
dropPgIndex( $table, $index)
setDefault( $table, $field, $default)
DatabasePostgres $db
addPgField( $table, $field, $type)
setSequenceOwner( $table, $pkey, $seq)
dropFkey( $table, $field)
dropConstraint( $table, $field, $type, $conname=null)
Drop generic constraint.
changeFkeyDeferrable( $table, $field, $clause)
checkIndex( $index, $should_be, $good_def)
changeFieldPurgeTable( $table, $field, $newtype, $default)
addPgIndex( $table, $index, $type, $unique=false)
$command
Definition mcc.php:125
return true
Definition router.php:92