aboutsummaryrefslogtreecommitdiffstats
path: root/sql/abstractSchemaChanges
diff options
context:
space:
mode:
Diffstat (limited to 'sql/abstractSchemaChanges')
-rw-r--r--sql/abstractSchemaChanges/patch-change_tag-ct_rc_id.json108
-rw-r--r--sql/abstractSchemaChanges/patch-change_tag-rename-indexes.json109
-rw-r--r--sql/abstractSchemaChanges/patch-drop-cl_collation_ext.json143
-rw-r--r--sql/abstractSchemaChanges/patch-drop-ct_tag.json124
-rw-r--r--sql/abstractSchemaChanges/patch-drop-page_restrictions-pr_user.json115
-rw-r--r--sql/abstractSchemaChanges/patch-drop-rev_page_id.json195
-rw-r--r--sql/abstractSchemaChanges/patch-extend-iwlinks-iwl_prefix.json81
-rw-r--r--sql/abstractSchemaChanges/patch-externallinks-drop-el_to.json93
-rw-r--r--sql/abstractSchemaChanges/patch-externallinks-el_to_default.json115
-rw-r--r--sql/abstractSchemaChanges/patch-externallinks-el_to_path.json102
-rw-r--r--sql/abstractSchemaChanges/patch-filearchive-fa_id.json488
-rw-r--r--sql/abstractSchemaChanges/patch-filearchive-fa_size_to_bigint.json487
-rw-r--r--sql/abstractSchemaChanges/patch-image-img_size_to_bigint.json368
-rw-r--r--sql/abstractSchemaChanges/patch-ipblocks-ipb_id.json477
-rw-r--r--sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_ipb_id.json69
-rw-r--r--sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_value.json69
-rw-r--r--sql/abstractSchemaChanges/patch-iwlinks-drop-iwl_prefix_from_title.json75
-rw-r--r--sql/abstractSchemaChanges/patch-logging-rename-indexes.json231
-rw-r--r--sql/abstractSchemaChanges/patch-objectcache-modtoken.json63
-rw-r--r--sql/abstractSchemaChanges/patch-oldimage-oi_size_to_bigint.json371
-rw-r--r--sql/abstractSchemaChanges/patch-oldimage-oi_timestamp.json363
-rw-r--r--sql/abstractSchemaChanges/patch-page-drop-page_restrictions.json243
-rw-r--r--sql/abstractSchemaChanges/patch-page-page_links_updated-noinfinite.json234
-rw-r--r--sql/abstractSchemaChanges/patch-page-rename-name_title-index.json249
-rw-r--r--sql/abstractSchemaChanges/patch-page_props-pp_page.json65
-rw-r--r--sql/abstractSchemaChanges/patch-page_restrictions-pr_page.json109
-rw-r--r--sql/abstractSchemaChanges/patch-pagelinks-drop-pl_title.json103
-rw-r--r--sql/abstractSchemaChanges/patch-pagelinks-target_id.json107
-rw-r--r--sql/abstractSchemaChanges/patch-recentchanges-rc_id-bigint.json618
-rw-r--r--sql/abstractSchemaChanges/patch-recentchanges-rc_id.json620
-rw-r--r--sql/abstractSchemaChanges/patch-recentchanges-rc_new_name_timestamp.json621
-rw-r--r--sql/abstractSchemaChanges/patch-revision-cleanup.json188
-rw-r--r--sql/abstractSchemaChanges/patch-revision-rename-index.json203
-rw-r--r--sql/abstractSchemaChanges/patch-searchindex-pk-titlelength.json131
-rw-r--r--sql/abstractSchemaChanges/patch-site_identifiers-rename-indexes.json61
-rw-r--r--sql/abstractSchemaChanges/patch-sites-drop_indexes.json162
-rw-r--r--sql/abstractSchemaChanges/patch-sites-rename-indexes.json169
-rw-r--r--sql/abstractSchemaChanges/patch-templatelinks-drop-tl_title.json103
-rw-r--r--sql/abstractSchemaChanges/patch-templatelinks-target_id.json107
-rw-r--r--sql/abstractSchemaChanges/patch-templatelinks-tl_title-nullable.json125
-rw-r--r--sql/abstractSchemaChanges/patch-uploadstash-us_size_to_bigint.json375
-rw-r--r--sql/abstractSchemaChanges/patch-user-user_editcount.json175
-rw-r--r--sql/abstractSchemaChanges/patch-user-user_is_temp.json225
-rw-r--r--sql/abstractSchemaChanges/patch-user_autocreate_serial-uas_year.json49
-rw-r--r--sql/abstractSchemaChanges/patch-user_properties-rename-index.json59
-rw-r--r--sql/abstractSchemaChanges/patch-user_table-updates.json217
-rw-r--r--sql/abstractSchemaChanges/patch-watchlist-namespace_title-rename-index.json107
47 files changed, 9671 insertions, 0 deletions
diff --git a/sql/abstractSchemaChanges/patch-change_tag-ct_rc_id.json b/sql/abstractSchemaChanges/patch-change_tag-ct_rc_id.json
new file mode 100644
index 000000000000..7f03469e3fbd
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-change_tag-ct_rc_id.json
@@ -0,0 +1,108 @@
+{
+ "before": {
+ "name": "change_tag",
+ "comment": "A table to track tags for revisions, logs and recent changes",
+ "columns": [
+ {
+ "name": "ct_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "ct_rc_id",
+ "comment": "RCID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_log_id",
+ "comment": "LOGID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_rev_id",
+ "comment": "REVID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_params",
+ "comment": "Parameters for the tag; used by some extensions",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag_id",
+ "comment": "Foreign key to change_tag_def row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "ct_rc_tag_id", "columns": [ "ct_rc_id", "ct_tag_id" ], "unique": true },
+ { "name": "ct_log_tag_id", "columns": [ "ct_log_id", "ct_tag_id" ], "unique": true },
+ { "name": "ct_rev_tag_id", "columns": [ "ct_rev_id", "ct_tag_id" ], "unique": true },
+ {
+ "name": "ct_tag_id_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag_id", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ct_id" ]
+ },
+ "after": {
+ "name": "change_tag",
+ "comment": "A table to track tags for revisions, logs and recent changes",
+ "columns": [
+ {
+ "name": "ct_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "ct_rc_id",
+ "comment": "RCID for the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_log_id",
+ "comment": "LOGID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_rev_id",
+ "comment": "REVID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_params",
+ "comment": "Parameters for the tag; used by some extensions",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag_id",
+ "comment": "Foreign key to change_tag_def row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "ct_rc_tag_id", "columns": [ "ct_rc_id", "ct_tag_id" ], "unique": true },
+ { "name": "ct_log_tag_id", "columns": [ "ct_log_id", "ct_tag_id" ], "unique": true },
+ { "name": "ct_rev_tag_id", "columns": [ "ct_rev_id", "ct_tag_id" ], "unique": true },
+ {
+ "name": "ct_tag_id_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag_id", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ct_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-change_tag-rename-indexes.json b/sql/abstractSchemaChanges/patch-change_tag-rename-indexes.json
new file mode 100644
index 000000000000..2d4e51f98fb8
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-change_tag-rename-indexes.json
@@ -0,0 +1,109 @@
+{
+ "comment": "Rename all indexes to have uniform ct_ prefix (T270033)",
+ "before": {
+ "name": "change_tag",
+ "comment": "A table to track tags for revisions, logs and recent changes",
+ "columns": [
+ {
+ "name": "ct_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "ct_rc_id",
+ "comment": "RCID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_log_id",
+ "comment": "LOGID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_rev_id",
+ "comment": "REVID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_params",
+ "comment": "Parameters for the tag; used by some extensions",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag_id",
+ "comment": "Foreign key to change_tag_def row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "change_tag_rc_tag_id", "columns": [ "ct_rc_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_log_tag_id", "columns": [ "ct_log_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_rev_tag_id", "columns": [ "ct_rev_id", "ct_tag_id" ], "unique": true },
+ {
+ "name": "change_tag_tag_id_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag_id", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ct_id" ]
+ },
+ "after": {
+ "name": "change_tag",
+ "comment": "A table to track tags for revisions, logs and recent changes",
+ "columns": [
+ {
+ "name": "ct_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "ct_rc_id",
+ "comment": "RCID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_log_id",
+ "comment": "LOGID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_rev_id",
+ "comment": "REVID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_params",
+ "comment": "Parameters for the tag; used by some extensions",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag_id",
+ "comment": "Foreign key to change_tag_def row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "ct_rc_tag_id", "columns": [ "ct_rc_id", "ct_tag_id" ], "unique": true },
+ { "name": "ct_log_tag_id", "columns": [ "ct_log_id", "ct_tag_id" ], "unique": true },
+ { "name": "ct_rev_tag_id", "columns": [ "ct_rev_id", "ct_tag_id" ], "unique": true },
+ {
+ "name": "ct_tag_id_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag_id", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ct_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-drop-cl_collation_ext.json b/sql/abstractSchemaChanges/patch-drop-cl_collation_ext.json
new file mode 100644
index 000000000000..7c43262f89ed
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-drop-cl_collation_ext.json
@@ -0,0 +1,143 @@
+{
+ "comment": "Drop cl_collation_ext index from categorylinks (T342854)",
+ "before": {
+ "name": "categorylinks",
+ "comment": "Track category inclusions *used inline* This tracks a single level of category membership",
+ "columns": [
+ {
+ "name": "cl_from",
+ "comment": "Key to page_id of the page defined as a category member.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "cl_to",
+ "comment": "Name of the category. This is also the page_title of the category's description page; all such pages are in namespace 14 (NS_CATEGORY).",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "cl_sortkey",
+ "comment": "A binary string obtained by applying a sortkey generation algorithm (Collation::getSortKey()) to page_title, or cl_sortkey_prefix . \"\\n\" page_title if cl_sortkey_prefix is nonempty.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 230 }
+ },
+ {
+ "name": "cl_sortkey_prefix",
+ "comment": "A prefix for the raw sortkey manually specified by the user, either via [[Category:Foo|prefix]] or {{defaultsort:prefix}}. If nonempty, it's concatenated with a line break followed by the page title before the sortkey conversion algorithm is run. We store this so that we can update collations without reparsing all pages. Note: If you change the length of this field, you also need to change code in LinksUpdate.php. See T27254.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "cl_timestamp",
+ "comment": "This isn't really used at present. Provided for an optional sorting method by approximate addition time.",
+ "type": "datetimetz",
+ "options": { "notnull": true, "PlatformOptions": { "version": true } }
+ },
+ {
+ "name": "cl_collation",
+ "comment": "Stores $wgCategoryCollation at the time cl_sortkey was generated. This can be used to install new collation versions, tracking which rows are not yet updated. '' means no collation, this is a legacy row that needs to be updated by updateCollation.php. In the future, it might be possible to specify different collations per category.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32 }
+ },
+ {
+ "name": "cl_type",
+ "comment": "Stores whether cl_from is a category, file, or other page, so we can paginate the three categories separately. This only has to be updated when moving pages into or out of the category namespace, since file pages cannot be moved to other namespaces, nor can non-files be moved into the file namespace.",
+ "type": "mwenum",
+ "options": { "notnull": true, "default": "page",
+ "CustomSchemaOptions": {
+ "enum_values": [ "page", "subcat", "file" ]
+ }
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "cl_sortkey",
+ "comment": "We always sort within a given category, and within a given type. FIXME: Formerly this index didn't cover cl_type (since that didn't exist), so old callers won't be using an index: fix this?",
+ "columns": [ "cl_to", "cl_type", "cl_sortkey", "cl_from" ],
+ "unique": false
+ },
+ {
+ "name": "cl_timestamp",
+ "comment": "Used by the API (and some extensions)",
+ "columns": [ "cl_to", "cl_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "cl_collation_ext",
+ "comment": "Used when updating collation (e.g. updateCollation.php)",
+ "columns": [ "cl_collation", "cl_to", "cl_type", "cl_from" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "cl_from", "cl_to" ]
+ },
+ "after": {
+ "name": "categorylinks",
+ "comment": "Track category inclusions *used inline* This tracks a single level of category membership",
+ "columns": [
+ {
+ "name": "cl_from",
+ "comment": "Key to page_id of the page defined as a category member.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "cl_to",
+ "comment": "Name of the category. This is also the page_title of the category's description page; all such pages are in namespace 14 (NS_CATEGORY).",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "cl_sortkey",
+ "comment": "A binary string obtained by applying a sortkey generation algorithm (Collation::getSortKey()) to page_title, or cl_sortkey_prefix . \"\\n\" page_title if cl_sortkey_prefix is nonempty.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 230 }
+ },
+ {
+ "name": "cl_sortkey_prefix",
+ "comment": "A prefix for the raw sortkey manually specified by the user, either via [[Category:Foo|prefix]] or {{defaultsort:prefix}}. If nonempty, it's concatenated with a line break followed by the page title before the sortkey conversion algorithm is run. We store this so that we can update collations without reparsing all pages. Note: If you change the length of this field, you also need to change code in LinksUpdate.php. See T27254.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "cl_timestamp",
+ "comment": "This isn't really used at present. Provided for an optional sorting method by approximate addition time.",
+ "type": "datetimetz",
+ "options": { "notnull": true, "PlatformOptions": { "version": true } }
+ },
+ {
+ "name": "cl_collation",
+ "comment": "Stores $wgCategoryCollation at the time cl_sortkey was generated. This can be used to install new collation versions, tracking which rows are not yet updated. '' means no collation, this is a legacy row that needs to be updated by updateCollation.php. In the future, it might be possible to specify different collations per category.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32 }
+ },
+ {
+ "name": "cl_type",
+ "comment": "Stores whether cl_from is a category, file, or other page, so we can paginate the three categories separately. This only has to be updated when moving pages into or out of the category namespace, since file pages cannot be moved to other namespaces, nor can non-files be moved into the file namespace.",
+ "type": "mwenum",
+ "options": { "notnull": true, "default": "page",
+ "CustomSchemaOptions": {
+ "enum_values": [ "page", "subcat", "file" ]
+ }
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "cl_sortkey",
+ "comment": "We always sort within a given category, and within a given type. FIXME: Formerly this index didn't cover cl_type (since that didn't exist), so old callers won't be using an index: fix this?",
+ "columns": [ "cl_to", "cl_type", "cl_sortkey", "cl_from" ],
+ "unique": false
+ },
+ {
+ "name": "cl_timestamp",
+ "comment": "Used by the API (and some extensions)",
+ "columns": [ "cl_to", "cl_timestamp" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "cl_from", "cl_to" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-drop-ct_tag.json b/sql/abstractSchemaChanges/patch-drop-ct_tag.json
new file mode 100644
index 000000000000..08c102f041e0
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-drop-ct_tag.json
@@ -0,0 +1,124 @@
+{
+ "comment": "Drop change_tag.ct_tag field (T185355)",
+ "before": {
+ "name": "change_tag",
+ "comment": "A table to track tags for revisions, logs and recent changes",
+ "columns": [
+ {
+ "name": "ct_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "ct_rc_id",
+ "comment": "RCID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_log_id",
+ "comment": "LOGID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_rev_id",
+ "comment": "REVID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag",
+ "comment": "Tag applied, this will go away and be replaced with ct_tag_id",
+ "type": "string",
+ "options": { "length": 255, "notnull": true, "default": "" }
+ },
+ {
+ "name": "ct_params",
+ "comment": "Parameters for the tag; used by some extensions",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag_id",
+ "comment": "Foreign key to change_tag_def row",
+ "type": "integer",
+ "options": { "unsigned": false, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "change_tag_rc_tag_id", "columns": [ "ct_rc_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_log_tag_id", "columns": [ "ct_log_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_rev_tag_id", "columns": [ "ct_rev_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_rc_tag_nonuniq", "columns": [ "ct_rc_id", "ct_tag" ], "unique": true },
+ { "name": "change_tag_log_tag_nonuniq", "columns": [ "ct_log_id", "ct_tag" ], "unique": true },
+ { "name": "change_tag_rev_tag_nonuniq", "columns": [ "ct_rev_id", "ct_tag" ], "unique": true },
+ {
+ "name": "change_tag_tag_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ },
+ {
+ "name": "change_tag_tag_id_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag_id", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ct_id" ]
+ },
+ "after": {
+ "name": "change_tag",
+ "comment": "A table to track tags for revisions, logs and recent changes",
+ "columns": [
+ {
+ "name": "ct_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "ct_rc_id",
+ "comment": "RCID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_log_id",
+ "comment": "LOGID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_rev_id",
+ "comment": "REVID for the change",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_params",
+ "comment": "Parameters for the tag; used by some extensions",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false, "default": null }
+ },
+ {
+ "name": "ct_tag_id",
+ "comment": "Foreign key to change_tag_def row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "change_tag_rc_tag_id", "columns": [ "ct_rc_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_log_tag_id", "columns": [ "ct_log_id", "ct_tag_id" ], "unique": true },
+ { "name": "change_tag_rev_tag_id", "columns": [ "ct_rev_id", "ct_tag_id" ], "unique": true },
+ {
+ "name": "change_tag_tag_id_id",
+ "comment": "Covering index, so we can pull all the info only out of the index.",
+ "columns": [ "ct_tag_id", "ct_rc_id", "ct_rev_id", "ct_log_id" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ct_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-drop-page_restrictions-pr_user.json b/sql/abstractSchemaChanges/patch-drop-page_restrictions-pr_user.json
new file mode 100644
index 000000000000..7f3a8dc0cf9a
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-drop-page_restrictions-pr_user.json
@@ -0,0 +1,115 @@
+{
+ "comment": "Drop page_restrictions.pr_user field (T199377)",
+ "before": {
+ "name": "page_restrictions",
+ "comment": "Used for storing page restrictions (i.e. protection levels)",
+ "columns": [
+ {
+ "name": "pr_id",
+ "comment": "Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "pr_page",
+ "comment": "Page to apply restrictions to (Foreign Key to page).",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_type",
+ "comment": "The protection type (edit, move, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_level",
+ "comment": "The protection level (Sysop, autoconfirmed, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_cascade",
+ "type": "mwtinyint",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_user",
+ "comment": "Field for future support of per-user restriction.",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true }
+ },
+ {
+ "name": "pr_expiry",
+ "comment": "Field for time-limited protection.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "pr_pagetype", "columns": [ "pr_page", "pr_type" ], "unique": true },
+ { "name": "pr_typelevel", "columns": [ "pr_type", "pr_level" ], "unique": false },
+ { "name": "pr_level", "columns": [ "pr_level" ], "unique": false },
+ { "name": "pr_cascade", "columns": [ "pr_cascade" ], "unique": false }
+ ],
+ "pk": [ "pr_id" ]
+ },
+ "after": {
+ "name": "page_restrictions",
+ "comment": "Used for storing page restrictions (i.e. protection levels)",
+ "columns": [
+ {
+ "name": "pr_id",
+ "comment": "Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "pr_page",
+ "comment": "Page to apply restrictions to (Foreign Key to page).",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_type",
+ "comment": "The protection type (edit, move, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_level",
+ "comment": "The protection level (Sysop, autoconfirmed, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_cascade",
+ "type": "mwtinyint",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_expiry",
+ "comment": "Field for time-limited protection.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "pr_pagetype", "columns": [ "pr_page", "pr_type" ], "unique": true },
+ { "name": "pr_typelevel", "columns": [ "pr_type", "pr_level" ], "unique": false },
+ { "name": "pr_level", "columns": [ "pr_level" ], "unique": false },
+ { "name": "pr_cascade", "columns": [ "pr_cascade" ], "unique": false }
+ ],
+ "pk": [ "pr_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-drop-rev_page_id.json b/sql/abstractSchemaChanges/patch-drop-rev_page_id.json
new file mode 100644
index 000000000000..0348193b9bc3
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-drop-rev_page_id.json
@@ -0,0 +1,195 @@
+{
+ "comment": "Drop rev_page_id index on revision (T163532)",
+ "before": {
+ "name": "revision",
+ "comment": "Every edit of a page creates also a revision row. This stores metadata about the revision, and a reference to the text storage backend.",
+ "columns": [
+ {
+ "name": "rev_id",
+ "comment": "Unique ID to identify each revision",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "rev_page",
+ "comment": "Key to page_id. This should never be invalid",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_comment_id",
+ "comment": "Key to comment.comment_id. Comment summarizing the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_actor",
+ "comment": "Key to actor.actor_id of the user or IP who made this edit",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_timestamp",
+ "comment": "Timestamp of when revision was created",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "rev_minor_edit",
+ "comment": "Records whether the user marked the 'minor edit' checkbox. Many automated edits are marked as minor",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_deleted",
+ "comment": "Restrictions on who can access this revision",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_len",
+ "comment": "Length of this revision in bytes",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_parent_id",
+ "comment": "Key to revision.rev_id. This field is used to add support for a tree structure (The Adjacency List Model)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_sha1",
+ "comment": "SHA-1 text content hash in base-36",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rev_page_id",
+ "columns": [ "rev_page", "rev_id" ],
+ "comment": "The index is proposed for removal, do not use it in new code: T163532. Used for ordering revisions within a page by rev_id, which is usually incorrect, since rev_timestamp is normally the correct order. It can also be used by dumpBackup.php, if a page and rev_id range is specified.",
+ "unique": false
+ },
+ {
+ "name": "rev_timestamp",
+ "columns": [ "rev_timestamp" ],
+ "comment": "Used by ApiQueryAllRevisions",
+ "unique": false
+ },
+ {
+ "name": "rev_page_timestamp",
+ "columns": [ "rev_page", "rev_timestamp" ],
+ "comment": "History index",
+ "unique": false
+ },
+ {
+ "name": "rev_actor_timestamp",
+ "columns": [ "rev_actor", "rev_timestamp", "rev_id" ],
+ "comment": "User contributions index",
+ "unique": false
+ },
+ {
+ "name": "rev_page_actor_timestamp",
+ "columns": [ "rev_page", "rev_actor", "rev_timestamp" ],
+ "comment": "Credits index. This is scanned in order to compile credits lists for pages, in ApiQueryContributors. Also for ApiQueryRevisions if rvuser is specified",
+ "unique": false
+ }
+ ],
+ "pk": [ "rev_id" ]
+ },
+ "after": {
+ "name": "revision",
+ "comment": "Every edit of a page creates also a revision row. This stores metadata about the revision, and a reference to the text storage backend.",
+ "columns": [
+ {
+ "name": "rev_id",
+ "comment": "Unique ID to identify each revision",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "rev_page",
+ "comment": "Key to page_id. This should never be invalid",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_comment_id",
+ "comment": "Key to comment.comment_id. Comment summarizing the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_actor",
+ "comment": "Key to actor.actor_id of the user or IP who made this edit",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_timestamp",
+ "comment": "Timestamp of when revision was created",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "rev_minor_edit",
+ "comment": "Records whether the user marked the 'minor edit' checkbox. Many automated edits are marked as minor",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_deleted",
+ "comment": "Restrictions on who can access this revision",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_len",
+ "comment": "Length of this revision in bytes",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_parent_id",
+ "comment": "Key to revision.rev_id. This field is used to add support for a tree structure (The Adjacency List Model)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_sha1",
+ "comment": "SHA-1 text content hash in base-36",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rev_timestamp",
+ "columns": [ "rev_timestamp" ],
+ "comment": "Used by ApiQueryAllRevisions",
+ "unique": false
+ },
+ {
+ "name": "rev_page_timestamp",
+ "columns": [ "rev_page", "rev_timestamp" ],
+ "comment": "History index",
+ "unique": false
+ },
+ {
+ "name": "rev_actor_timestamp",
+ "columns": [ "rev_actor", "rev_timestamp", "rev_id" ],
+ "comment": "User contributions index",
+ "unique": false
+ },
+ {
+ "name": "rev_page_actor_timestamp",
+ "columns": [ "rev_page", "rev_actor", "rev_timestamp" ],
+ "comment": "Credits index. This is scanned in order to compile credits lists for pages, in ApiQueryContributors. Also for ApiQueryRevisions if rvuser is specified",
+ "unique": false
+ }
+ ],
+ "pk": [ "rev_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-extend-iwlinks-iwl_prefix.json b/sql/abstractSchemaChanges/patch-extend-iwlinks-iwl_prefix.json
new file mode 100644
index 000000000000..96c08bbc1b29
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-extend-iwlinks-iwl_prefix.json
@@ -0,0 +1,81 @@
+{
+ "comment": "T275242 - increase size of iwl_prefix from VARBINARY(20) to VARBINARY(32)",
+ "before": {
+ "name": "iwlinks",
+ "comment": "Track inline interwiki links",
+ "columns": [
+ {
+ "name": "iwl_from",
+ "comment": "page_id of the referring page",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "iwl_prefix",
+ "type": "binary",
+ "comment": "Interwiki prefix code of the target",
+ "options": { "notnull": true, "length": 20, "default": "" }
+ },
+ {
+ "name": "iwl_title",
+ "type": "binary",
+ "comment": "Title of the target, including namespace",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "iwl_prefix_title_from",
+ "columns": [ "iwl_prefix", "iwl_title", "iwl_from" ],
+ "comment": "Index for ApiQueryIWBacklinks",
+ "unique": false
+ },
+ {
+ "name": "iwl_prefix_from_title",
+ "columns": [ "iwl_prefix", "iwl_from", "iwl_title" ],
+ "comment": "Index for ApiQueryIWLinks",
+ "unique": false
+ }
+ ],
+ "pk": [ "iwl_from", "iwl_prefix", "iwl_title" ]
+ },
+ "after": {
+ "name": "iwlinks",
+ "comment": "Track inline interwiki links",
+ "columns": [
+ {
+ "name": "iwl_from",
+ "comment": "page_id of the referring page",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "iwl_prefix",
+ "type": "binary",
+ "comment": "Interwiki prefix code of the target",
+ "options": { "notnull": true, "length": 32, "default": "" }
+ },
+ {
+ "name": "iwl_title",
+ "type": "binary",
+ "comment": "Title of the target, including namespace",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "iwl_prefix_title_from",
+ "columns": [ "iwl_prefix", "iwl_title", "iwl_from" ],
+ "comment": "Index for ApiQueryIWBacklinks",
+ "unique": false
+ },
+ {
+ "name": "iwl_prefix_from_title",
+ "columns": [ "iwl_prefix", "iwl_from", "iwl_title" ],
+ "comment": "Index for ApiQueryIWLinks",
+ "unique": false
+ }
+ ],
+ "pk": [ "iwl_from", "iwl_prefix", "iwl_title" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-externallinks-drop-el_to.json b/sql/abstractSchemaChanges/patch-externallinks-drop-el_to.json
new file mode 100644
index 000000000000..cfbc07e27e45
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-externallinks-drop-el_to.json
@@ -0,0 +1,93 @@
+{
+ "comment": "Drop old columns of externallinks (T312666)",
+ "before": {
+ "name": "externallinks",
+ "comment": "Track links to external URLs",
+ "columns": [
+ {
+ "name": "el_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "el_from",
+ "type": "integer",
+ "comment": "page_id of the referring page",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "el_to",
+ "type": "blob",
+ "comment": "The external link",
+ "options": { "length": 65530, "notnull": false, "default": "" }
+ },
+ {
+ "name": "el_index",
+ "type": "blob",
+ "comment": "In the case of HTTP URLs, this is the URL with any username or password removed, and with the labels in the hostname reversed and converted to lower case which will allow faster searching for all pages with WHERE clause. Note: If PHP's intl extension is enabled/disabled, maintenance/refreshExternallinksIndex.php needs to be run to refresh this field",
+ "options": { "length": 65530, "notnull": false, "default": "" }
+ },
+ {
+ "name": "el_index_60",
+ "type": "binary",
+ "comment": "'el_index' truncated to 60 bytes to allow for sortable queries that aren't supported by a partial index",
+ "options": { "notnull": true, "length": 60, "default": "" }
+ },
+ {
+ "name": "el_to_domain_index",
+ "type": "binary",
+ "comment": "Indexable domain",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "el_to_path",
+ "type": "blob",
+ "comment": "Path to the external link without considering the domain",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "el_from", "columns": [ "el_from" ], "unique": false },
+ { "name": "el_to", "columns": [ "el_to", "el_from" ], "unique": false, "options": { "lengths": [ 60, null ] } },
+ { "name": "el_index", "columns": [ "el_index" ], "unique": false, "options": { "lengths": [ 60 ] } },
+ { "name": "el_index_60", "columns": [ "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_from_index_60", "columns": [ "el_from", "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_to_domain_index_to_path", "columns": [ "el_to_domain_index", "el_to_path" ], "unique": false, "options": { "lengths": [ null, 60 ] } }
+ ],
+ "pk": [ "el_id" ]
+ },
+ "after": {
+ "name": "externallinks",
+ "comment": "Track links to external URLs",
+ "columns": [
+ {
+ "name": "el_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "el_from",
+ "type": "integer",
+ "comment": "page_id of the referring page",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "el_to_domain_index",
+ "type": "binary",
+ "comment": "Indexable domain",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "el_to_path",
+ "type": "blob",
+ "comment": "Path to the external link without considering the domain",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "el_from", "columns": [ "el_from" ], "unique": false },
+ { "name": "el_to_domain_index_to_path", "columns": [ "el_to_domain_index", "el_to_path" ], "unique": false, "options": { "lengths": [ null, 60 ] } }
+ ],
+ "pk": [ "el_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-externallinks-el_to_default.json b/sql/abstractSchemaChanges/patch-externallinks-el_to_default.json
new file mode 100644
index 000000000000..7f1164fb20dd
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-externallinks-el_to_default.json
@@ -0,0 +1,115 @@
+{
+ "comment": "Set default for old externallinks columns in preparation of dropping them (T312666).",
+ "before": {
+ "name": "externallinks",
+ "comment": "Track links to external URLs",
+ "columns": [
+ {
+ "name": "el_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "el_from",
+ "type": "integer",
+ "comment": "page_id of the referring page",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "el_to",
+ "type": "blob",
+ "comment": "The external link",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "el_index",
+ "type": "blob",
+ "comment": "In the case of HTTP URLs, this is the URL with any username or password removed, and with the labels in the hostname reversed and converted to lower case which will allow faster searching for all pages with WHERE clause. Note: If PHP's intl extension is enabled/disabled, maintenance/refreshExternallinksIndex.php needs to be run to refresh this field",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "el_index_60",
+ "type": "binary",
+ "comment": "'el_index' truncated to 60 bytes to allow for sortable queries that aren't supported by a partial index",
+ "options": { "notnull": true, "length": 60 }
+ },
+ {
+ "name": "el_to_domain_index",
+ "type": "binary",
+ "comment": "Indexable domain",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "el_to_path",
+ "type": "blob",
+ "comment": "Path to the external link without considering the domain",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "el_from", "columns": [ "el_from" ], "unique": false },
+ { "name": "el_to", "columns": [ "el_to", "el_from" ], "unique": false, "options": { "lengths": [ 60, null ] } },
+ { "name": "el_index", "columns": [ "el_index" ], "unique": false, "options": { "lengths": [ 60 ] } },
+ { "name": "el_index_60", "columns": [ "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_from_index_60", "columns": [ "el_from", "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_to_domain_index_to_path", "columns": [ "el_to_domain_index", "el_to_path" ], "unique": false, "options": { "lengths": [ null, 60 ] } }
+ ],
+ "pk": [ "el_id" ]
+ },
+ "after": {
+ "name": "externallinks",
+ "comment": "Track links to external URLs",
+ "columns": [
+ {
+ "name": "el_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "el_from",
+ "type": "integer",
+ "comment": "page_id of the referring page",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "el_to",
+ "type": "blob",
+ "comment": "The external link",
+ "options": { "length": 65530, "notnull": false, "default": "" }
+ },
+ {
+ "name": "el_index",
+ "type": "blob",
+ "comment": "In the case of HTTP URLs, this is the URL with any username or password removed, and with the labels in the hostname reversed and converted to lower case which will allow faster searching for all pages with WHERE clause. Note: If PHP's intl extension is enabled/disabled, maintenance/refreshExternallinksIndex.php needs to be run to refresh this field",
+ "options": { "length": 65530, "notnull": false, "default": "" }
+ },
+ {
+ "name": "el_index_60",
+ "type": "binary",
+ "comment": "'el_index' truncated to 60 bytes to allow for sortable queries that aren't supported by a partial index",
+ "options": { "notnull": true, "length": 60, "default": "" }
+ },
+ {
+ "name": "el_to_domain_index",
+ "type": "binary",
+ "comment": "Indexable domain",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "el_to_path",
+ "type": "blob",
+ "comment": "Path to the external link without considering the domain",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "el_from", "columns": [ "el_from" ], "unique": false },
+ { "name": "el_to", "columns": [ "el_to", "el_from" ], "unique": false, "options": { "lengths": [ 60, null ] } },
+ { "name": "el_index", "columns": [ "el_index" ], "unique": false, "options": { "lengths": [ 60 ] } },
+ { "name": "el_index_60", "columns": [ "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_from_index_60", "columns": [ "el_from", "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_to_domain_index_to_path", "columns": [ "el_to_domain_index", "el_to_path" ], "unique": false, "options": { "lengths": [ null, 60 ] } }
+ ],
+ "pk": [ "el_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-externallinks-el_to_path.json b/sql/abstractSchemaChanges/patch-externallinks-el_to_path.json
new file mode 100644
index 000000000000..77fb3b76e21c
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-externallinks-el_to_path.json
@@ -0,0 +1,102 @@
+{
+ "comment": "Set unsigned true for ipb_id and ipb_parent_block_id in ipblocks table",
+ "before": {
+ "name": "externallinks",
+ "comment": "Track links to external URLs",
+ "columns": [
+ {
+ "name": "el_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "el_from",
+ "type": "integer",
+ "comment": "page_id of the referring page",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "el_to",
+ "type": "blob",
+ "comment": "The external link",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "el_index",
+ "type": "blob",
+ "comment": "In the case of HTTP URLs, this is the URL with any username or password removed, and with the labels in the hostname reversed and converted to lower case which will allow faster searching for all pages with WHERE clause. Note: If PHP's intl extension is enabled/disabled, maintenance/refreshExternallinksIndex.php needs to be run to refresh this field",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "el_index_60",
+ "type": "binary",
+ "comment": "'el_index' truncated to 60 bytes to allow for sortable queries that aren't supported by a partial index",
+ "options": { "notnull": true, "length": 60 }
+ }
+ ],
+ "indexes": [
+ { "name": "el_from", "columns": [ "el_from", "el_to" ], "unique": false, "options": { "lengths": [ null, 40 ] } },
+ { "name": "el_to", "columns": [ "el_to", "el_from" ], "unique": false, "options": { "lengths": [ 60, null ] } },
+ { "name": "el_index", "columns": [ "el_index" ], "unique": false, "options": { "lengths": [ 60 ] } },
+ { "name": "el_index_60", "columns": [ "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_from_index_60", "columns": [ "el_from", "el_index_60", "el_id" ], "unique": false }
+ ],
+ "pk": [ "el_id" ]
+ },
+ "after": {
+ "name": "externallinks",
+ "comment": "Track links to external URLs",
+ "columns": [
+ {
+ "name": "el_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "el_from",
+ "type": "integer",
+ "comment": "page_id of the referring page",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "el_to",
+ "type": "blob",
+ "comment": "The external link",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "el_index",
+ "type": "blob",
+ "comment": "In the case of HTTP URLs, this is the URL with any username or password removed, and with the labels in the hostname reversed and converted to lower case which will allow faster searching for all pages with WHERE clause. Note: If PHP's intl extension is enabled/disabled, maintenance/refreshExternallinksIndex.php needs to be run to refresh this field",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "el_index_60",
+ "type": "binary",
+ "comment": "'el_index' truncated to 60 bytes to allow for sortable queries that aren't supported by a partial index",
+ "options": { "notnull": true, "length": 60 }
+ },
+ {
+ "name": "el_to_domain_index",
+ "type": "binary",
+ "comment": "Indexable domain",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "el_to_path",
+ "type": "blob",
+ "comment": "Path to the external link without considering the domain",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "el_from", "columns": [ "el_from" ], "unique": false },
+ { "name": "el_to", "columns": [ "el_to", "el_from" ], "unique": false, "options": { "lengths": [ 60, null ] } },
+ { "name": "el_index", "columns": [ "el_index" ], "unique": false, "options": { "lengths": [ 60 ] } },
+ { "name": "el_index_60", "columns": [ "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_from_index_60", "columns": [ "el_from", "el_index_60", "el_id" ], "unique": false },
+ { "name": "el_to_domain_index_to_path", "columns": [ "el_to_domain_index", "el_to_path" ], "unique": false, "options": { "lengths": [ null, 60 ] } }
+ ],
+ "pk": [ "el_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-filearchive-fa_id.json b/sql/abstractSchemaChanges/patch-filearchive-fa_id.json
new file mode 100644
index 000000000000..7b3b618273a2
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-filearchive-fa_id.json
@@ -0,0 +1,488 @@
+{
+ "comment": "Set unsigned true for fa_id in filearchive table",
+ "before": {
+ "name": "filearchive",
+ "comment": "Record of deleted file data",
+ "columns": [
+ {
+ "name": "fa_id",
+ "comment": "Unique row id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_name",
+ "comment": "Original base filename; key to image.img_name, page.page_title, etc",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_archive_name",
+ "comment": "Filename of archived file, if an old revision",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "Which storage bin (directory tree or object store) the file data is stored in. Should be 'deleted' for files that have been deleted; any other bin is not yet in use.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "length": 16
+ }
+ },
+ {
+ "name": "fa_storage_key",
+ "comment": "SHA-1 of the file contents plus extension, used as a key for storage. eg 8f8a562add37052a1848ff7771a2c515db94baa9.jpg. If NULL, the file was missing at deletion time or has been purged from the archival storage.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 64
+ }
+ },
+ {
+ "name": "fa_deleted_user",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "length": 14
+ }
+ },
+ {
+ "name": "fa_deleted_reason_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_width",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_height",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "fa_bits",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "fa_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "fa_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "fa_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "length": 14
+ }
+ },
+ {
+ "name": "fa_deleted",
+ "comment": "Visibility of deleted revisions, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "sha1 hash of file content",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "fa_name",
+ "comment": "pick out by image name",
+ "columns": [
+ "fa_name",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "pick out dupe files",
+ "columns": [
+ "fa_storage_group",
+ "fa_storage_key"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "comment": "sort by deletion time",
+ "columns": [
+ "fa_deleted_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_actor_timestamp",
+ "comment": "sort by uploader",
+ "columns": [
+ "fa_actor",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "find file by sha1, 10 bytes will be enough for hashes to be indexed",
+ "columns": [
+ "fa_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ }
+ ],
+ "pk": [
+ "fa_id"
+ ]
+ },
+ "after": {
+ "name": "filearchive",
+ "comment": "Record of deleted file data",
+ "columns": [
+ {
+ "name": "fa_id",
+ "comment": "Unique row id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_name",
+ "comment": "Original base filename; key to image.img_name, page.page_title, etc",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_archive_name",
+ "comment": "Filename of archived file, if an old revision",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "Which storage bin (directory tree or object store) the file data is stored in. Should be 'deleted' for files that have been deleted; any other bin is not yet in use.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "length": 16
+ }
+ },
+ {
+ "name": "fa_storage_key",
+ "comment": "SHA-1 of the file contents plus extension, used as a key for storage. eg 8f8a562add37052a1848ff7771a2c515db94baa9.jpg. If NULL, the file was missing at deletion time or has been purged from the archival storage.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 64
+ }
+ },
+ {
+ "name": "fa_deleted_user",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "length": 14
+ }
+ },
+ {
+ "name": "fa_deleted_reason_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_width",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_height",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "fa_bits",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "fa_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "fa_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "fa_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "length": 14
+ }
+ },
+ {
+ "name": "fa_deleted",
+ "comment": "Visibility of deleted revisions, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "sha1 hash of file content",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "fa_name",
+ "comment": "pick out by image name",
+ "columns": [
+ "fa_name",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "pick out dupe files",
+ "columns": [
+ "fa_storage_group",
+ "fa_storage_key"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "comment": "sort by deletion time",
+ "columns": [
+ "fa_deleted_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_actor_timestamp",
+ "comment": "sort by uploader",
+ "columns": [
+ "fa_actor",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "find file by sha1, 10 bytes will be enough for hashes to be indexed",
+ "columns": [
+ "fa_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ }
+ ],
+ "pk": [
+ "fa_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-filearchive-fa_size_to_bigint.json b/sql/abstractSchemaChanges/patch-filearchive-fa_size_to_bigint.json
new file mode 100644
index 000000000000..7226c09e9bfc
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-filearchive-fa_size_to_bigint.json
@@ -0,0 +1,487 @@
+{
+ "comment": "Increase fa_size to bigint (T191805)",
+ "before":
+ {
+ "name": "filearchive",
+ "comment": "Record of deleted file data",
+ "columns": [
+ {
+ "name": "fa_id",
+ "comment": "Unique row id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_name",
+ "comment": "Original base filename; key to image.img_name, page.page_title, etc",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_archive_name",
+ "comment": "Filename of archived file, if an old revision",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "Which storage bin (directory tree or object store) the file data is stored in. Should be 'deleted' for files that have been deleted; any other bin is not yet in use.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "length": 16
+ }
+ },
+ {
+ "name": "fa_storage_key",
+ "comment": "SHA-1 of the file contents plus extension, used as a key for storage. eg 8f8a562add37052a1848ff7771a2c515db94baa9.jpg. If NULL, the file was missing at deletion time or has been purged from the archival storage.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 64
+ }
+ },
+ {
+ "name": "fa_deleted_user",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted_reason_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_width",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_height",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "fa_bits",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "fa_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "fa_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "fa_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted",
+ "comment": "Visibility of deleted revisions, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "sha1 hash of file content",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "fa_name",
+ "comment": "pick out by image name",
+ "columns": [
+ "fa_name",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "pick out dupe files",
+ "columns": [
+ "fa_storage_group",
+ "fa_storage_key"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "comment": "sort by deletion time",
+ "columns": [
+ "fa_deleted_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_actor_timestamp",
+ "comment": "sort by uploader",
+ "columns": [
+ "fa_actor",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "find file by sha1, 10 bytes will be enough for hashes to be indexed",
+ "columns": [
+ "fa_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ }
+ ],
+ "pk": [
+ "fa_id"
+ ]
+ },
+ "after":
+ {
+ "name": "filearchive",
+ "comment": "Record of deleted file data",
+ "columns": [
+ {
+ "name": "fa_id",
+ "comment": "Unique row id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_name",
+ "comment": "Original base filename; key to image.img_name, page.page_title, etc",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_archive_name",
+ "comment": "Filename of archived file, if an old revision",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "Which storage bin (directory tree or object store) the file data is stored in. Should be 'deleted' for files that have been deleted; any other bin is not yet in use.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "length": 16
+ }
+ },
+ {
+ "name": "fa_storage_key",
+ "comment": "SHA-1 of the file contents plus extension, used as a key for storage. eg 8f8a562add37052a1848ff7771a2c515db94baa9.jpg. If NULL, the file was missing at deletion time or has been purged from the archival storage.",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "",
+ "length": 64
+ }
+ },
+ {
+ "name": "fa_deleted_user",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted_reason_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_size",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_width",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_height",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "fa_bits",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "fa_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "fa_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "fa_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "fa_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "fa_deleted",
+ "comment": "Visibility of deleted revisions, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "sha1 hash of file content",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "fa_name",
+ "comment": "pick out by image name",
+ "columns": [
+ "fa_name",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_storage_group",
+ "comment": "pick out dupe files",
+ "columns": [
+ "fa_storage_group",
+ "fa_storage_key"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_deleted_timestamp",
+ "comment": "sort by deletion time",
+ "columns": [
+ "fa_deleted_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_actor_timestamp",
+ "comment": "sort by uploader",
+ "columns": [
+ "fa_actor",
+ "fa_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "fa_sha1",
+ "comment": "find file by sha1, 10 bytes will be enough for hashes to be indexed",
+ "columns": [
+ "fa_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ }
+ ],
+ "pk": [
+ "fa_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-image-img_size_to_bigint.json b/sql/abstractSchemaChanges/patch-image-img_size_to_bigint.json
new file mode 100644
index 000000000000..b86976409173
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-image-img_size_to_bigint.json
@@ -0,0 +1,368 @@
+{
+ "comment": "Make img.img_size an unsigned bigint (T191805)",
+ "before":
+ {
+ "name": "image",
+ "comment": "Uploaded images and other files.",
+ "columns": [
+ {
+ "name": "img_name",
+ "comment": "Filename. This is also the title of the associated description page, which will be in namespace 6 (NS_FILE).",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "img_size",
+ "comment": "File size in bytes.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_width",
+ "comment": "For images, width in pixels.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_height",
+ "comment": "For images, height in pixels.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_metadata",
+ "comment": "Extracted Exif metadata stored as a json array (new system) or serialized PHP array (old system). The json array can contain an address in the text table or external storage.",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "img_bits",
+ "comment": "For images, bits per pixel if known.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_media_type",
+ "comment": "Media type as defined by the MEDIATYPE_xxx constants",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "img_major_mime",
+ "comment": "major part of a MIME media type as defined by IANA see https://www.iana.org/assignments/media-types/ for \"chemical\" cf. http://dx.doi.org/10.1021/ci9803233 by the ACS",
+ "type": "mwenum",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "img_minor_mime",
+ "comment": "minor part of a MIME media type as defined by IANA the minor parts are not required to adhere to any standard but should be consistent throughout the database see https://www.iana.org/assignments/media-types/",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "img_description_id",
+ "comment": "Foreign key to comment table, which contains the description field as entered by the uploader. This is displayed in image upload history and logs.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "img_actor",
+ "comment": "actor_id of the uploader.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "img_timestamp",
+ "comment": "Time of the upload.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "img_sha1",
+ "comment": "SHA-1 content hash in base-36",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "img_actor_timestamp",
+ "comment": "Used by Special:Newimages and ApiQueryAllImages",
+ "columns": [
+ "img_actor",
+ "img_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "img_size",
+ "comment": "Used by Special:ListFiles for sort-by-size",
+ "columns": [
+ "img_size"
+ ],
+ "unique": false
+ },
+ {
+ "name": "img_timestamp",
+ "comment": "Used by Special:Newimages and Special:ListFiles",
+ "columns": [
+ "img_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "img_sha1",
+ "comment": "Used in API and duplicate search",
+ "columns": [
+ "img_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ },
+ {
+ "name": "img_media_mime",
+ "comment": "Used to get media of one type",
+ "columns": [
+ "img_media_type",
+ "img_major_mime",
+ "img_minor_mime"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "img_name"
+ ]
+ },
+ "after":
+ {
+ "name": "image",
+ "comment": "Uploaded images and other files.",
+ "columns": [
+ {
+ "name": "img_name",
+ "comment": "Filename. This is also the title of the associated description page, which will be in namespace 6 (NS_FILE).",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "img_size",
+ "comment": "File size in bytes.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_width",
+ "comment": "For images, width in pixels.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_height",
+ "comment": "For images, height in pixels.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_metadata",
+ "comment": "Extracted Exif metadata stored as a json array (new system) or serialized PHP array (old system). The json array can contain an address in the text table or external storage.",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "img_bits",
+ "comment": "For images, bits per pixel if known.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "img_media_type",
+ "comment": "Media type as defined by the MEDIATYPE_xxx constants",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "img_major_mime",
+ "comment": "major part of a MIME media type as defined by IANA see https://www.iana.org/assignments/media-types/ for \"chemical\" cf. http://dx.doi.org/10.1021/ci9803233 by the ACS",
+ "type": "mwenum",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "img_minor_mime",
+ "comment": "minor part of a MIME media type as defined by IANA the minor parts are not required to adhere to any standard but should be consistent throughout the database see https://www.iana.org/assignments/media-types/",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "img_description_id",
+ "comment": "Foreign key to comment table, which contains the description field as entered by the uploader. This is displayed in image upload history and logs.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "img_actor",
+ "comment": "actor_id of the uploader.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "img_timestamp",
+ "comment": "Time of the upload.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "img_sha1",
+ "comment": "SHA-1 content hash in base-36",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "img_actor_timestamp",
+ "comment": "Used by Special:Newimages and ApiQueryAllImages",
+ "columns": [
+ "img_actor",
+ "img_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "img_size",
+ "comment": "Used by Special:ListFiles for sort-by-size",
+ "columns": [
+ "img_size"
+ ],
+ "unique": false
+ },
+ {
+ "name": "img_timestamp",
+ "comment": "Used by Special:Newimages and Special:ListFiles",
+ "columns": [
+ "img_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "img_sha1",
+ "comment": "Used in API and duplicate search",
+ "columns": [
+ "img_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ },
+ {
+ "name": "img_media_mime",
+ "comment": "Used to get media of one type",
+ "columns": [
+ "img_media_type",
+ "img_major_mime",
+ "img_minor_mime"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "img_name"
+ ]
+ }
+
+}
diff --git a/sql/abstractSchemaChanges/patch-ipblocks-ipb_id.json b/sql/abstractSchemaChanges/patch-ipblocks-ipb_id.json
new file mode 100644
index 000000000000..b5fdde258ceb
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-ipblocks-ipb_id.json
@@ -0,0 +1,477 @@
+{
+ "comment": "Set unsigned true for ipb_id and ipb_parent_block_id in ipblocks table",
+ "before": {
+ "name": "ipblocks",
+ "comment": "Blocks against user accounts, IP addresses and IP ranges.",
+ "columns": [
+ {
+ "name": "ipb_id",
+ "comment": "Primary key, introduced for privacy.",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_address",
+ "comment": "Blocked IP address in dotted-quad form or user name.",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "ipb_user",
+ "comment": "Blocked user ID or 0 for IP blocks.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_by_actor",
+ "comment": "Actor who made the block.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_reason_id",
+ "comment": "Key to comment_id. Text comment made by blocker.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_timestamp",
+ "comment": "Creation (or refresh) date in standard YMDHMS form. IP blocks expire automatically.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_auto",
+ "comment": "Indicates that the IP address was banned because a banned user accessed a page through it. If this is 1, ipb_address will be hidden, and the block identified by block ID number.",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_anon_only",
+ "comment": "If set to 1, block applies only to logged-out users",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_create_account",
+ "comment": "Block prevents account creation from matching IP addresses",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 1
+ }
+ },
+ {
+ "name": "ipb_enable_autoblock",
+ "comment": "Block triggers autoblocks",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 1
+ }
+ },
+ {
+ "name": "ipb_expiry",
+ "comment": "Time at which the block will expire. May be \"infinity\"",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "ipb_range_start",
+ "comment": "Start of an address range, in hexadecimal size chosen to allow IPv6. FIXME: this field were originally blank for single-IP blocks, but now it's populated. No migration was ever done. It should be fixed to be blank again for such blocks (T51504).",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "ipb_range_end",
+ "comment": "End of an address range, in hexadecimal size chosen to allow IPv6. FIXME: this field were originally blank for single-IP blocks, but now it's populated. No migration was ever done. It should be fixed to be blank again for such blocks (T51504).",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "ipb_deleted",
+ "comment": "Flag for entries hidden from users and Sysops",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_block_email",
+ "comment": "Block prevents user from accessing Special:Emailuser",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_allow_usertalk",
+ "comment": "Block allows user to edit their own talk page",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_parent_block_id",
+ "comment": "ID of the block that caused this block to exist. Autoblocks set this to the original block so that the original block being deleted also deletes the autoblocks",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "default": null
+ }
+ },
+ {
+ "name": "ipb_sitewide",
+ "comment": "Block user from editing any page on the site (other than their own user talk page).",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 1
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "ipb_address_unique",
+ "comment": "Unique index to support \"user already blocked\" messages. Any new options which prevent collisions should be included",
+ "columns": [
+ "ipb_address",
+ "ipb_user",
+ "ipb_auto"
+ ],
+ "unique": true,
+ "options": { "lengths": [ 255, null, null ] }
+ },
+ {
+ "name": "ipb_user",
+ "comment": "For querying whether a logged-in user is blocked",
+ "columns": [
+ "ipb_user"
+ ],
+ "unique": false
+ },
+ {
+ "name": "ipb_range",
+ "comment": "For querying whether an IP address is in any range",
+ "columns": [
+ "ipb_range_start",
+ "ipb_range_end"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 8, 8 ] }
+ },
+ {
+ "name": "ipb_timestamp",
+ "comment": "Index for Special:BlockList",
+ "columns": [
+ "ipb_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "ipb_expiry",
+ "comment": "Index for table pruning",
+ "columns": [
+ "ipb_expiry"
+ ],
+ "unique": false
+ },
+ {
+ "name": "ipb_parent_block_id",
+ "comment": "Index for removing autoblocks when a parent block is removed",
+ "columns": [
+ "ipb_parent_block_id"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "ipb_id"
+ ]
+ },
+ "after": {
+ "name": "ipblocks",
+ "comment": "Blocks against user accounts, IP addresses and IP ranges.",
+ "columns": [
+ {
+ "name": "ipb_id",
+ "comment": "Primary key, introduced for privacy.",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "notnull": true,
+ "unsigned": true
+ }
+ },
+ {
+ "name": "ipb_address",
+ "comment": "Blocked IP address in dotted-quad form or user name.",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "ipb_user",
+ "comment": "Blocked user ID or 0 for IP blocks.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_by_actor",
+ "comment": "Actor who made the block.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_reason_id",
+ "comment": "Key to comment_id. Text comment made by blocker.",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_timestamp",
+ "comment": "Creation (or refresh) date in standard YMDHMS form. IP blocks expire automatically.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "ipb_auto",
+ "comment": "Indicates that the IP address was banned because a banned user accessed a page through it. If this is 1, ipb_address will be hidden, and the block identified by block ID number.",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_anon_only",
+ "comment": "If set to 1, block applies only to logged-out users",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_create_account",
+ "comment": "Block prevents account creation from matching IP addresses",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 1
+ }
+ },
+ {
+ "name": "ipb_enable_autoblock",
+ "comment": "Block triggers autoblocks",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 1
+ }
+ },
+ {
+ "name": "ipb_expiry",
+ "comment": "Time at which the block will expire. May be \"infinity\"",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "ipb_range_start",
+ "comment": "Start of an address range, in hexadecimal size chosen to allow IPv6. FIXME: this field were originally blank for single-IP blocks, but now it's populated. No migration was ever done. It should be fixed to be blank again for such blocks (T51504).",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "ipb_range_end",
+ "comment": "End of an address range, in hexadecimal size chosen to allow IPv6. FIXME: this field were originally blank for single-IP blocks, but now it's populated. No migration was ever done. It should be fixed to be blank again for such blocks (T51504).",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "ipb_deleted",
+ "comment": "Flag for entries hidden from users and Sysops",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_block_email",
+ "comment": "Block prevents user from accessing Special:Emailuser",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_allow_usertalk",
+ "comment": "Block allows user to edit their own talk page",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ },
+ {
+ "name": "ipb_parent_block_id",
+ "comment": "ID of the block that caused this block to exist. Autoblocks set this to the original block so that the original block being deleted also deletes the autoblocks",
+ "type": "integer",
+ "options": {
+ "notnull": false,
+ "unsigned": true,
+ "default": null
+ }
+ },
+ {
+ "name": "ipb_sitewide",
+ "comment": "Block user from editing any page on the site (other than their own user talk page).",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 1
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "ipb_address_unique",
+ "comment": "Unique index to support \"user already blocked\" messages. Any new options which prevent collisions should be included",
+ "columns": [
+ "ipb_address",
+ "ipb_user",
+ "ipb_auto"
+ ],
+ "unique": true,
+ "options": { "lengths": [ 255, null, null ] }
+ },
+ {
+ "name": "ipb_user",
+ "comment": "For querying whether a logged-in user is blocked",
+ "columns": [
+ "ipb_user"
+ ],
+ "unique": false
+ },
+ {
+ "name": "ipb_range",
+ "comment": "For querying whether an IP address is in any range",
+ "columns": [
+ "ipb_range_start",
+ "ipb_range_end"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 8, 8 ] }
+ },
+ {
+ "name": "ipb_timestamp",
+ "comment": "Index for Special:BlockList",
+ "columns": [
+ "ipb_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "ipb_expiry",
+ "comment": "Index for table pruning",
+ "columns": [
+ "ipb_expiry"
+ ],
+ "unique": false
+ },
+ {
+ "name": "ipb_parent_block_id",
+ "comment": "Index for removing autoblocks when a parent block is removed",
+ "columns": [
+ "ipb_parent_block_id"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "ipb_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_ipb_id.json b/sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_ipb_id.json
new file mode 100644
index 000000000000..2cddb8ddd58d
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_ipb_id.json
@@ -0,0 +1,69 @@
+{
+ "comment": "Set unsigned true for ir_ipb_id in ipblocks_restrictions table",
+ "before": {
+ "name": "ipblocks_restrictions",
+ "comment": "Partial Block Restrictions",
+ "columns": [
+ {
+ "name": "ir_ipb_id",
+ "comment": "The ipb_id from ipblocks",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "ir_type",
+ "comment": "The restriction type id.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "length": 4 }
+ },
+ {
+ "name": "ir_value",
+ "comment": "The restriction id that corresponds to the type. Typically a Page ID or a Namespace ID.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "ir_type_value",
+ "comment": "Index to query restrictions by the page or namespace.",
+ "columns": [ "ir_type", "ir_value" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ir_ipb_id", "ir_type", "ir_value" ]
+ },
+ "after": {
+ "name": "ipblocks_restrictions",
+ "comment": "Partial Block Restrictions",
+ "columns": [
+ {
+ "name": "ir_ipb_id",
+ "comment": "The ipb_id from ipblocks",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "ir_type",
+ "comment": "The restriction type id.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "length": 4 }
+ },
+ {
+ "name": "ir_value",
+ "comment": "The restriction id that corresponds to the type. Typically a Page ID or a Namespace ID.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "ir_type_value",
+ "comment": "Index to query restrictions by the page or namespace.",
+ "columns": [ "ir_type", "ir_value" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ir_ipb_id", "ir_type", "ir_value" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_value.json b/sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_value.json
new file mode 100644
index 000000000000..c1ca1177e9c7
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-ipblocks_restrictions-ir_value.json
@@ -0,0 +1,69 @@
+{
+ "comment": "Set unsigned true for ir_value in ipblocks_restrictions table",
+ "before": {
+ "name": "ipblocks_restrictions",
+ "comment": "Partial Block Restrictions",
+ "columns": [
+ {
+ "name": "ir_ipb_id",
+ "comment": "The ipb_id from ipblocks",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "ir_type",
+ "comment": "The restriction type id.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "length": 4 }
+ },
+ {
+ "name": "ir_value",
+ "comment": "The restriction id that corresponds to the type. Typically a Page ID or a Namespace ID.",
+ "type": "integer",
+ "options": { "notnull": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "ir_type_value",
+ "comment": "Index to query restrictions by the page or namespace.",
+ "columns": [ "ir_type", "ir_value" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ir_ipb_id", "ir_type", "ir_value" ]
+ },
+ "after": {
+ "name": "ipblocks_restrictions",
+ "comment": "Partial Block Restrictions",
+ "columns": [
+ {
+ "name": "ir_ipb_id",
+ "comment": "The ipb_id from ipblocks",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "ir_type",
+ "comment": "The restriction type id.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "length": 4 }
+ },
+ {
+ "name": "ir_value",
+ "comment": "The restriction id that corresponds to the type. Typically a Page ID or a Namespace ID.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "ir_type_value",
+ "comment": "Index to query restrictions by the page or namespace.",
+ "columns": [ "ir_type", "ir_value" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "ir_ipb_id", "ir_type", "ir_value" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-iwlinks-drop-iwl_prefix_from_title.json b/sql/abstractSchemaChanges/patch-iwlinks-drop-iwl_prefix_from_title.json
new file mode 100644
index 000000000000..170f77bbae48
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-iwlinks-drop-iwl_prefix_from_title.json
@@ -0,0 +1,75 @@
+{
+ "comment": "Drop iwl_title field from iwl_prefix_from_title index",
+ "before": {
+ "name": "iwlinks",
+ "comment": "Track inline interwiki links",
+ "columns": [
+ {
+ "name": "iwl_from",
+ "comment": "page_id of the referring page",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "iwl_prefix",
+ "type": "binary",
+ "comment": "Interwiki prefix code of the target",
+ "options": { "notnull": true, "length": 32, "default": "" }
+ },
+ {
+ "name": "iwl_title",
+ "type": "binary",
+ "comment": "Title of the target, including namespace",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "iwl_prefix_title_from",
+ "columns": [ "iwl_prefix", "iwl_title", "iwl_from" ],
+ "comment": "Index for ApiQueryIWBacklinks",
+ "unique": false
+ },
+ {
+ "name": "iwl_prefix_from_title",
+ "columns": [ "iwl_prefix", "iwl_from", "iwl_title" ],
+ "comment": "Index for ApiQueryIWLinks",
+ "unique": false
+ }
+ ],
+ "pk": [ "iwl_from", "iwl_prefix", "iwl_title" ]
+ },
+ "after": {
+ "name": "iwlinks",
+ "comment": "Track inline interwiki links",
+ "columns": [
+ {
+ "name": "iwl_from",
+ "comment": "page_id of the referring page",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "iwl_prefix",
+ "type": "binary",
+ "comment": "Interwiki prefix code of the target",
+ "options": { "notnull": true, "length": 32, "default": "" }
+ },
+ {
+ "name": "iwl_title",
+ "type": "binary",
+ "comment": "Title of the target, including namespace",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "iwl_prefix_title_from",
+ "columns": [ "iwl_prefix", "iwl_title", "iwl_from" ],
+ "comment": "Index for ApiQueryIWBacklinks",
+ "unique": false
+ }
+ ],
+ "pk": [ "iwl_from", "iwl_prefix", "iwl_title" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-logging-rename-indexes.json b/sql/abstractSchemaChanges/patch-logging-rename-indexes.json
new file mode 100644
index 000000000000..03b96edd467d
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-logging-rename-indexes.json
@@ -0,0 +1,231 @@
+{
+ "comment": "Rename several indexes in logging table to comply with database convention by having log_ prefix",
+ "before": {
+ "name": "logging",
+ "columns": [
+ {
+ "name": "log_id",
+ "comment": "Log ID, for referring to this specific log entry, probably for deletion and such.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "log_type",
+ "comment": "Symbolic key for the general log type. The output format will be controlled by the log_action field.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32 }
+ },
+ {
+ "name": "log_action",
+ "comment": "Symbolic key for the log action type.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32 }
+ },
+ {
+ "name": "log_timestamp",
+ "type": "mwtimestamp",
+ "options": { "notnull": true, "default": "19700101000000" }
+ },
+ {
+ "name": "log_actor",
+ "type": "bigint",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "log_namespace",
+ "comment": "Key to the namespace of the page affected",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "log_title",
+ "comment": "Key to the title of the page affected",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "log_page",
+ "comment": "Key to the page affected",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true }
+ },
+ {
+ "name": "log_comment_id",
+ "comment": "Key to comment_id. Comment summarizing the change.",
+ "type": "bigint",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "log_params",
+ "comment": "LF separated list (old system) or serialized PHP array (new system)",
+ "type": "blob",
+ "options": { "notnull": true, "length": 65530 }
+ },
+ {
+ "name": "log_deleted",
+ "comment": "rev_deleted for logs",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "type_time",
+ "comment": "Special:Log type filter",
+ "columns": [ "log_type", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "actor_time",
+ "comment": "Special:Log performer filter",
+ "columns": [ "log_actor", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "page_time",
+ "comment": "Special:Log title filter, log extract",
+ "columns": [ "log_namespace", "log_title", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "times",
+ "comment": "Special:Log unfiltered",
+ "columns": [ "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_actor_type_time",
+ "comment": "Special:Log filter by performer and type",
+ "columns": [ "log_actor", "log_type", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_page_id_time",
+ "comment": "Apparently just used for a few maintenance pages (findMissingFiles.php, Flow). Could be removed?",
+ "columns": [ "log_page", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_type_action",
+ "comment": "Special:Log action filter",
+ "columns": [ "log_type", "log_action", "log_timestamp" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "log_id" ]
+ },
+ "after": {
+ "name": "logging",
+ "columns": [
+ {
+ "name": "log_id",
+ "comment": "Log ID, for referring to this specific log entry, probably for deletion and such.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "log_type",
+ "comment": "Symbolic key for the general log type. The output format will be controlled by the log_action field.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32 }
+ },
+ {
+ "name": "log_action",
+ "comment": "Symbolic key for the log action type.",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32 }
+ },
+ {
+ "name": "log_timestamp",
+ "type": "mwtimestamp",
+ "options": { "notnull": true, "default": "19700101000000" }
+ },
+ {
+ "name": "log_actor",
+ "type": "bigint",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "log_namespace",
+ "comment": "Key to the namespace of the page affected",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "log_title",
+ "comment": "Key to the title of the page affected",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "log_page",
+ "comment": "Key to the page affected",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true }
+ },
+ {
+ "name": "log_comment_id",
+ "comment": "Key to comment_id. Comment summarizing the change.",
+ "type": "bigint",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "log_params",
+ "comment": "LF separated list (old system) or serialized PHP array (new system)",
+ "type": "blob",
+ "options": { "notnull": true, "length": 65530 }
+ },
+ {
+ "name": "log_deleted",
+ "comment": "rev_deleted for logs",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "log_type_time",
+ "comment": "Special:Log type filter",
+ "columns": [ "log_type", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_actor_time",
+ "comment": "Special:Log performer filter",
+ "columns": [ "log_actor", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_page_time",
+ "comment": "Special:Log title filter, log extract",
+ "columns": [ "log_namespace", "log_title", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_times",
+ "comment": "Special:Log unfiltered",
+ "columns": [ "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_actor_type_time",
+ "comment": "Special:Log filter by performer and type",
+ "columns": [ "log_actor", "log_type", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_page_id_time",
+ "comment": "Apparently just used for a few maintenance pages (findMissingFiles.php, Flow). Could be removed?",
+ "columns": [ "log_page", "log_timestamp" ],
+ "unique": false
+ },
+ {
+ "name": "log_type_action",
+ "comment": "Special:Log action filter",
+ "columns": [ "log_type", "log_action", "log_timestamp" ],
+ "unique": false
+ }
+ ],
+ "pk": [ "log_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-objectcache-modtoken.json b/sql/abstractSchemaChanges/patch-objectcache-modtoken.json
new file mode 100644
index 000000000000..8cb587cc603c
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-objectcache-modtoken.json
@@ -0,0 +1,63 @@
+{
+ "comment": "Add objectcache.modtime and objectcache.token fields (T274174)",
+ "before": {
+ "name": "objectcache",
+ "comment": "For a few generic cache operations if not using Memcached",
+ "columns": [
+ {
+ "name": "keyname",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "value",
+ "type": "blob",
+ "options": { "notnull": false, "length": 16777215 }
+ },
+ {
+ "name": "exptime",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "exptime", "columns": [ "exptime" ], "unique": false }
+ ],
+ "pk": [ "keyname" ]
+ },
+ "after": {
+ "name": "objectcache",
+ "comment": "For a few generic cache operations if not using Memcached",
+ "columns": [
+ {
+ "name": "keyname",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 255 }
+ },
+ {
+ "name": "value",
+ "type": "blob",
+ "options": { "notnull": false, "length": 16777215 }
+ },
+ {
+ "name": "exptime",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "modtoken",
+ "type": "string",
+ "options": { "notnull": true, "length": 17, "default": "00000000000000000" }
+ },
+ {
+ "name": "flags",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true, "default": null }
+ }
+ ],
+ "indexes": [
+ { "name": "exptime", "columns": [ "exptime" ], "unique": false }
+ ],
+ "pk": [ "keyname" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-oldimage-oi_size_to_bigint.json b/sql/abstractSchemaChanges/patch-oldimage-oi_size_to_bigint.json
new file mode 100644
index 000000000000..e122bc373e36
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-oldimage-oi_size_to_bigint.json
@@ -0,0 +1,371 @@
+{
+ "comment": "Increase oi_size to be a bigint (T191805)",
+ "before":
+ {
+ "name": "oldimage",
+ "comment": "Previous revisions of uploaded files. Awkwardly, image rows have to be moved into this table at re-upload time.",
+ "columns": [
+ {
+ "name": "oi_name",
+ "comment": "Base filename: key to image.img_name",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_archive_name",
+ "comment": "Filename of the archived file. This is generally a timestamp and '!' prepended to the base name.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_width",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_height",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_bits",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "oi_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "oi_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "oi_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "oi_deleted",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_sha1",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "oi_actor_timestamp",
+ "columns": [
+ "oi_actor",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_timestamp",
+ "columns": [
+ "oi_name",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_archive_name",
+ "comment": "oi_archive_name truncated to 14 to avoid key length overflow",
+ "columns": [
+ "oi_name",
+ "oi_archive_name"
+ ],
+ "unique": false,
+ "options": { "lengths": [ null, 14 ] }
+ },
+ {
+ "name": "oi_sha1",
+ "columns": [
+ "oi_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ },
+ {
+ "name": "oi_timestamp",
+ "comment": "Used by Special:ListFiles",
+ "columns": [
+ "oi_timestamp"
+ ],
+ "unique": false
+ }
+ ]
+ },
+ "after":
+ {
+ "name": "oldimage",
+ "comment": "Previous revisions of uploaded files. Awkwardly, image rows have to be moved into this table at re-upload time.",
+ "columns": [
+ {
+ "name": "oi_name",
+ "comment": "Base filename: key to image.img_name",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_archive_name",
+ "comment": "Filename of the archived file. This is generally a timestamp and '!' prepended to the base name.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_size",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_width",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_height",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_bits",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "oi_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "oi_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "oi_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "oi_deleted",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_sha1",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "oi_actor_timestamp",
+ "columns": [
+ "oi_actor",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_timestamp",
+ "columns": [
+ "oi_name",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_archive_name",
+ "comment": "oi_archive_name truncated to 14 to avoid key length overflow",
+ "columns": [
+ "oi_name",
+ "oi_archive_name"
+ ],
+ "unique": false,
+ "options": { "lengths": [ null, 14 ] }
+ },
+ {
+ "name": "oi_sha1",
+ "columns": [
+ "oi_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ },
+ {
+ "name": "oi_timestamp",
+ "comment": "Used by Special:ListFiles",
+ "columns": [
+ "oi_timestamp"
+ ],
+ "unique": false
+ }
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-oldimage-oi_timestamp.json b/sql/abstractSchemaChanges/patch-oldimage-oi_timestamp.json
new file mode 100644
index 000000000000..32ee34ae43e2
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-oldimage-oi_timestamp.json
@@ -0,0 +1,363 @@
+{
+ "comment": "Add index on oi_timestamp (T279982)",
+ "before": {
+ "name": "oldimage",
+ "comment": "Previous revisions of uploaded files. Awkwardly, image rows have to be moved into this table at re-upload time.",
+ "columns": [
+ {
+ "name": "oi_name",
+ "comment": "Base filename: key to image.img_name",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_archive_name",
+ "comment": "Filename of the archived file. This is generally a timestamp and '!' prepended to the base name.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_width",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_height",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_bits",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "length": 14
+ }
+ },
+ {
+ "name": "oi_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "oi_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "oi_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "oi_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "oi_deleted",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_sha1",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "oi_actor_timestamp",
+ "columns": [
+ "oi_actor",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_timestamp",
+ "columns": [
+ "oi_name",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_archive_name",
+ "comment": "oi_archive_name truncated to 14 to avoid key length overflow",
+ "columns": [
+ "oi_name",
+ "oi_archive_name"
+ ],
+ "unique": false,
+ "options": { "lengths": [ null, 14 ] }
+ },
+ {
+ "name": "oi_sha1",
+ "columns": [
+ "oi_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ }
+ ]
+ },
+ "after": {
+ "name": "oldimage",
+ "comment": "Previous revisions of uploaded files. Awkwardly, image rows have to be moved into this table at re-upload time.",
+ "columns": [
+ {
+ "name": "oi_name",
+ "comment": "Base filename: key to image.img_name",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_archive_name",
+ "comment": "Filename of the archived file. This is generally a timestamp and '!' prepended to the base name.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "oi_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_width",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_height",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_bits",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_description_id",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_actor",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "oi_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "length": 14
+ }
+ },
+ {
+ "name": "oi_metadata",
+ "type": "blob",
+ "options": {
+ "notnull": true,
+ "length": 16777215
+ }
+ },
+ {
+ "name": "oi_media_type",
+ "type": "mwenum",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "oi_major_mime",
+ "type": "mwenum",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "CustomSchemaOptions": {
+ "enum_values": [ "unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical" ]
+ }
+ }
+ },
+ {
+ "name": "oi_minor_mime",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "unknown",
+ "length": 100
+ }
+ },
+ {
+ "name": "oi_deleted",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "oi_sha1",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 32
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "oi_actor_timestamp",
+ "columns": [
+ "oi_actor",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_timestamp",
+ "columns": [
+ "oi_name",
+ "oi_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "oi_name_archive_name",
+ "comment": "oi_archive_name truncated to 14 to avoid key length overflow",
+ "columns": [
+ "oi_name",
+ "oi_archive_name"
+ ],
+ "unique": false,
+ "options": { "lengths": [ null, 14 ] }
+ },
+ {
+ "name": "oi_sha1",
+ "columns": [
+ "oi_sha1"
+ ],
+ "unique": false,
+ "options": { "lengths": [ 10 ] }
+ },
+ {
+ "name": "oi_timestamp",
+ "comment": "Used by Special:ListFiles",
+ "columns": [
+ "oi_timestamp"
+ ],
+ "unique": false
+ }
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-page-drop-page_restrictions.json b/sql/abstractSchemaChanges/patch-page-drop-page_restrictions.json
new file mode 100644
index 000000000000..ee21dc05b194
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-page-drop-page_restrictions.json
@@ -0,0 +1,243 @@
+{
+ "comment": "Drop legacy page.page_restrictions field (T35334)",
+ "before": {
+ "name": "page",
+ "comment": "Core of the wiki: each page has an entry here which identifies it by title and contains some essential metadata.",
+ "columns": [
+ {
+ "name": "page_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "page_namespace",
+ "comment": "A page name is broken into a namespace and a title. The namespace keys are UI-language-independent constants, defined in includes/Defines.php",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_title",
+ "comment": "The rest of the title, as text. Spaces are transformed into underscores in title storage.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "page_restrictions",
+ "comment": "Comma-separated set of permission keys indicating who can move or edit the page.",
+ "type": "blob",
+ "options": { "notnull": false, "length": 255 }
+ },
+ {
+ "name": "page_is_redirect",
+ "comment": "1 indicates the article is a redirect.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_is_new",
+ "comment": "1 indicates this is a new entry, with only one edit. Not all pages with one edit are new pages.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_random",
+ "comment": "Random value between 0 and 1, used for Special:Randompage",
+ "type": "float",
+ "options": {
+ "notnull": true,
+ "unsigned": true,
+ "CustomSchemaOptions": {
+ "doublePrecision": true
+ }
+ }
+ },
+ {
+ "name": "page_touched",
+ "comment": "This timestamp is updated whenever the page changes in a way requiring it to be re-rendered, invalidating caches. Aside from editing this includes permission changes, creation or deletion of linked pages, and alteration of contained templates.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_links_updated",
+ "comment": "This timestamp is updated whenever a page is re-parsed and it has all the link tracking tables updated for it. This is useful for de-duplicating expensive backlink update jobs.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "page_latest",
+ "comment": "Handy key to revision.rev_id of the current revision. This may be 0 during page creation, but that shouldn't happen outside of a transaction... hopefully.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_len",
+ "comment": "Uncompressed length in bytes of the page's current source text.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_content_model",
+ "comment": "content model, see CONTENT_MODEL_XXX constants",
+ "type": "binary",
+ "options": { "length": 32, "notnull": false }
+ },
+ {
+ "name": "page_lang",
+ "comment": "Page content language",
+ "type": "binary",
+ "options": { "length": 35, "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "page_name_title",
+ "columns": [ "page_namespace", "page_title" ],
+ "comment": "The title index. Care must be taken to always specify a namespace when by title, so that the index is used. Even listing all known namespaces with IN() is better than omitting page_namespace from the WHERE clause.",
+ "unique": true
+ },
+ {
+ "name": "page_random",
+ "columns": [ "page_random" ],
+ "comment": "Index for Special:Random",
+ "unique": false
+ },
+ {
+ "name": "page_len",
+ "columns": [ "page_len" ],
+ "comment": "Questionable utility, used by ProofreadPage, possibly DynamicPageList. ApiQueryAllPages unconditionally filters on namespace and so hopefully does not use it.",
+ "unique": false
+ },
+ {
+ "name": "page_redirect_namespace_len",
+ "columns": [ "page_is_redirect", "page_namespace", "page_len" ],
+ "comment": "The index for Special:Shortpages and Special:Longpages. Also SiteStats::articles() in 'comma' counting mode, MessageCache::loadFromDB().",
+ "unique": false
+ }
+ ],
+ "pk": [ "page_id" ]
+ },
+ "after": {
+ "name": "page",
+ "comment": "Core of the wiki: each page has an entry here which identifies it by title and contains some essential metadata.",
+ "columns": [
+ {
+ "name": "page_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "page_namespace",
+ "comment": "A page name is broken into a namespace and a title. The namespace keys are UI-language-independent constants, defined in includes/Defines.php",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_title",
+ "comment": "The rest of the title, as text. Spaces are transformed into underscores in title storage.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "page_is_redirect",
+ "comment": "1 indicates the article is a redirect.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_is_new",
+ "comment": "1 indicates this is a new entry, with only one edit. Not all pages with one edit are new pages.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_random",
+ "comment": "Random value between 0 and 1, used for Special:Randompage",
+ "type": "float",
+ "options": {
+ "notnull": true,
+ "unsigned": true,
+ "CustomSchemaOptions": {
+ "doublePrecision": true
+ }
+ }
+ },
+ {
+ "name": "page_touched",
+ "comment": "This timestamp is updated whenever the page changes in a way requiring it to be re-rendered, invalidating caches. Aside from editing this includes permission changes, creation or deletion of linked pages, and alteration of contained templates.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_links_updated",
+ "comment": "This timestamp is updated whenever a page is re-parsed and it has all the link tracking tables updated for it. This is useful for de-duplicating expensive backlink update jobs.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "page_latest",
+ "comment": "Handy key to revision.rev_id of the current revision. This may be 0 during page creation, but that shouldn't happen outside of a transaction... hopefully.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_len",
+ "comment": "Uncompressed length in bytes of the page's current source text.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_content_model",
+ "comment": "content model, see CONTENT_MODEL_XXX constants",
+ "type": "binary",
+ "options": { "length": 32, "notnull": false }
+ },
+ {
+ "name": "page_lang",
+ "comment": "Page content language",
+ "type": "binary",
+ "options": { "length": 35, "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "page_name_title",
+ "columns": [ "page_namespace", "page_title" ],
+ "comment": "The title index. Care must be taken to always specify a namespace when by title, so that the index is used. Even listing all known namespaces with IN() is better than omitting page_namespace from the WHERE clause.",
+ "unique": true
+ },
+ {
+ "name": "page_random",
+ "columns": [ "page_random" ],
+ "comment": "Index for Special:Random",
+ "unique": false
+ },
+ {
+ "name": "page_len",
+ "columns": [ "page_len" ],
+ "comment": "Questionable utility, used by ProofreadPage, possibly DynamicPageList. ApiQueryAllPages unconditionally filters on namespace and so hopefully does not use it.",
+ "unique": false
+ },
+ {
+ "name": "page_redirect_namespace_len",
+ "columns": [ "page_is_redirect", "page_namespace", "page_len" ],
+ "comment": "The index for Special:Shortpages and Special:Longpages. Also SiteStats::articles() in 'comma' counting mode, MessageCache::loadFromDB().",
+ "unique": false
+ }
+ ],
+ "pk": [ "page_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-page-page_links_updated-noinfinite.json b/sql/abstractSchemaChanges/patch-page-page_links_updated-noinfinite.json
new file mode 100644
index 000000000000..e716c63a77a6
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-page-page_links_updated-noinfinite.json
@@ -0,0 +1,234 @@
+{
+ "comment": "Remove allowInfinite from page_links_updated (T298317)",
+ "before": {
+ "name": "page",
+ "comment": "Core of the wiki: each page has an entry here which identifies it by title and contains some essential metadata.",
+ "columns": [
+ {
+ "name": "page_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "page_namespace",
+ "comment": "A page name is broken into a namespace and a title. The namespace keys are UI-language-independent constants, defined in includes/Defines.php",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_title",
+ "comment": "The rest of the title, as text. Spaces are transformed into underscores in title storage.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "page_is_redirect",
+ "comment": "1 indicates the article is a redirect. If so, there is a row in the `redirect` table with rd_from=page_id, which contains the redirect target.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_is_new",
+ "comment": "1 indicates this is a new entry, with only one edit. Not all pages with one edit are new pages.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_random",
+ "comment": "Random value between 0 and 1, used for Special:Randompage",
+ "type": "float",
+ "options": {
+ "notnull": true,
+ "unsigned": true,
+ "CustomSchemaOptions": {
+ "doublePrecision": true
+ }
+ }
+ },
+ {
+ "name": "page_touched",
+ "comment": "This timestamp is updated whenever the page changes in a way requiring it to be re-rendered, invalidating caches. Aside from editing this includes permission changes, creation or deletion of linked pages, and alteration of contained templates.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_links_updated",
+ "comment": "This timestamp is updated whenever a page is re-parsed and it has all the link tracking tables updated for it. This is useful for de-duplicating expensive backlink update jobs.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "page_latest",
+ "comment": "Handy key to revision.rev_id of the current revision. This may be 0 during page creation, but that shouldn't happen outside of a transaction... hopefully.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_len",
+ "comment": "Uncompressed length in bytes of the page's current source text.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_content_model",
+ "comment": "content model, see CONTENT_MODEL_XXX constants",
+ "type": "binary",
+ "options": { "length": 32, "notnull": false }
+ },
+ {
+ "name": "page_lang",
+ "comment": "Page content language",
+ "type": "binary",
+ "options": { "length": 35, "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "page_name_title",
+ "columns": [ "page_namespace", "page_title" ],
+ "comment": "The title index. Care must be taken to always specify a namespace when by title, so that the index is used. Even listing all known namespaces with IN() is better than omitting page_namespace from the WHERE clause.",
+ "unique": true
+ },
+ {
+ "name": "page_random",
+ "columns": [ "page_random" ],
+ "comment": "Index for Special:Random",
+ "unique": false
+ },
+ {
+ "name": "page_len",
+ "columns": [ "page_len" ],
+ "comment": "Questionable utility, used by ProofreadPage, possibly DynamicPageList. ApiQueryAllPages unconditionally filters on namespace and so hopefully does not use it.",
+ "unique": false
+ },
+ {
+ "name": "page_redirect_namespace_len",
+ "columns": [ "page_is_redirect", "page_namespace", "page_len" ],
+ "comment": "The index for Special:Shortpages and Special:Longpages. Also SiteStats::articles() in 'comma' counting mode, MessageCache::loadFromDB().",
+ "unique": false
+ }
+ ],
+ "pk": [ "page_id" ]
+ },
+ "after": {
+ "name": "page",
+ "comment": "Core of the wiki: each page has an entry here which identifies it by title and contains some essential metadata.",
+ "columns": [
+ {
+ "name": "page_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "page_namespace",
+ "comment": "A page name is broken into a namespace and a title. The namespace keys are UI-language-independent constants, defined in includes/Defines.php",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_title",
+ "comment": "The rest of the title, as text. Spaces are transformed into underscores in title storage.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "page_is_redirect",
+ "comment": "1 indicates the article is a redirect. If so, there is a row in the `redirect` table with rd_from=page_id, which contains the redirect target.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_is_new",
+ "comment": "1 indicates this is a new entry, with only one edit. Not all pages with one edit are new pages.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "page_random",
+ "comment": "Random value between 0 and 1, used for Special:Randompage",
+ "type": "float",
+ "options": {
+ "notnull": true,
+ "unsigned": true,
+ "CustomSchemaOptions": {
+ "doublePrecision": true
+ }
+ }
+ },
+ {
+ "name": "page_touched",
+ "comment": "This timestamp is updated whenever the page changes in a way requiring it to be re-rendered, invalidating caches. Aside from editing this includes permission changes, creation or deletion of linked pages, and alteration of contained templates.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_links_updated",
+ "comment": "This timestamp is updated whenever a page is re-parsed and it has all the link tracking tables updated for it. This is useful for de-duplicating expensive backlink update jobs.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "default": null
+ }
+ },
+ {
+ "name": "page_latest",
+ "comment": "Handy key to revision.rev_id of the current revision. This may be 0 during page creation, but that shouldn't happen outside of a transaction... hopefully.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_len",
+ "comment": "Uncompressed length in bytes of the page's current source text.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_content_model",
+ "comment": "content model, see CONTENT_MODEL_XXX constants",
+ "type": "binary",
+ "options": { "length": 32, "notnull": false }
+ },
+ {
+ "name": "page_lang",
+ "comment": "Page content language",
+ "type": "binary",
+ "options": { "length": 35, "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "page_name_title",
+ "columns": [ "page_namespace", "page_title" ],
+ "comment": "The title index. Care must be taken to always specify a namespace when by title, so that the index is used. Even listing all known namespaces with IN() is better than omitting page_namespace from the WHERE clause.",
+ "unique": true
+ },
+ {
+ "name": "page_random",
+ "columns": [ "page_random" ],
+ "comment": "Index for Special:Random",
+ "unique": false
+ },
+ {
+ "name": "page_len",
+ "columns": [ "page_len" ],
+ "comment": "Questionable utility, used by ProofreadPage, possibly DynamicPageList. ApiQueryAllPages unconditionally filters on namespace and so hopefully does not use it.",
+ "unique": false
+ },
+ {
+ "name": "page_redirect_namespace_len",
+ "columns": [ "page_is_redirect", "page_namespace", "page_len" ],
+ "comment": "The index for Special:Shortpages and Special:Longpages. Also SiteStats::articles() in 'comma' counting mode, MessageCache::loadFromDB().",
+ "unique": false
+ }
+ ],
+ "pk": [ "page_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-page-rename-name_title-index.json b/sql/abstractSchemaChanges/patch-page-rename-name_title-index.json
new file mode 100644
index 000000000000..728548199220
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-page-rename-name_title-index.json
@@ -0,0 +1,249 @@
+{
+ "comment": "Rename 'name_title' to have the page_ prefix (T270033)",
+ "before": {
+ "name": "page",
+ "comment": "Core of the wiki: each page has an entry here which identifies it by title and contains some essential metadata.",
+ "columns": [
+ {
+ "name": "page_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "page_namespace",
+ "comment": "A page name is broken into a namespace and a title. The namespace keys are UI-language-independent constants, defined in includes/Defines.php",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_title",
+ "comment": "The rest of the title, as text. Spaces are transformed into underscores in title storage.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "page_restrictions",
+ "comment": "Comma-separated set of permission keys indicating who can move or edit the page.",
+ "type": "blob",
+ "options": { "notnull": false, "length": 255 }
+ },
+ {
+ "name": "page_is_redirect",
+ "comment": "1 indicates the article is a redirect.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "page_is_new",
+ "comment": "1 indicates this is a new entry, with only one edit. Not all pages with one edit are new pages.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "page_random",
+ "comment": "Random value between 0 and 1, used for Special:Randompage",
+ "type": "float",
+ "options": {
+ "notnull": true,
+ "unsigned": true,
+ "CustomSchemaOptions": {
+ "doublePrecision": true
+ }
+ }
+ },
+ {
+ "name": "page_touched",
+ "comment": "This timestamp is updated whenever the page changes in a way requiring it to be re-rendered, invalidating caches. Aside from editing this includes permission changes, creation or deletion of linked pages, and alteration of contained templates.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_links_updated",
+ "comment": "This timestamp is updated whenever a page is re-parsed and it has all the link tracking tables updated for it. This is useful for de-duplicating expensive backlink update jobs.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "page_latest",
+ "comment": "Handy key to revision.rev_id of the current revision. This may be 0 during page creation, but that shouldn't happen outside of a transaction... hopefully.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_len",
+ "comment": "Uncompressed length in bytes of the page's current source text.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_content_model",
+ "comment": "content model, see CONTENT_MODEL_XXX constants",
+ "type": "binary",
+ "options": { "length": 32, "notnull": false }
+ },
+ {
+ "name": "page_lang",
+ "comment": "Page content language",
+ "type": "binary",
+ "options": { "length": 35, "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "name_title",
+ "columns": [ "page_namespace", "page_title" ],
+ "comment": "The title index. Care must be taken to always specify a namespace when by title, so that the index is used. Even listing all known namespaces with IN() is better than omitting page_namespace from the WHERE clause.",
+ "unique": true
+ },
+ {
+ "name": "page_random",
+ "columns": [ "page_random" ],
+ "comment": "Index for Special:Random",
+ "unique": false
+ },
+ {
+ "name": "page_len",
+ "columns": [ "page_len" ],
+ "comment": "Questionable utility, used by ProofreadPage, possibly DynamicPageList. ApiQueryAllPages unconditionally filters on namespace and so hopefully does not use it.",
+ "unique": false
+ },
+ {
+ "name": "page_redirect_namespace_len",
+ "columns": [ "page_is_redirect", "page_namespace", "page_len" ],
+ "comment": "The index for Special:Shortpages and Special:Longpages. Also SiteStats::articles() in 'comma' counting mode, MessageCache::loadFromDB().",
+ "unique": false
+ }
+ ],
+ "pk": [ "page_id" ]
+ },
+ "after": {
+ "name": "page",
+ "comment": "Core of the wiki: each page has an entry here which identifies it by title and contains some essential metadata.",
+ "columns": [
+ {
+ "name": "page_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "page_namespace",
+ "comment": "A page name is broken into a namespace and a title. The namespace keys are UI-language-independent constants, defined in includes/Defines.php",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_title",
+ "comment": "The rest of the title, as text. Spaces are transformed into underscores in title storage.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "page_restrictions",
+ "comment": "Comma-separated set of permission keys indicating who can move or edit the page.",
+ "type": "blob",
+ "options": { "notnull": false, "length": 255 }
+ },
+ {
+ "name": "page_is_redirect",
+ "comment": "1 indicates the article is a redirect.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "page_is_new",
+ "comment": "1 indicates this is a new entry, with only one edit. Not all pages with one edit are new pages.",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "page_random",
+ "comment": "Random value between 0 and 1, used for Special:Randompage",
+ "type": "float",
+ "options": {
+ "notnull": true,
+ "unsigned": true,
+ "CustomSchemaOptions": {
+ "doublePrecision": true
+ }
+ }
+ },
+ {
+ "name": "page_touched",
+ "comment": "This timestamp is updated whenever the page changes in a way requiring it to be re-rendered, invalidating caches. Aside from editing this includes permission changes, creation or deletion of linked pages, and alteration of contained templates.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "page_links_updated",
+ "comment": "This timestamp is updated whenever a page is re-parsed and it has all the link tracking tables updated for it. This is useful for de-duplicating expensive backlink update jobs.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "page_latest",
+ "comment": "Handy key to revision.rev_id of the current revision. This may be 0 during page creation, but that shouldn't happen outside of a transaction... hopefully.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_len",
+ "comment": "Uncompressed length in bytes of the page's current source text.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "page_content_model",
+ "comment": "content model, see CONTENT_MODEL_XXX constants",
+ "type": "binary",
+ "options": { "length": 32, "notnull": false }
+ },
+ {
+ "name": "page_lang",
+ "comment": "Page content language",
+ "type": "binary",
+ "options": { "length": 35, "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "page_name_title",
+ "columns": [ "page_namespace", "page_title" ],
+ "comment": "The title index. Care must be taken to always specify a namespace when by title, so that the index is used. Even listing all known namespaces with IN() is better than omitting page_namespace from the WHERE clause.",
+ "unique": true
+ },
+ {
+ "name": "page_random",
+ "columns": [ "page_random" ],
+ "comment": "Index for Special:Random",
+ "unique": false
+ },
+ {
+ "name": "page_len",
+ "columns": [ "page_len" ],
+ "comment": "Questionable utility, used by ProofreadPage, possibly DynamicPageList. ApiQueryAllPages unconditionally filters on namespace and so hopefully does not use it.",
+ "unique": false
+ },
+ {
+ "name": "page_redirect_namespace_len",
+ "columns": [ "page_is_redirect", "page_namespace", "page_len" ],
+ "comment": "The index for Special:Shortpages and Special:Longpages. Also SiteStats::articles() in 'comma' counting mode, MessageCache::loadFromDB().",
+ "unique": false
+ }
+ ],
+ "pk": [ "page_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-page_props-pp_page.json b/sql/abstractSchemaChanges/patch-page_props-pp_page.json
new file mode 100644
index 000000000000..e3c70fd3696f
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-page_props-pp_page.json
@@ -0,0 +1,65 @@
+{
+ "comment": "Set unsigned true for pp_page in page_props table",
+ "before": {
+ "name": "page_props",
+ "comment": "Name/value pairs indexed by page_id",
+ "columns": [
+ {
+ "name": "pp_page",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pp_propname",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pp_value",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "pp_sortkey",
+ "type": "float",
+ "options": { "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "pp_propname_page", "columns": [ "pp_propname", "pp_page" ], "unique": true },
+ { "name": "pp_propname_sortkey_page", "columns": [ "pp_propname", "pp_sortkey", "pp_page" ], "unique": true, "options": { "where": "(pp_sortkey IS NOT NULL)" } }
+ ],
+ "pk": [ "pp_page", "pp_propname" ]
+ },
+ "after": {
+ "name": "page_props",
+ "comment": "Name/value pairs indexed by page_id",
+ "columns": [
+ {
+ "name": "pp_page",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "pp_propname",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pp_value",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": true }
+ },
+ {
+ "name": "pp_sortkey",
+ "type": "float",
+ "options": { "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "pp_propname_page", "columns": [ "pp_propname", "pp_page" ], "unique": true },
+ { "name": "pp_propname_sortkey_page", "columns": [ "pp_propname", "pp_sortkey", "pp_page" ], "unique": true, "options": { "where": "(pp_sortkey IS NOT NULL)" } }
+ ],
+ "pk": [ "pp_page", "pp_propname" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-page_restrictions-pr_page.json b/sql/abstractSchemaChanges/patch-page_restrictions-pr_page.json
new file mode 100644
index 000000000000..e9b2b9c30b53
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-page_restrictions-pr_page.json
@@ -0,0 +1,109 @@
+{
+ "comment": "Set unsigned true for pr_page in page_restrictions table",
+ "before": {
+ "name": "page_restrictions",
+ "comment": "Used for storing page restrictions (i.e. protection levels)",
+ "columns": [
+ {
+ "name": "pr_id",
+ "comment": "Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "pr_page",
+ "comment": "Page to apply restrictions to (Foreign Key to page).",
+ "type": "integer",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_type",
+ "comment": "The protection type (edit, move, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_level",
+ "comment": "The protection level (Sysop, autoconfirmed, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_cascade",
+ "type": "mwtinyint",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_expiry",
+ "comment": "Field for time-limited protection.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "pr_pagetype", "columns": [ "pr_page", "pr_type" ], "unique": true },
+ { "name": "pr_typelevel", "columns": [ "pr_type", "pr_level" ], "unique": false },
+ { "name": "pr_level", "columns": [ "pr_level" ], "unique": false },
+ { "name": "pr_cascade", "columns": [ "pr_cascade" ], "unique": false }
+ ],
+ "pk": [ "pr_id" ]
+ },
+ "after": {
+ "name": "page_restrictions",
+ "comment": "Used for storing page restrictions (i.e. protection levels)",
+ "columns": [
+ {
+ "name": "pr_id",
+ "comment": "Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "pr_page",
+ "comment": "Page to apply restrictions to (Foreign Key to page).",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "pr_type",
+ "comment": "The protection type (edit, move, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_level",
+ "comment": "The protection level (Sysop, autoconfirmed, etc)",
+ "type": "binary",
+ "options": { "length": 60, "notnull": true }
+ },
+ {
+ "name": "pr_cascade",
+ "type": "mwtinyint",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "pr_expiry",
+ "comment": "Field for time-limited protection.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "pr_pagetype", "columns": [ "pr_page", "pr_type" ], "unique": true },
+ { "name": "pr_typelevel", "columns": [ "pr_type", "pr_level" ], "unique": false },
+ { "name": "pr_level", "columns": [ "pr_level" ], "unique": false },
+ { "name": "pr_cascade", "columns": [ "pr_cascade" ], "unique": false }
+ ],
+ "pk": [ "pr_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-pagelinks-drop-pl_title.json b/sql/abstractSchemaChanges/patch-pagelinks-drop-pl_title.json
new file mode 100644
index 000000000000..a316c173255e
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-pagelinks-drop-pl_title.json
@@ -0,0 +1,103 @@
+{
+ "comment": "Drop old pagelinks columns (T299947)",
+ "before": {
+ "name": "pagelinks",
+ "comment": "Track page-to-page hyperlinks within the wiki. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "pl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "pl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "pl_title",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "pl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for pl_from page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "pl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": false, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "pl_namespace",
+ "columns": [ "pl_namespace", "pl_title", "pl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "pl_backlinks_namespace",
+ "columns": [ "pl_from_namespace", "pl_namespace", "pl_title", "pl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ },
+ {
+ "name": "pl_target_id",
+ "columns": [ "pl_target_id", "pl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "pl_backlinks_namespace_target_id",
+ "columns": [ "pl_from_namespace", "pl_target_id", "pl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "pl_from", "pl_namespace", "pl_title" ]
+ },
+ "after": {
+ "name": "pagelinks",
+ "comment": "Track page-to-page hyperlinks within the wiki. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "pl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "pl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for pl_from page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "pl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": false, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "pl_target_id",
+ "columns": [ "pl_target_id", "pl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "pl_backlinks_namespace_target_id",
+ "columns": [ "pl_from_namespace", "pl_target_id", "pl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "pl_from", "pl_target_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-pagelinks-target_id.json b/sql/abstractSchemaChanges/patch-pagelinks-target_id.json
new file mode 100644
index 000000000000..2c32b6fa1160
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-pagelinks-target_id.json
@@ -0,0 +1,107 @@
+{
+ "comment": "Add tl_target_id on pagelinks (T299947)",
+ "before": {
+ "name": "pagelinks",
+ "comment": "Track page-to-page hyperlinks within the wiki. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "pl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "pl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "pl_title",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "pl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for pl_from page",
+ "options": { "notnull": true, "default": 0 }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "pl_namespace",
+ "columns": [ "pl_namespace", "pl_title", "pl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "pl_backlinks_namespace",
+ "columns": [ "pl_from_namespace", "pl_namespace", "pl_title", "pl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "pl_from", "pl_namespace", "pl_title" ]
+ },
+ "after": {
+ "name": "pagelinks",
+ "comment": "Track page-to-page hyperlinks within the wiki. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "pl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "pl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "pl_title",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "pl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for pl_from page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "pl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": false, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "pl_namespace",
+ "columns": [ "pl_namespace", "pl_title", "pl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "pl_backlinks_namespace",
+ "columns": [ "pl_from_namespace", "pl_namespace", "pl_title", "pl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ },
+ {
+ "name": "pl_target_id",
+ "columns": [ "pl_target_id", "pl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "pl_backlinks_namespace_target_id",
+ "columns": [ "pl_from_namespace", "pl_target_id", "pl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "pl_from", "pl_namespace", "pl_title" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-recentchanges-rc_id-bigint.json b/sql/abstractSchemaChanges/patch-recentchanges-rc_id-bigint.json
new file mode 100644
index 000000000000..e8dc8a06f1be
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-recentchanges-rc_id-bigint.json
@@ -0,0 +1,618 @@
+{
+ "before": {
+ "name": "recentchanges",
+ "comment": "Primarily a summary table for Special:RecentChanges, this table contains some additional info on edits from the last few days",
+ "columns": [
+ {
+ "name": "rc_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_actor",
+ "comment": "As in revision",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_namespace",
+ "comment": "When pages are renamed, their RC entries do _not_ change.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_title",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_comment_id",
+ "comment": "as in revision...",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_minor",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_bot",
+ "comment": "Edits by user accounts with the 'bot' rights key are marked with a 1 here, and will be hidden from the default view.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_new",
+ "comment": "Set if this change corresponds to a page creation",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Key to page_id (was cur_id prior to 1.5). This will keep links working after moves while retaining the at-the-time name in the changes list.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "rev_id of the given revision",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_last_oldid",
+ "comment": "rev_id of the prior revision, for generating diff links.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_type",
+ "comment": "The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_source",
+ "comment": "The source of the change entry (replaces rc_type) default of '' is temporary, needed for initial migration",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 16
+ }
+ },
+ {
+ "name": "rc_patrolled",
+ "comment": "If the Recent Changes Patrol option is enabled, users may mark edits as having been reviewed to remove a warning flag on the RC list. A value of 1 indicates the page has been reviewed.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Recorded IP address the edit was made from, if the $wgPutIPinRC option is enabled.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 40
+ }
+ },
+ {
+ "name": "rc_old_len",
+ "comment": "Text length in characters before the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_new_len",
+ "comment": "Text length in characters after the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_deleted",
+ "comment": "Visibility of recent changes items, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_logid",
+ "comment": "Value corresponding to log_id, specific log entries",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_log_type",
+ "comment": "Store log type info here, or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_log_action",
+ "comment": "Store log action or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_params",
+ "comment": "Log params",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65535
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rc_timestamp",
+ "comment": "Special:Recentchanges",
+ "columns": [
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_namespace_title_timestamp",
+ "comment": "Special:Watchlist",
+ "columns": [
+ "rc_namespace",
+ "rc_title",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Special:Recentchangeslinked when finding changes in pages linked from a page",
+ "columns": [
+ "rc_cur_id"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_new_name_timestamp",
+ "comment": "Special:Newpages",
+ "columns": [
+ "rc_new",
+ "rc_namespace",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Blank unless $wgPutIPinRC=true (false at WMF), possibly used by extensions, but mostly replaced by CheckUser.",
+ "columns": [
+ "rc_ip"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ns_actor",
+ "comment": "Probably intended for Special:NewPages namespace filter",
+ "columns": [
+ "rc_namespace",
+ "rc_actor"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_actor",
+ "comment": "SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter",
+ "columns": [
+ "rc_actor",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_name_type_patrolled_timestamp",
+ "comment": "ApiQueryRecentChanges (T140108)",
+ "columns": [
+ "rc_namespace",
+ "rc_type",
+ "rc_patrolled",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "Article.php and friends (T139012)",
+ "columns": [
+ "rc_this_oldid"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "rc_id"
+ ]
+ },
+ "after": {
+ "name": "recentchanges",
+ "comment": "Primarily a summary table for Special:RecentChanges, this table contains some additional info on edits from the last few days",
+ "columns": [
+ {
+ "name": "rc_id",
+ "type": "bigint",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_actor",
+ "comment": "As in revision",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_namespace",
+ "comment": "When pages are renamed, their RC entries do _not_ change.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_title",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_comment_id",
+ "comment": "as in revision...",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_minor",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_bot",
+ "comment": "Edits by user accounts with the 'bot' rights key are marked with a 1 here, and will be hidden from the default view.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_new",
+ "comment": "Set if this change corresponds to a page creation",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Key to page_id (was cur_id prior to 1.5). This will keep links working after moves while retaining the at-the-time name in the changes list.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "rev_id of the given revision",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_last_oldid",
+ "comment": "rev_id of the prior revision, for generating diff links.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_type",
+ "comment": "The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_source",
+ "comment": "The source of the change entry (replaces rc_type) default of '' is temporary, needed for initial migration",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 16
+ }
+ },
+ {
+ "name": "rc_patrolled",
+ "comment": "If the Recent Changes Patrol option is enabled, users may mark edits as having been reviewed to remove a warning flag on the RC list. A value of 1 indicates the page has been reviewed.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Recorded IP address the edit was made from, if the $wgPutIPinRC option is enabled.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 40
+ }
+ },
+ {
+ "name": "rc_old_len",
+ "comment": "Text length in characters before the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_new_len",
+ "comment": "Text length in characters after the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_deleted",
+ "comment": "Visibility of recent changes items, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_logid",
+ "comment": "Value corresponding to log_id, specific log entries",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_log_type",
+ "comment": "Store log type info here, or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_log_action",
+ "comment": "Store log action or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_params",
+ "comment": "Log params",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65535
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rc_timestamp",
+ "comment": "Special:Recentchanges",
+ "columns": [
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_namespace_title_timestamp",
+ "comment": "Special:Watchlist",
+ "columns": [
+ "rc_namespace",
+ "rc_title",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Special:Recentchangeslinked when finding changes in pages linked from a page",
+ "columns": [
+ "rc_cur_id"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_new_name_timestamp",
+ "comment": "Special:Newpages",
+ "columns": [
+ "rc_new",
+ "rc_namespace",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Blank unless $wgPutIPinRC=true (false at WMF), possibly used by extensions, but mostly replaced by CheckUser.",
+ "columns": [
+ "rc_ip"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ns_actor",
+ "comment": "Probably intended for Special:NewPages namespace filter",
+ "columns": [
+ "rc_namespace",
+ "rc_actor"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_actor",
+ "comment": "SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter",
+ "columns": [
+ "rc_actor",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_name_type_patrolled_timestamp",
+ "comment": "ApiQueryRecentChanges (T140108)",
+ "columns": [
+ "rc_namespace",
+ "rc_type",
+ "rc_patrolled",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "Article.php and friends (T139012)",
+ "columns": [
+ "rc_this_oldid"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "rc_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-recentchanges-rc_id.json b/sql/abstractSchemaChanges/patch-recentchanges-rc_id.json
new file mode 100644
index 000000000000..975a45e46f51
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-recentchanges-rc_id.json
@@ -0,0 +1,620 @@
+{
+ "comment": "Set unsigned true for rc_id in recentchanges table (T62962)",
+ "before": {
+ "name": "recentchanges",
+ "comment": "Primarily a summary table for Special:RecentChanges, this table contains some additional info on edits from the last few days",
+ "columns": [
+ {
+ "name": "rc_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "length": 14
+ }
+ },
+ {
+ "name": "rc_actor",
+ "comment": "As in revision",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_namespace",
+ "comment": "When pages are renamed, their RC entries do _not_ change.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_title",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_comment_id",
+ "comment": "as in revision...",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_minor",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_bot",
+ "comment": "Edits by user accounts with the 'bot' rights key are marked with a 1 here, and will be hidden from the default view.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_new",
+ "comment": "Set if this change corresponds to a page creation",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Key to page_id (was cur_id prior to 1.5). This will keep links working after moves while retaining the at-the-time name in the changes list.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "rev_id of the given revision",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_last_oldid",
+ "comment": "rev_id of the prior revision, for generating diff links.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_type",
+ "comment": "The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_source",
+ "comment": "The source of the change entry (replaces rc_type) default of '' is temporary, needed for initial migration",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 16
+ }
+ },
+ {
+ "name": "rc_patrolled",
+ "comment": "If the Recent Changes Patrol option is enabled, users may mark edits as having been reviewed to remove a warning flag on the RC list. A value of 1 indicates the page has been reviewed.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Recorded IP address the edit was made from, if the $wgPutIPinRC option is enabled.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 40
+ }
+ },
+ {
+ "name": "rc_old_len",
+ "comment": "Text length in characters before the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_new_len",
+ "comment": "Text length in characters after the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_deleted",
+ "comment": "Visibility of recent changes items, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_logid",
+ "comment": "Value corresponding to log_id, specific log entries",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_log_type",
+ "comment": "Store log type info here, or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_log_action",
+ "comment": "Store log action or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_params",
+ "comment": "Log params",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65535
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rc_timestamp",
+ "comment": "Special:Recentchanges",
+ "columns": [
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_namespace_title_timestamp",
+ "comment": "Special:Watchlist",
+ "columns": [
+ "rc_namespace",
+ "rc_title",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Special:Recentchangeslinked when finding changes in pages linked from a page",
+ "columns": [
+ "rc_cur_id"
+ ],
+ "unique": false
+ },
+ {
+ "name": "new_name_timestamp",
+ "comment": "Special:Newpages",
+ "columns": [
+ "rc_new",
+ "rc_namespace",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Blank unless $wgPutIPinRC=true (false at WMF), possibly used by extensions, but mostly replaced by CheckUser.",
+ "columns": [
+ "rc_ip"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ns_actor",
+ "comment": "Probably intended for Special:NewPages namespace filter",
+ "columns": [
+ "rc_namespace",
+ "rc_actor"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_actor",
+ "comment": "SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter",
+ "columns": [
+ "rc_actor",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_name_type_patrolled_timestamp",
+ "comment": "ApiQueryRecentChanges (T140108)",
+ "columns": [
+ "rc_namespace",
+ "rc_type",
+ "rc_patrolled",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "Article.php and friends (T139012)",
+ "columns": [
+ "rc_this_oldid"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "rc_id"
+ ]
+ },
+ "after": {
+ "name": "recentchanges",
+ "comment": "Primarily a summary table for Special:Recentchanges, this table contains some additional info on edits from the last few days, see Article::editUpdates()",
+ "columns": [
+ {
+ "name": "rc_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "length": 14
+ }
+ },
+ {
+ "name": "rc_actor",
+ "comment": "As in revision",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_namespace",
+ "comment": "When pages are renamed, their RC entries do _not_ change.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_title",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_comment_id",
+ "comment": "as in revision...",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_minor",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_bot",
+ "comment": "Edits by user accounts with the 'bot' rights key are marked with a 1 here, and will be hidden from the default view.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_new",
+ "comment": "Set if this change corresponds to a page creation",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Key to page_id (was cur_id prior to 1.5). This will keep links working after moves while retaining the at-the-time name in the changes list.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "rev_id of the given revision",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_last_oldid",
+ "comment": "rev_id of the prior revision, for generating diff links.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_type",
+ "comment": "The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_source",
+ "comment": "The source of the change entry (replaces rc_type) default of '' is temporary, needed for initial migration",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 16
+ }
+ },
+ {
+ "name": "rc_patrolled",
+ "comment": "If the Recent Changes Patrol option is enabled, users may mark edits as having been reviewed to remove a warning flag on the RC list. A value of 1 indicates the page has been reviewed.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Recorded IP address the edit was made from, if the $wgPutIPinRC option is enabled.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 40
+ }
+ },
+ {
+ "name": "rc_old_len",
+ "comment": "Text length in characters before the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_new_len",
+ "comment": "Text length in characters after the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_deleted",
+ "comment": "Visibility of recent changes items, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_logid",
+ "comment": "Value corresponding to log_id, specific log entries",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_log_type",
+ "comment": "Store log type info here, or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_log_action",
+ "comment": "Store log action or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_params",
+ "comment": "Log params",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65535
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rc_timestamp",
+ "comment": "Special:Recentchanges",
+ "columns": [
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_namespace_title_timestamp",
+ "comment": "Special:Watchlist",
+ "columns": [
+ "rc_namespace",
+ "rc_title",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Special:Recentchangeslinked when finding changes in pages linked from a page",
+ "columns": [
+ "rc_cur_id"
+ ],
+ "unique": false
+ },
+ {
+ "name": "new_name_timestamp",
+ "comment": "Special:Newpages",
+ "columns": [
+ "rc_new",
+ "rc_namespace",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Blank unless $wgPutIPinRC=true (false at WMF), possibly used by extensions, but mostly replaced by CheckUser.",
+ "columns": [
+ "rc_ip"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ns_actor",
+ "comment": "Probably intended for Special:NewPages namespace filter",
+ "columns": [
+ "rc_namespace",
+ "rc_actor"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_actor",
+ "comment": "SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter",
+ "columns": [
+ "rc_actor",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_name_type_patrolled_timestamp",
+ "comment": "ApiQueryRecentChanges (T140108)",
+ "columns": [
+ "rc_namespace",
+ "rc_type",
+ "rc_patrolled",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "Article.php and friends (T139012)",
+ "columns": [
+ "rc_this_oldid"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "rc_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-recentchanges-rc_new_name_timestamp.json b/sql/abstractSchemaChanges/patch-recentchanges-rc_new_name_timestamp.json
new file mode 100644
index 000000000000..acae5e199049
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-recentchanges-rc_new_name_timestamp.json
@@ -0,0 +1,621 @@
+{
+ "comment": "Renaming new_name_timestamp index on recentchanges to rc_new_name_timestamp (T270033)",
+ "before": {
+ "name": "recentchanges",
+ "comment": "Primarily a summary table for Special:Recentchanges, this table contains some additional info on edits from the last few days, see Article::editUpdates()",
+ "columns": [
+ {
+ "name": "rc_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "length": 14
+ }
+ },
+ {
+ "name": "rc_actor",
+ "comment": "As in revision",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_namespace",
+ "comment": "When pages are renamed, their RC entries do _not_ change.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_title",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_comment_id",
+ "comment": "as in revision...",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_minor",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_bot",
+ "comment": "Edits by user accounts with the 'bot' rights key are marked with a 1 here, and will be hidden from the default view.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_new",
+ "comment": "Set if this change corresponds to a page creation",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Key to page_id (was cur_id prior to 1.5). This will keep links working after moves while retaining the at-the-time name in the changes list.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "rev_id of the given revision",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_last_oldid",
+ "comment": "rev_id of the prior revision, for generating diff links.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_type",
+ "comment": "The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_source",
+ "comment": "The source of the change entry (replaces rc_type) default of '' is temporary, needed for initial migration",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 16
+ }
+ },
+ {
+ "name": "rc_patrolled",
+ "comment": "If the Recent Changes Patrol option is enabled, users may mark edits as having been reviewed to remove a warning flag on the RC list. A value of 1 indicates the page has been reviewed.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Recorded IP address the edit was made from, if the $wgPutIPinRC option is enabled.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 40
+ }
+ },
+ {
+ "name": "rc_old_len",
+ "comment": "Text length in characters before the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_new_len",
+ "comment": "Text length in characters after the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_deleted",
+ "comment": "Visibility of recent changes items, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_logid",
+ "comment": "Value corresponding to log_id, specific log entries",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_log_type",
+ "comment": "Store log type info here, or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_log_action",
+ "comment": "Store log action or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_params",
+ "comment": "Log params",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65535
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rc_timestamp",
+ "comment": "Special:Recentchanges",
+ "columns": [
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_namespace_title_timestamp",
+ "comment": "Special:Watchlist",
+ "columns": [
+ "rc_namespace",
+ "rc_title",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Special:Recentchangeslinked when finding changes in pages linked from a page",
+ "columns": [
+ "rc_cur_id"
+ ],
+ "unique": false
+ },
+ {
+ "name": "new_name_timestamp",
+ "comment": "Special:Newpages",
+ "columns": [
+ "rc_new",
+ "rc_namespace",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Blank unless $wgPutIPinRC=true (false at WMF), possibly used by extensions, but mostly replaced by CheckUser.",
+ "columns": [
+ "rc_ip"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ns_actor",
+ "comment": "Probably intended for Special:NewPages namespace filter",
+ "columns": [
+ "rc_namespace",
+ "rc_actor"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_actor",
+ "comment": "SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter",
+ "columns": [
+ "rc_actor",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_name_type_patrolled_timestamp",
+ "comment": "ApiQueryRecentChanges (T140108)",
+ "columns": [
+ "rc_namespace",
+ "rc_type",
+ "rc_patrolled",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "Article.php and friends (T139012)",
+ "columns": [
+ "rc_this_oldid"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "rc_id"
+ ]
+ },
+ "after": {
+ "name": "recentchanges",
+ "comment": "Primarily a summary table for Special:RecentChanges, this table contains some additional info on edits from the last few days",
+ "columns": [
+ {
+ "name": "rc_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_timestamp",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true,
+ "length": 14
+ }
+ },
+ {
+ "name": "rc_actor",
+ "comment": "As in revision",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_namespace",
+ "comment": "When pages are renamed, their RC entries do _not_ change.",
+ "type": "integer",
+ "options": {
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_title",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_comment_id",
+ "comment": "as in revision...",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "rc_minor",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_bot",
+ "comment": "Edits by user accounts with the 'bot' rights key are marked with a 1 here, and will be hidden from the default view.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_new",
+ "comment": "Set if this change corresponds to a page creation",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Key to page_id (was cur_id prior to 1.5). This will keep links working after moves while retaining the at-the-time name in the changes list.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "rev_id of the given revision",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_last_oldid",
+ "comment": "rev_id of the prior revision, for generating diff links.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_type",
+ "comment": "The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_source",
+ "comment": "The source of the change entry (replaces rc_type) default of '' is temporary, needed for initial migration",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 16
+ }
+ },
+ {
+ "name": "rc_patrolled",
+ "comment": "If the Recent Changes Patrol option is enabled, users may mark edits as having been reviewed to remove a warning flag on the RC list. A value of 1 indicates the page has been reviewed.",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Recorded IP address the edit was made from, if the $wgPutIPinRC option is enabled.",
+ "type": "binary",
+ "options": {
+ "notnull": true,
+ "default": "",
+ "length": 40
+ }
+ },
+ {
+ "name": "rc_old_len",
+ "comment": "Text length in characters before the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_new_len",
+ "comment": "Text length in characters after the edit",
+ "type": "integer",
+ "options": {
+ "notnull": false
+ }
+ },
+ {
+ "name": "rc_deleted",
+ "comment": "Visibility of recent changes items, bitfield",
+ "type": "mwtinyint",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_logid",
+ "comment": "Value corresponding to log_id, specific log entries",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true,
+ "default": 0
+ }
+ },
+ {
+ "name": "rc_log_type",
+ "comment": "Store log type info here, or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_log_action",
+ "comment": "Store log action or null",
+ "type": "binary",
+ "options": {
+ "notnull": false,
+ "default": null,
+ "length": 255
+ }
+ },
+ {
+ "name": "rc_params",
+ "comment": "Log params",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65535
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rc_timestamp",
+ "comment": "Special:Recentchanges",
+ "columns": [
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_namespace_title_timestamp",
+ "comment": "Special:Watchlist",
+ "columns": [
+ "rc_namespace",
+ "rc_title",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_cur_id",
+ "comment": "Special:Recentchangeslinked when finding changes in pages linked from a page",
+ "columns": [
+ "rc_cur_id"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_new_name_timestamp",
+ "comment": "Special:Newpages",
+ "columns": [
+ "rc_new",
+ "rc_namespace",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ip",
+ "comment": "Blank unless $wgPutIPinRC=true (false at WMF), possibly used by extensions, but mostly replaced by CheckUser.",
+ "columns": [
+ "rc_ip"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_ns_actor",
+ "comment": "Probably intended for Special:NewPages namespace filter",
+ "columns": [
+ "rc_namespace",
+ "rc_actor"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_actor",
+ "comment": "SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter",
+ "columns": [
+ "rc_actor",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_name_type_patrolled_timestamp",
+ "comment": "ApiQueryRecentChanges (T140108)",
+ "columns": [
+ "rc_namespace",
+ "rc_type",
+ "rc_patrolled",
+ "rc_timestamp"
+ ],
+ "unique": false
+ },
+ {
+ "name": "rc_this_oldid",
+ "comment": "Article.php and friends (T139012)",
+ "columns": [
+ "rc_this_oldid"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "rc_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-revision-cleanup.json b/sql/abstractSchemaChanges/patch-revision-cleanup.json
new file mode 100644
index 000000000000..1c24e7070623
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-revision-cleanup.json
@@ -0,0 +1,188 @@
+{
+ "before": {
+ "name": "revision",
+ "comment": "Every edit of a page creates also a revision row. This stores metadata about the revision, and a reference to the text storage backend.",
+ "columns": [
+ {
+ "name": "rev_id",
+ "comment": "Unique ID to identify each revision",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "rev_page",
+ "comment": "Key to page_id. This should never be invalid",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_comment_id",
+ "comment": "Key to comment.comment_id. Comment summarizing the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_actor",
+ "comment": "Key to actor.actor_id of the user or IP who made this edit",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_timestamp",
+ "comment": "Timestamp of when revision was created",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "rev_minor_edit",
+ "comment": "Records whether the user marked the 'minor edit' checkbox. Many automated edits are marked as minor",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_deleted",
+ "comment": "Restrictions on who can access this revision",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_len",
+ "comment": "Length of this revision in bytes",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_parent_id",
+ "comment": "Key to revision.rev_id. This field is used to add support for a tree structure (The Adjacency List Model)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_sha1",
+ "comment": "SHA-1 text content hash in base-36",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rev_timestamp",
+ "columns": [ "rev_timestamp" ],
+ "comment": "Used by ApiQueryAllRevisions",
+ "unique": false
+ },
+ {
+ "name": "rev_page_timestamp",
+ "columns": [ "rev_page", "rev_timestamp" ],
+ "comment": "History index",
+ "unique": false
+ },
+ {
+ "name": "rev_actor_timestamp",
+ "columns": [ "rev_actor", "rev_timestamp", "rev_id" ],
+ "comment": "User contributions index",
+ "unique": false
+ },
+ {
+ "name": "rev_page_actor_timestamp",
+ "columns": [ "rev_page", "rev_actor", "rev_timestamp" ],
+ "comment": "Credits index. This is scanned in order to compile credits lists for pages, in ApiQueryContributors. Also for ApiQueryRevisions if rvuser is specified",
+ "unique": false
+ }
+ ],
+ "pk": [ "rev_id" ]
+ },
+ "after": {
+ "name": "revision",
+ "comment": "Every edit of a page creates also a revision row. This stores metadata about the revision, and a reference to the text storage backend.",
+ "columns": [
+ {
+ "name": "rev_id",
+ "comment": "Unique ID to identify each revision",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "rev_page",
+ "comment": "Key to page_id. This should never be invalid",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_comment_id",
+ "comment": "Key to comment.comment_id. Comment summarizing the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_actor",
+ "comment": "Key to actor.actor_id of the user or IP who made this edit",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_timestamp",
+ "comment": "Timestamp of when revision was created",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "rev_minor_edit",
+ "comment": "Records whether the user marked the 'minor edit' checkbox. Many automated edits are marked as minor",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_deleted",
+ "comment": "Restrictions on who can access this revision",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_len",
+ "comment": "Length of this revision in bytes",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_parent_id",
+ "comment": "Key to revision.rev_id. This field is used to add support for a tree structure (The Adjacency List Model)",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_sha1",
+ "comment": "SHA-1 text content hash in base-36",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rev_timestamp",
+ "columns": [ "rev_timestamp" ],
+ "comment": "Used by ApiQueryAllRevisions",
+ "unique": false
+ },
+ {
+ "name": "rev_page_timestamp",
+ "columns": [ "rev_page", "rev_timestamp" ],
+ "comment": "History index",
+ "unique": false
+ },
+ {
+ "name": "rev_actor_timestamp",
+ "columns": [ "rev_actor", "rev_timestamp", "rev_id" ],
+ "comment": "User contributions index",
+ "unique": false
+ },
+ {
+ "name": "rev_page_actor_timestamp",
+ "columns": [ "rev_page", "rev_actor", "rev_timestamp" ],
+ "comment": "Credits index. This is scanned in order to compile credits lists for pages, in ApiQueryContributors. Also for ApiQueryRevisions if rvuser is specified",
+ "unique": false
+ }
+ ],
+ "pk": [ "rev_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-revision-rename-index.json b/sql/abstractSchemaChanges/patch-revision-rename-index.json
new file mode 100644
index 000000000000..db31878545f8
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-revision-rename-index.json
@@ -0,0 +1,203 @@
+{
+ "comment": "Rename page_timestamp index to have 'rev_' prefix (T270033)",
+ "before": {
+ "name": "revision",
+ "comment": "Every edit of a page creates also a revision row. This stores metadata about the revision, and a reference to the text storage backend.",
+ "columns": [
+ {
+ "name": "rev_id",
+ "comment": "Unique ID to identify each revision",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "rev_page",
+ "comment": "Key to page_id. This should never be invalid",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_comment_id",
+ "comment": "Key to comment.comment_id. Comment summarizing the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_actor",
+ "comment": "Key to actor.actor_id of the user or IP who made this edit",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_timestamp",
+ "comment": "Timestamp of when revision was created",
+ "type": "mwtimestamp",
+ "options": { "notnull": true, "default": "" }
+ },
+ {
+ "name": "rev_minor_edit",
+ "comment": "Records whether the user marked the 'minor edit' checkbox. Many automated edits are marked as minor",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_deleted",
+ "comment": "Restrictions on who can access this revision",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_len",
+ "comment": "Length of this revision in bytes",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_parent_id",
+ "comment": "Key to revision.rev_id. This field is used to add support for a tree structure (The Adjacency List Model)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_sha1",
+ "comment": "SHA-1 text content hash in base-36",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rev_page_id",
+ "columns": [ "rev_page", "rev_id" ],
+ "comment": "The index is proposed for removal, do not use it in new code: T163532. Used for ordering revisions within a page by rev_id, which is usually incorrect, since rev_timestamp is normally the correct order. It can also be used by dumpBackup.php, if a page and rev_id range is specified.",
+ "unique": false
+ },
+ {
+ "name": "rev_timestamp",
+ "columns": [ "rev_timestamp" ],
+ "comment": "Used by ApiQueryAllRevisions",
+ "unique": false
+ },
+ {
+ "name": "page_timestamp",
+ "columns": [ "rev_page", "rev_timestamp" ],
+ "comment": "History index",
+ "unique": false
+ },
+ {
+ "name": "rev_actor_timestamp",
+ "columns": [ "rev_actor", "rev_timestamp", "rev_id" ],
+ "comment": "User contributions index",
+ "unique": false
+ },
+ {
+ "name": "rev_page_actor_timestamp",
+ "columns": [ "rev_page", "rev_actor", "rev_timestamp" ],
+ "comment": "Credits index. This is scanned in order to compile credits lists for pages, in ApiQueryContributors. Also for ApiQueryRevisions if rvuser is specified",
+ "unique": false
+ }
+ ],
+ "table_options": [ "/*$wgDBTableOptions*/", "MAX_ROWS=10000000", "AVG_ROW_LENGTH=1024" ],
+ "pk": [ "rev_id" ]
+ },
+ "after": {
+ "name": "revision",
+ "comment": "Every edit of a page creates also a revision row. This stores metadata about the revision, and a reference to the text storage backend.",
+ "columns": [
+ {
+ "name": "rev_id",
+ "comment": "Unique ID to identify each revision",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "rev_page",
+ "comment": "Key to page_id. This should never be invalid",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "rev_comment_id",
+ "comment": "Key to comment.comment_id. Comment summarizing the change",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_actor",
+ "comment": "Key to actor.actor_id of the user or IP who made this edit",
+ "type": "bigint",
+ "options": { "unsigned": true, "notnull": true, "default": 0 }
+ },
+ {
+ "name": "rev_timestamp",
+ "comment": "Timestamp of when revision was created",
+ "type": "mwtimestamp",
+ "options": { "notnull": true, "default": "" }
+ },
+ {
+ "name": "rev_minor_edit",
+ "comment": "Records whether the user marked the 'minor edit' checkbox. Many automated edits are marked as minor",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_deleted",
+ "comment": "Restrictions on who can access this revision",
+ "type": "mwtinyint",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "rev_len",
+ "comment": "Length of this revision in bytes",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_parent_id",
+ "comment": "Key to revision.rev_id. This field is used to add support for a tree structure (The Adjacency List Model)",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": false }
+ },
+ {
+ "name": "rev_sha1",
+ "comment": "SHA-1 text content hash in base-36",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "rev_page_id",
+ "columns": [ "rev_page", "rev_id" ],
+ "comment": "The index is proposed for removal, do not use it in new code: T163532. Used for ordering revisions within a page by rev_id, which is usually incorrect, since rev_timestamp is normally the correct order. It can also be used by dumpBackup.php, if a page and rev_id range is specified.",
+ "unique": false
+ },
+ {
+ "name": "rev_timestamp",
+ "columns": [ "rev_timestamp" ],
+ "comment": "Used by ApiQueryAllRevisions",
+ "unique": false
+ },
+ {
+ "name": "rev_page_timestamp",
+ "columns": [ "rev_page", "rev_timestamp" ],
+ "comment": "History index",
+ "unique": false
+ },
+ {
+ "name": "rev_actor_timestamp",
+ "columns": [ "rev_actor", "rev_timestamp", "rev_id" ],
+ "comment": "User contributions index",
+ "unique": false
+ },
+ {
+ "name": "rev_page_actor_timestamp",
+ "columns": [ "rev_page", "rev_actor", "rev_timestamp" ],
+ "comment": "Credits index. This is scanned in order to compile credits lists for pages, in ApiQueryContributors. Also for ApiQueryRevisions if rvuser is specified",
+ "unique": false
+ }
+ ],
+ "table_options": [ "/*$wgDBTableOptions*/", "MAX_ROWS=10000000", "AVG_ROW_LENGTH=1024" ],
+ "pk": [ "rev_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-searchindex-pk-titlelength.json b/sql/abstractSchemaChanges/patch-searchindex-pk-titlelength.json
new file mode 100644
index 000000000000..9ff3bce55428
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-searchindex-pk-titlelength.json
@@ -0,0 +1,131 @@
+{
+ "comment": "Searchindex with PK (T249976), InnoDB (T107875), larger title (T231827)",
+ "before": {
+ "columns": [
+ {
+ "name": "si_page",
+ "type": "integer",
+ "comment": "Key to page_id",
+ "options": {
+ "notnull": true,
+ "unsigned": true
+ }
+ },
+ {
+ "name": "si_title",
+ "type": "string",
+ "comment": "Munged version of title",
+ "options": {
+ "default": "",
+ "length": 255,
+ "notnull": true
+ }
+ },
+ {
+ "name": "si_text",
+ "type": "text",
+ "comment": "Munged version of body text",
+ "options": {
+ "length": 16777215,
+ "notnull": true
+ }
+ }
+ ],
+ "comment": "search backend, this is actively used in MySQL but created and not used in Postgres while there are plans to use it in the future (T220450). This table must be MyISAM in MySQL; InnoDB does not support the needed fulltext index.",
+ "indexes": [
+ {
+ "name": "si_page",
+ "columns": [
+ "si_page"
+ ],
+ "unique": true
+ },
+ {
+ "name": "si_title",
+ "columns": [
+ "si_title"
+ ],
+ "flags": [
+ "fulltext"
+ ],
+ "unique": false
+ },
+ {
+ "name": "si_text",
+ "columns": [
+ "si_text"
+ ],
+ "flags": [
+ "fulltext"
+ ],
+ "unique": false
+ }
+ ],
+ "name": "searchindex",
+ "pk": [],
+ "table_options": [
+ "ENGINE=MyISAM",
+ "DEFAULT CHARSET=utf8"
+ ]
+ },
+ "after": {
+ "columns": [
+ {
+ "name": "si_page",
+ "type": "integer",
+ "comment": "Key to page_id",
+ "options": {
+ "notnull": true,
+ "unsigned": true
+ }
+ },
+ {
+ "name": "si_title",
+ "type": "string",
+ "comment": "Munged version of title",
+ "options": {
+ "length": 16777215,
+ "notnull": true
+ }
+ },
+ {
+ "name": "si_text",
+ "type": "text",
+ "comment": "Munged version of body text",
+ "options": {
+ "length": 16777215,
+ "notnull": true
+ }
+ }
+ ],
+ "comment": "search backend, this is actively used in MySQL but created and not used in Postgres while there are plans to use it in the future (T220450). This table must be MyISAM in MySQL; InnoDB does not support the needed fulltext index.",
+ "indexes": [
+ {
+ "name": "si_title",
+ "columns": [
+ "si_title"
+ ],
+ "flags": [
+ "fulltext"
+ ],
+ "unique": false
+ },
+ {
+ "name": "si_text",
+ "columns": [
+ "si_text"
+ ],
+ "flags": [
+ "fulltext"
+ ],
+ "unique": false
+ }
+ ],
+ "name": "searchindex",
+ "pk": [ "si_page" ],
+ "table_options": [
+ "ENGINE=MyISAM",
+ "DEFAULT CHARSET=utf8mb4"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-site_identifiers-rename-indexes.json b/sql/abstractSchemaChanges/patch-site_identifiers-rename-indexes.json
new file mode 100644
index 000000000000..76a561a00448
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-site_identifiers-rename-indexes.json
@@ -0,0 +1,61 @@
+{
+ "comment": "Rename indexes to have uniform si_ prefix with the columns (T270033)",
+ "before": {
+ "name": "site_identifiers",
+ "comment": "Links local site identifiers to their corresponding site.",
+ "columns": [
+ {
+ "name": "si_type",
+ "comment": "local key type, ie 'interwiki' or 'langlink'",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true }
+ },
+ {
+ "name": "si_key",
+ "comment": "local key value, ie 'en' or 'wiktionary'",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true }
+ },
+ {
+ "name": "si_site",
+ "comment": "Key on sites.site_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "site_ids_site", "columns": [ "si_site" ], "unique": false },
+ { "name": "site_ids_key", "columns": [ "si_key" ], "unique": false }
+ ],
+ "pk": [ "si_type", "si_key" ]
+ },
+ "after": {
+ "name": "site_identifiers",
+ "comment": "Links local site identifiers to their corresponding site.",
+ "columns": [
+ {
+ "name": "si_type",
+ "comment": "local key type, ie 'interwiki' or 'langlink'",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true }
+ },
+ {
+ "name": "si_key",
+ "comment": "local key value, ie 'en' or 'wiktionary'",
+ "type": "binary",
+ "options": { "length": 32, "notnull": true }
+ },
+ {
+ "name": "si_site",
+ "comment": "Key on sites.site_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [
+ { "name": "si_site", "columns": [ "si_site" ], "unique": false },
+ { "name": "si_key", "columns": [ "si_key" ], "unique": false }
+ ],
+ "pk": [ "si_type", "si_key" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-sites-drop_indexes.json b/sql/abstractSchemaChanges/patch-sites-drop_indexes.json
new file mode 100644
index 000000000000..62c32d26b3ae
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-sites-drop_indexes.json
@@ -0,0 +1,162 @@
+{
+ "comment": "Drop unused indexes of sites table",
+ "before": {
+ "name": "sites",
+ "comment": "Holds all the sites known to the wiki.",
+ "columns": [
+ {
+ "name": "site_id",
+ "type": "integer",
+ "comment": "Numeric id of the site",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "site_global_key",
+ "type": "binary",
+ "comment": "Global identifier for the site, ie 'enwiktionary'",
+ "options": { "notnull": true, "length": 64 }
+ },
+ {
+ "name": "site_type",
+ "type": "binary",
+ "comment": "Type of the site, ie 'mediawiki'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_group",
+ "type": "binary",
+ "comment": "Group of the site, ie 'wikipedia'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_source",
+ "type": "binary",
+ "comment": "Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_language",
+ "type": "binary",
+ "comment": "Language code of the sites primary language.",
+ "options": { "notnull": true, "length": 35 }
+ },
+ {
+ "name": "site_protocol",
+ "type": "binary",
+ "comment": "Protocol of the site, ie 'http://', 'irc://', '//'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_domain",
+ "type": "string",
+ "comment": "Domain of the site in reverse order, ie 'org.mediawiki.www.'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "site_data",
+ "type": "blob",
+ "comment": "Type dependent site data.",
+ "options": { "notnull": true, "length": 65530 }
+ },
+ {
+ "name": "site_forward",
+ "type": "mwtinyint",
+ "comment": "If site.tld/path/key:pageTitle should forward users to the page on the actual site, where \"key\" is the local identifier.",
+ "options": { "notnull": true, "length": 1 }
+ },
+ {
+ "name": "site_config",
+ "type": "blob",
+ "comment": "Type dependent site config. For instance if template transclusion should be allowed if it's a MediaWiki.",
+ "options": { "notnull": true, "length": 65530 }
+ }
+ ],
+ "indexes": [
+ { "name": "site_global_key", "columns": [ "site_global_key" ], "unique": true },
+ { "name": "site_type", "columns": [ "site_type" ], "unique": false },
+ { "name": "site_group", "columns": [ "site_group" ], "unique": false },
+ { "name": "site_source", "columns": [ "site_source" ], "unique": false },
+ { "name": "site_language", "columns": [ "site_language" ], "unique": false },
+ { "name": "site_protocol", "columns": [ "site_protocol" ], "unique": false },
+ { "name": "site_domain", "columns": [ "site_domain" ], "unique": false },
+ { "name": "site_forward", "columns": [ "site_forward" ], "unique": false }
+ ],
+ "pk": [ "site_id" ]
+ },
+ "after": {
+ "name": "sites",
+ "comment": "Holds all the sites known to the wiki.",
+ "columns": [
+ {
+ "name": "site_id",
+ "type": "integer",
+ "comment": "Numeric id of the site",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "site_global_key",
+ "type": "binary",
+ "comment": "Global identifier for the site, ie 'enwiktionary'",
+ "options": { "notnull": true, "length": 64 }
+ },
+ {
+ "name": "site_type",
+ "type": "binary",
+ "comment": "Type of the site, ie 'mediawiki'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_group",
+ "type": "binary",
+ "comment": "Group of the site, ie 'wikipedia'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_source",
+ "type": "binary",
+ "comment": "Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_language",
+ "type": "binary",
+ "comment": "Language code of the sites primary language.",
+ "options": { "notnull": true, "length": 35 }
+ },
+ {
+ "name": "site_protocol",
+ "type": "binary",
+ "comment": "Protocol of the site, ie 'http://', 'irc://', '//'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_domain",
+ "type": "string",
+ "comment": "Domain of the site in reverse order, ie 'org.mediawiki.www.'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "site_data",
+ "type": "blob",
+ "comment": "Type dependent site data.",
+ "options": { "notnull": true, "length": 65530 }
+ },
+ {
+ "name": "site_forward",
+ "type": "mwtinyint",
+ "comment": "If site.tld/path/key:pageTitle should forward users to the page on the actual site, where \"key\" is the local identifier.",
+ "options": { "notnull": true, "length": 1 }
+ },
+ {
+ "name": "site_config",
+ "type": "blob",
+ "comment": "Type dependent site config. For instance if template transclusion should be allowed if it's a MediaWiki.",
+ "options": { "notnull": true, "length": 65530 }
+ }
+ ],
+ "indexes": [
+ { "name": "site_global_key", "columns": [ "site_global_key" ], "unique": true }
+ ],
+ "pk": [ "site_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-sites-rename-indexes.json b/sql/abstractSchemaChanges/patch-sites-rename-indexes.json
new file mode 100644
index 000000000000..1d2e57ae17e3
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-sites-rename-indexes.json
@@ -0,0 +1,169 @@
+{
+ "comment": "Rename all indexes to have 'site_' prefix (T270033)",
+ "before": {
+ "name": "sites",
+ "comment": "Holds all the sites known to the wiki.",
+ "columns": [
+ {
+ "name": "site_id",
+ "type": "integer",
+ "comment": "Numeric id of the site",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "site_global_key",
+ "type": "binary",
+ "comment": "Global identifier for the site, ie 'enwiktionary'",
+ "options": { "notnull": true, "length": 64 }
+ },
+ {
+ "name": "site_type",
+ "type": "binary",
+ "comment": "Type of the site, ie 'mediawiki'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_group",
+ "type": "binary",
+ "comment": "Group of the site, ie 'wikipedia'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_source",
+ "type": "binary",
+ "comment": "Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_language",
+ "type": "binary",
+ "comment": "Language code of the sites primary language.",
+ "options": { "notnull": true, "length": 35 }
+ },
+ {
+ "name": "site_protocol",
+ "type": "binary",
+ "comment": "Protocol of the site, ie 'http://', 'irc://', '//'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_domain",
+ "type": "string",
+ "comment": "Domain of the site in reverse order, ie 'org.mediawiki.www.'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "site_data",
+ "type": "blob",
+ "comment": "Type dependent site data.",
+ "options": { "notnull": true, "length": 65530 }
+ },
+ {
+ "name": "site_forward",
+ "type": "mwtinyint",
+ "comment": "If site.tld/path/key:pageTitle should forward users to the page on the actual site, where \"key\" is the local identifier.",
+ "options": { "notnull": true, "length": 1 }
+ },
+ {
+ "name": "site_config",
+ "type": "blob",
+ "comment": "Type dependent site config. For instance if template transclusion should be allowed if it's a MediaWiki.",
+ "options": { "notnull": true, "length": 65530 }
+ }
+ ],
+ "indexes": [
+ { "name": "sites_global_key", "columns": [ "site_global_key" ], "unique": true },
+ { "name": "sites_type", "columns": [ "site_type" ], "unique": false },
+ { "name": "sites_group", "columns": [ "site_group" ], "unique": false },
+ { "name": "sites_source", "columns": [ "site_source" ], "unique": false },
+ { "name": "sites_language", "columns": [ "site_language" ], "unique": false },
+ { "name": "sites_protocol", "columns": [ "site_protocol" ], "unique": false },
+ { "name": "sites_domain", "columns": [ "site_domain" ], "unique": false },
+ { "name": "sites_forward", "columns": [ "site_forward" ], "unique": false }
+ ],
+ "pk": [ "site_id" ]
+ },
+ "after": {
+ "name": "sites",
+ "comment": "Holds all the sites known to the wiki.",
+ "columns": [
+ {
+ "name": "site_id",
+ "type": "integer",
+ "comment": "Numeric id of the site",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "site_global_key",
+ "type": "binary",
+ "comment": "Global identifier for the site, ie 'enwiktionary'",
+ "options": { "notnull": true, "length": 64 }
+ },
+ {
+ "name": "site_type",
+ "type": "binary",
+ "comment": "Type of the site, ie 'mediawiki'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_group",
+ "type": "binary",
+ "comment": "Group of the site, ie 'wikipedia'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_source",
+ "type": "binary",
+ "comment": "Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_language",
+ "type": "binary",
+ "comment": "Language code of the sites primary language.",
+ "options": { "notnull": true, "length": 35 }
+ },
+ {
+ "name": "site_protocol",
+ "type": "binary",
+ "comment": "Protocol of the site, ie 'http://', 'irc://', '//'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 32 }
+ },
+ {
+ "name": "site_domain",
+ "type": "string",
+ "comment": "Domain of the site in reverse order, ie 'org.mediawiki.www.'. This field is an index for lookups and is build from type specific data in site_data.",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "site_data",
+ "type": "blob",
+ "comment": "Type dependent site data.",
+ "options": { "notnull": true, "length": 65530 }
+ },
+ {
+ "name": "site_forward",
+ "type": "mwtinyint",
+ "comment": "If site.tld/path/key:pageTitle should forward users to the page on the actual site, where \"key\" is the local identifier.",
+ "options": { "notnull": true, "length": 1 }
+ },
+ {
+ "name": "site_config",
+ "type": "blob",
+ "comment": "Type dependent site config. For instance if template transclusion should be allowed if it's a MediaWiki.",
+ "options": { "notnull": true, "length": 65530 }
+ }
+ ],
+ "indexes": [
+ { "name": "site_global_key", "columns": [ "site_global_key" ], "unique": true },
+ { "name": "site_type", "columns": [ "site_type" ], "unique": false },
+ { "name": "site_group", "columns": [ "site_group" ], "unique": false },
+ { "name": "site_source", "columns": [ "site_source" ], "unique": false },
+ { "name": "site_language", "columns": [ "site_language" ], "unique": false },
+ { "name": "site_protocol", "columns": [ "site_protocol" ], "unique": false },
+ { "name": "site_domain", "columns": [ "site_domain" ], "unique": false },
+ { "name": "site_forward", "columns": [ "site_forward" ], "unique": false }
+ ],
+ "pk": [ "site_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-templatelinks-drop-tl_title.json b/sql/abstractSchemaChanges/patch-templatelinks-drop-tl_title.json
new file mode 100644
index 000000000000..acaf715f5112
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-templatelinks-drop-tl_title.json
@@ -0,0 +1,103 @@
+{
+ "comment": "Drop tl_title column (and more) on templatelinks (T299417)",
+ "before": {
+ "name": "templatelinks",
+ "comment": "Track template inclusions. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "tl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "tl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for this page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_namespace",
+ "type": "integer",
+ "options": { "default": 0 }
+ },
+ {
+ "name": "tl_title",
+ "type": "binary",
+ "options": { "length": 255, "default": "" }
+ },
+ {
+ "name": "tl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": true, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "tl_namespace",
+ "columns": [ "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace",
+ "columns": [ "tl_from_namespace", "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ },
+ {
+ "name": "tl_target_id",
+ "columns": [ "tl_target_id", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace_target_id",
+ "columns": [ "tl_from_namespace", "tl_target_id", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "tl_from", "tl_target_id" ]
+ },
+ "after": {
+ "name": "templatelinks",
+ "comment": "Track template inclusions. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "tl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "tl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for this page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": true, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "tl_target_id",
+ "columns": [ "tl_target_id", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace_target_id",
+ "columns": [ "tl_from_namespace", "tl_target_id", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "tl_from", "tl_target_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-templatelinks-target_id.json b/sql/abstractSchemaChanges/patch-templatelinks-target_id.json
new file mode 100644
index 000000000000..e7ff8acf69e1
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-templatelinks-target_id.json
@@ -0,0 +1,107 @@
+{
+ "comment": "Add tl_target_id on templatelinks (T299418)",
+ "before": {
+ "name": "templatelinks",
+ "comment": "Track template inclusions. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "tl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "tl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for this page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_title",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "tl_namespace",
+ "columns": [ "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace",
+ "columns": [ "tl_from_namespace", "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "tl_from", "tl_namespace", "tl_title" ]
+ },
+ "after": {
+ "name": "templatelinks",
+ "comment": "Track template inclusions. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "tl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "tl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for this page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_title",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "tl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": false, "unsigned": true, "default": null }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "tl_namespace",
+ "columns": [ "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace",
+ "columns": [ "tl_from_namespace", "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ },
+ {
+ "name": "tl_target_id",
+ "columns": [ "tl_target_id", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace_target_id",
+ "columns": [ "tl_from_namespace", "tl_target_id", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "tl_from", "tl_namespace", "tl_title" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-templatelinks-tl_title-nullable.json b/sql/abstractSchemaChanges/patch-templatelinks-tl_title-nullable.json
new file mode 100644
index 000000000000..bfbbe7c2aca1
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-templatelinks-tl_title-nullable.json
@@ -0,0 +1,125 @@
+{
+ "comment": "Changing the primary key as part of normalizing templatelinks (T306674)",
+ "before": {
+ "name": "templatelinks",
+ "comment": "Track template inclusions. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "tl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "tl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for this page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_title",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "tl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": false, "unsigned": true, "default": null }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "tl_namespace",
+ "columns": [ "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace",
+ "columns": [ "tl_from_namespace", "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ },
+ {
+ "name": "tl_target_id",
+ "columns": [ "tl_target_id", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace_target_id",
+ "columns": [ "tl_from_namespace", "tl_target_id", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "tl_from", "tl_namespace", "tl_title" ]
+ },
+ "after": {
+ "name": "templatelinks",
+ "comment": "Track template inclusions. The target page may or may not exist, and due to renames and deletions may refer to different page records as time goes by.",
+ "columns": [
+ {
+ "name": "tl_from",
+ "comment": "Key to the page_id of the page containing the link.",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true, "default": 0 }
+ },
+ {
+ "name": "tl_from_namespace",
+ "type": "integer",
+ "comment": "Namespace for this page",
+ "options": { "notnull": true, "default": 0 }
+ },
+ {
+ "name": "tl_namespace",
+ "type": "integer",
+ "options": { "default": 0 }
+ },
+ {
+ "name": "tl_title",
+ "type": "binary",
+ "options": { "length": 255, "default": "" }
+ },
+ {
+ "name": "tl_target_id",
+ "type": "bigint",
+ "comment": "Foreign key to linktarget.lt_id",
+ "options": { "notnull": true, "unsigned": true }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "tl_namespace",
+ "columns": [ "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace",
+ "columns": [ "tl_from_namespace", "tl_namespace", "tl_title", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ },
+ {
+ "name": "tl_target_id",
+ "columns": [ "tl_target_id", "tl_from" ],
+ "comment": "Reverse index, for Special:Whatlinkshere",
+ "unique": false
+ },
+ {
+ "name": "tl_backlinks_namespace_target_id",
+ "columns": [ "tl_from_namespace", "tl_target_id", "tl_from" ],
+ "comment": "Index for Special:Whatlinkshere with namespace filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "tl_from", "tl_target_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-uploadstash-us_size_to_bigint.json b/sql/abstractSchemaChanges/patch-uploadstash-us_size_to_bigint.json
new file mode 100644
index 000000000000..59aea9705da8
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-uploadstash-us_size_to_bigint.json
@@ -0,0 +1,375 @@
+{
+ "comment": "Increaes us_size to bigint (T191805)",
+ "before":
+ {
+ "name": "uploadstash",
+ "comment": "Store information about newly uploaded files before they're moved into the actual filestore",
+ "columns": [
+ {
+ "name": "us_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_user",
+ "comment": "the user who uploaded the file.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_key",
+ "comment": "file key. this is how applications actually search for the file. this might go away, or become the primary key.",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_orig_path",
+ "comment": "the original path",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_path",
+ "comment": "the temporary path at which the file is actually stored",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_source_type",
+ "comment": "which type of upload the file came from (sometimes)",
+ "type": "string",
+ "options": {
+ "notnull": false,
+ "length": 50
+ }
+ },
+ {
+ "name": "us_timestamp",
+ "comment": "the date/time on which the file was added",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_status",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 50
+ }
+ },
+ {
+ "name": "us_chunk_inx",
+ "comment": "chunk counter starts at 0, current offset is stored in us_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ },
+ {
+ "name": "us_props",
+ "comment": "Serialized file properties from FSFile::getProps()",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65530
+ }
+ },
+ {
+ "name": "us_size",
+ "comment": "file size in bytes",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_sha1",
+ "comment": "this hash comes from FSFile::getSha1Base36(), and is 31 characters",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 31
+ }
+ },
+ {
+ "name": "us_mime",
+ "type": "string",
+ "options": {
+ "notnull": false,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_media_type",
+ "comment": "Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table",
+ "type": "mwenum",
+ "options": { "notnull": false, "default": null,
+ "fixed": true,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "us_image_width",
+ "comment": "image-specific properties",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ },
+ {
+ "name": "us_image_height",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ },
+ {
+ "name": "us_image_bits",
+ "type": "smallint",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "us_user",
+ "comment": "sometimes there's a delete for all of a user's stuff.",
+ "columns": [
+ "us_user"
+ ],
+ "unique": false
+ },
+ {
+ "name": "us_key",
+ "comment": "pick out files by key, enforce key uniqueness",
+ "columns": [
+ "us_key"
+ ],
+ "unique": true
+ },
+ {
+ "name": "us_timestamp",
+ "comment": "the abandoned upload cleanup script needs this",
+ "columns": [
+ "us_timestamp"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "us_id"
+ ]
+ },
+ "after":
+ {
+ "name": "uploadstash",
+ "comment": "Store information about newly uploaded files before they're moved into the actual filestore",
+ "columns": [
+ {
+ "name": "us_id",
+ "type": "integer",
+ "options": {
+ "autoincrement": true,
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_user",
+ "comment": "the user who uploaded the file.",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_key",
+ "comment": "file key. this is how applications actually search for the file. this might go away, or become the primary key.",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_orig_path",
+ "comment": "the original path",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_path",
+ "comment": "the temporary path at which the file is actually stored",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_source_type",
+ "comment": "which type of upload the file came from (sometimes)",
+ "type": "string",
+ "options": {
+ "notnull": false,
+ "length": 50
+ }
+ },
+ {
+ "name": "us_timestamp",
+ "comment": "the date/time on which the file was added",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_status",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 50
+ }
+ },
+ {
+ "name": "us_chunk_inx",
+ "comment": "chunk counter starts at 0, current offset is stored in us_size",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ },
+ {
+ "name": "us_props",
+ "comment": "Serialized file properties from FSFile::getProps()",
+ "type": "blob",
+ "options": {
+ "notnull": false,
+ "length": 65530
+ }
+ },
+ {
+ "name": "us_size",
+ "comment": "file size in bytes",
+ "type": "bigint",
+ "options": {
+ "unsigned": true,
+ "notnull": true
+ }
+ },
+ {
+ "name": "us_sha1",
+ "comment": "this hash comes from FSFile::getSha1Base36(), and is 31 characters",
+ "type": "string",
+ "options": {
+ "notnull": true,
+ "length": 31
+ }
+ },
+ {
+ "name": "us_mime",
+ "type": "string",
+ "options": {
+ "notnull": false,
+ "length": 255
+ }
+ },
+ {
+ "name": "us_media_type",
+ "comment": "Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table",
+ "type": "mwenum",
+ "options": { "notnull": false, "default": null,
+ "fixed": true,
+ "CustomSchemaOptions": {
+ "enum_values": [ "UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ]
+ }
+ }
+ },
+ {
+ "name": "us_image_width",
+ "comment": "image-specific properties",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ },
+ {
+ "name": "us_image_height",
+ "type": "integer",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ },
+ {
+ "name": "us_image_bits",
+ "type": "smallint",
+ "options": {
+ "unsigned": true,
+ "notnull": false
+ }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "us_user",
+ "comment": "sometimes there's a delete for all of a user's stuff.",
+ "columns": [
+ "us_user"
+ ],
+ "unique": false
+ },
+ {
+ "name": "us_key",
+ "comment": "pick out files by key, enforce key uniqueness",
+ "columns": [
+ "us_key"
+ ],
+ "unique": true
+ },
+ {
+ "name": "us_timestamp",
+ "comment": "the abandoned upload cleanup script needs this",
+ "columns": [
+ "us_timestamp"
+ ],
+ "unique": false
+ }
+ ],
+ "pk": [
+ "us_id"
+ ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-user-user_editcount.json b/sql/abstractSchemaChanges/patch-user-user_editcount.json
new file mode 100644
index 000000000000..6a1271404c40
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-user-user_editcount.json
@@ -0,0 +1,175 @@
+{
+ "comment": "Set user_editcount to unsigned in user table",
+ "before": {
+ "name": "user",
+ "columns": [
+ {
+ "name": "user_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "user_name",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_real_name",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_password",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpassword",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpass_time",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_touched",
+ "type": "binary",
+ "options": { "notnull": true, "length": 14 }
+ },
+ {
+ "name": "user_token",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_authenticated",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email_token",
+ "type": "binary",
+ "options": { "notnull": false, "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_token_expires",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_registration",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_editcount",
+ "type": "integer",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_password_expires",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ }
+ ],
+ "indexes": [
+ { "name": "user_name", "columns": [ "user_name" ], "unique": true },
+ { "name": "user_email_token", "columns": [ "user_email_token" ], "unique": false },
+ { "name": "user_email", "columns": [ "user_email" ], "unique": false, "options": { "lengths": [ 50, null, null ] } }
+ ],
+ "pk": [ "user_id" ]
+ },
+ "after": {
+ "name": "user",
+ "columns": [
+ {
+ "name": "user_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "user_name",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_real_name",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_password",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpassword",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpass_time",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_touched",
+ "type": "binary",
+ "options": { "notnull": true, "length": 14 }
+ },
+ {
+ "name": "user_token",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_authenticated",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email_token",
+ "type": "binary",
+ "options": { "notnull": false, "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_token_expires",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_registration",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_editcount",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true }
+ },
+ {
+ "name": "user_password_expires",
+ "type": "binary",
+ "options": { "notnull": false, "length": 14 }
+ }
+ ],
+ "indexes": [
+ { "name": "user_name", "columns": [ "user_name" ], "unique": true },
+ { "name": "user_email_token", "columns": [ "user_email_token" ], "unique": false },
+ { "name": "user_email", "columns": [ "user_email" ], "unique": false, "options": { "lengths": [ 50, null, null ] } }
+ ],
+ "pk": [ "user_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-user-user_is_temp.json b/sql/abstractSchemaChanges/patch-user-user_is_temp.json
new file mode 100644
index 000000000000..14e40e656c25
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-user-user_is_temp.json
@@ -0,0 +1,225 @@
+{
+ "comment": "Add user_is_temp to user table",
+ "before": {
+ "name": "user",
+ "comment": "The user table contains basic account information, authentication keys, etc. Some multi-wiki sites may share a single central user table between separate wikis using the $wgSharedDB setting. Note that even when an external authentication plugin is in use, user table entries still need to be created to store preferences and to key tracking information in the other tables",
+ "columns": [
+ {
+ "name": "user_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "user_name",
+ "comment": "Usernames must be unique, must not be in the form of an IP address. They should not allow slashes or case conflicts. Spaces are allowed, and are not converted to underscores like in page titles.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_real_name",
+ "comment": "Optional 'real name' to be displayed in credit listings",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_password",
+ "comment": "Password hashes",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpassword",
+ "comment": "When using 'mail me a new password', a random password is generated and the hash stored here. The previous password is left in place until someone actually logs in with the new password, at which point the hash is moved to user_password and the old password is invalidated.",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpass_time",
+ "comment": "Timestamp of the last time when a new password was sent, for throttling and expiring purposes. Emailed passwords will expire $wgNewPasswordExpiry (a week) after being set. If user_newpass_time is NULL (eg. created by mail) it doesn't expire.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_email",
+ "comment": "User email. Non public info.",
+ "type": "text",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_touched",
+ "comment": "If the browser sends an If-Modified-Since header, a 304 response is suppressed if the value in this field for the current user is later than the value in the IMS header. That is, this field is an invalidation timestamp for the browser cache of logged-in users. Among other things, it is used to prevent pages generated for a previously logged in user from being displayed after a session expiry followed by a fresh login.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "user_token",
+ "comment": "A pseudorandomly generated value that is stored in a cookie when the 'remember password' feature is used (previously, a hash of the password was used, but this was vulnerable to cookie-stealing attacks)",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_authenticated",
+ "comment": "Initially NULL; when a user's e-mail address has been validated by returning with a mailed token, this is set to the current timestamp.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_email_token",
+ "comment": "Randomly generated token created when the e-mail address is set and a confirmation test mail sent.",
+ "type": "binary",
+ "options": { "notnull": false, "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_token_expires",
+ "comment": "Expiration date for the user_email_token.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_registration",
+ "comment": "Timestamp of account registration. Accounts predating this schema addition may contain NULL.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_editcount",
+ "comment": "Count of edits and edit-like actions. Not intended to be an accurate copy of 'COUNT(*) WHERE rev_actor refers to a user's actor_id'. May contain NULL for old accounts if batch-update scripts haven't been run, as well as listing deleted edits and other myriad ways it could be out of sync. Meant primarily for heuristic checks to give an impression of whether the account has been used much.",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true }
+ },
+ {
+ "name": "user_password_expires",
+ "comment": "Expiration date for user password.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "user_name", "columns": [ "user_name" ], "unique": true },
+ { "name": "user_email_token", "columns": [ "user_email_token" ], "unique": false },
+ { "name": "user_email", "columns": [ "user_email" ], "unique": false, "options": { "lengths": [ 50, null, null ] } }
+ ],
+ "pk": [ "user_id" ]
+ },
+ "after": {
+ "name": "user",
+ "comment": "The user table contains basic account information, authentication keys, etc. Some multi-wiki sites may share a single central user table between separate wikis using the $wgSharedDB setting. Note that even when an external authentication plugin is in use, user table entries still need to be created to store preferences and to key tracking information in the other tables",
+ "columns": [
+ {
+ "name": "user_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "user_name",
+ "comment": "Usernames must be unique, must not be in the form of an IP address. They should not allow slashes or case conflicts. Spaces are allowed, and are not converted to underscores like in page titles.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_real_name",
+ "comment": "Optional 'real name' to be displayed in credit listings",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_password",
+ "comment": "Password hashes",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpassword",
+ "comment": "When using 'mail me a new password', a random password is generated and the hash stored here. The previous password is left in place until someone actually logs in with the new password, at which point the hash is moved to user_password and the old password is invalidated.",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpass_time",
+ "comment": "Timestamp of the last time when a new password was sent, for throttling and expiring purposes. Emailed passwords will expire $wgNewPasswordExpiry (a week) after being set. If user_newpass_time is NULL (eg. created by mail) it doesn't expire.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_email",
+ "comment": "User email. Non public info.",
+ "type": "text",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_touched",
+ "comment": "If the browser sends an If-Modified-Since header, a 304 response is suppressed if the value in this field for the current user is later than the value in the IMS header. That is, this field is an invalidation timestamp for the browser cache of logged-in users. Among other things, it is used to prevent pages generated for a previously logged in user from being displayed after a session expiry followed by a fresh login.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true }
+ },
+ {
+ "name": "user_token",
+ "comment": "A pseudorandomly generated value that is stored in a cookie when the 'remember password' feature is used (previously, a hash of the password was used, but this was vulnerable to cookie-stealing attacks)",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_authenticated",
+ "comment": "Initially NULL; when a user's e-mail address has been validated by returning with a mailed token, this is set to the current timestamp.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_email_token",
+ "comment": "Randomly generated token created when the e-mail address is set and a confirmation test mail sent.",
+ "type": "binary",
+ "options": { "notnull": false, "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_token_expires",
+ "comment": "Expiration date for the user_email_token.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_registration",
+ "comment": "Timestamp of account registration. Accounts predating this schema addition may contain NULL.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_editcount",
+ "comment": "Count of edits and edit-like actions. Not intended to be an accurate copy of 'COUNT(*) WHERE rev_actor refers to a user's actor_id'. May contain NULL for old accounts if batch-update scripts haven't been run, as well as listing deleted edits and other myriad ways it could be out of sync. Meant primarily for heuristic checks to give an impression of whether the account has been used much.",
+ "type": "integer",
+ "options": { "notnull": false, "unsigned": true }
+ },
+ {
+ "name": "user_password_expires",
+ "comment": "Expiration date for user password.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ },
+ {
+ "name": "user_is_temp",
+ "comment": "A boolean value representing whether the user is a temporary user. False if any type of user other than a temporary user. This exists to allow temporary users to be identified from the database only, by external applications.",
+ "type": "mwtinyint",
+ "options": {
+ "notnull": true,
+ "length": 1,
+ "default": 0
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "user_name", "columns": [ "user_name" ], "unique": true },
+ { "name": "user_email_token", "columns": [ "user_email_token" ], "unique": false },
+ { "name": "user_email", "columns": [ "user_email" ], "unique": false, "options": { "lengths": [ 50, null, null ] } }
+ ],
+ "pk": [ "user_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-user_autocreate_serial-uas_year.json b/sql/abstractSchemaChanges/patch-user_autocreate_serial-uas_year.json
new file mode 100644
index 000000000000..734f1969808a
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-user_autocreate_serial-uas_year.json
@@ -0,0 +1,49 @@
+{
+ "comment": "Add uas_year to user_autocreate_serial table",
+ "before": {
+ "name": "user_autocreate_serial",
+ "comment": "Table for sequential name generation for auto-created temporary users",
+ "columns": [
+ {
+ "name": "uas_shard",
+ "comment": "The segment of ID space, ID mod N, referred to by this row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "uas_value",
+ "comment": "The maximum allocated ID value",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [],
+ "pk": [ "uas_shard" ]
+ },
+ "after": {
+ "name": "user_autocreate_serial",
+ "comment": "Table for sequential name generation for auto-created temporary users",
+ "columns": [
+ {
+ "name": "uas_shard",
+ "comment": "The segment of ID space, ID mod N, referred to by this row",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "uas_year",
+ "comment": "The year to which this row belongs, if $wgAutoCreateTempUser['serialProvider']['useYear'] is true.",
+ "type": "smallint",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "uas_value",
+ "comment": "The maximum allocated ID value",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ }
+ ],
+ "indexes": [],
+ "pk": [ "uas_shard", "uas_year" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-user_properties-rename-index.json b/sql/abstractSchemaChanges/patch-user_properties-rename-index.json
new file mode 100644
index 000000000000..8d0904b6e6ee
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-user_properties-rename-index.json
@@ -0,0 +1,59 @@
+{
+ "comment": "Rename user_properties_property index to up_property (T270033)",
+ "before": {
+ "name": "user_properties",
+ "comment": "User preferences and perhaps other fun stuff. :) Replaces the old user.user_options blob, with a couple nice properties: 1) We only store non-default settings, so changes to the defaults are now reflected for everybody, not just new accounts. 2) We can more easily do bulk lookups, statistics, or modifications of saved options since it's a sensible table structure.",
+ "columns": [
+ {
+ "name": "up_user",
+ "comment": "Foreign key to user.user_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "up_property",
+ "comment": "Name of the option being saved. This is indexed for bulk lookup.",
+ "type": "binary",
+ "options": { "length": 255, "notnull": true }
+ },
+ {
+ "name": "up_value",
+ "comment": "Property value as a string.",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "user_properties_property", "columns": [ "up_property" ], "unique": false }
+ ],
+ "pk": [ "up_user", "up_property" ]
+ },
+ "after": {
+ "name": "user_properties",
+ "comment": "User preferences and perhaps other fun stuff. :) Replaces the old user.user_options blob, with a couple nice properties: 1) We only store non-default settings, so changes to the defaults are now reflected for everybody, not just new accounts. 2) We can more easily do bulk lookups, statistics, or modifications of saved options since it's a sensible table structure.",
+ "columns": [
+ {
+ "name": "up_user",
+ "comment": "Foreign key to user.user_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true }
+ },
+ {
+ "name": "up_property",
+ "comment": "Name of the option being saved. This is indexed for bulk lookup.",
+ "type": "binary",
+ "options": { "length": 255, "notnull": true }
+ },
+ {
+ "name": "up_value",
+ "comment": "Property value as a string.",
+ "type": "blob",
+ "options": { "length": 65530, "notnull": false }
+ }
+ ],
+ "indexes": [
+ { "name": "up_property", "columns": [ "up_property" ], "unique": false }
+ ],
+ "pk": [ "up_user", "up_property" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-user_table-updates.json b/sql/abstractSchemaChanges/patch-user_table-updates.json
new file mode 100644
index 000000000000..08c8421084eb
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-user_table-updates.json
@@ -0,0 +1,217 @@
+{
+ "comment": "Update `user_name` and `user_real_name` from varchar to varbinary(255). Drop empty string default (invalid timestamp value) from `user_touched`.",
+ "before": {
+ "name": "user",
+ "comment": "The user table contains basic account information, authentication keys, etc. Some multi-wiki sites may share a single central user table between separate wikis using the $wgSharedDB setting. Note that even when an external authentication plugin is in use, user table entries still need to be created to store preferences and to key tracking information in the other tables",
+ "columns": [
+ {
+ "name": "user_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "user_name",
+ "comment": "Usernames must be unique, must not be in the form of an IP address. They should not allow slashes or case conflicts. Spaces are allowed, and are not converted to underscores like in page titles.",
+ "type": "string",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_real_name",
+ "comment": "Optional 'real name' to be displayed in credit listings",
+ "type": "string",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_password",
+ "comment": "Password hashes",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpassword",
+ "comment": "When using 'mail me a new password', a random password is generated and the hash stored here. The previous password is left in place until someone actually logs in with the new password, at which point the hash is moved to user_password and the old password is invalidated.",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpass_time",
+ "comment": "Timestamp of the last time when a new password was sent, for throttling and expiring purposes. Emailed passwords will expire $wgNewPasswordExpiry (a week) after being set. If user_newpass_time is NULL (eg. created by mail) it doesn't expire.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email",
+ "comment": "User email. Non public info.",
+ "type": "text",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_touched",
+ "comment": "If the browser sends an If-Modified-Since header, a 304 response is suppressed if the value in this field for the current user is later than the value in the IMS header. That is, this field is an invalidation timestamp for the browser cache of logged-in users. Among other things, it is used to prevent pages generated for a previously logged in user from being displayed after a session expiry followed by a fresh login.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true, "length": 14, "default": "" }
+ },
+ {
+ "name": "user_token",
+ "comment": "A pseudorandomly generated value that is stored in a cookie when the 'remember password' feature is used (previously, a hash of the password was used, but this was vulnerable to cookie-stealing attacks)",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_authenticated",
+ "comment": "Initially NULL; when a user's e-mail address has been validated by returning with a mailed token, this is set to the current timestamp.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email_token",
+ "comment": "Randomly generated token created when the e-mail address is set and a confirmation test mail sent.",
+ "type": "binary",
+ "options": { "notnull": false, "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_token_expires",
+ "comment": "Expiration date for the user_email_token.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_registration",
+ "comment": "Timestamp of account registration. Accounts predating this schema addition may contain NULL.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_editcount",
+ "comment": "Count of edits and edit-like actions. Not intended to be an accurate copy of 'COUNT(*) WHERE rev_actor refers to a user's actor_id'. May contain NULL for old accounts if batch-update scripts haven't been run, as well as listing deleted edits and other myriad ways it could be out of sync.Meant primarily for heuristic checks to give an impression of whether the account has been used much.",
+ "type": "integer",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_password_expires",
+ "comment": "Expiration date for user password.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "user_name", "columns": [ "user_name" ], "unique": true },
+ { "name": "user_email_token", "columns": [ "user_email_token" ], "unique": false },
+ { "name": "user_email", "columns": [ "user_email" ], "unique": false, "options": { "lengths": [ 50, null, null ] } }
+ ],
+ "pk": [ "user_id" ]
+ },
+ "after": {
+ "name": "user",
+ "comment": "The user table contains basic account information, authentication keys, etc. Some multi-wiki sites may share a single central user table between separate wikis using the $wgSharedDB setting. Note that even when an external authentication plugin is in use, user table entries still need to be created to store preferences and to key tracking information in the other tables",
+ "columns": [
+ {
+ "name": "user_id",
+ "comment": "Unique identifier number. The page_id will be preserved across edits and rename operations, but not deletions and recreations.",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "user_name",
+ "comment": "Usernames must be unique, must not be in the form of an IP address. They should not allow slashes or case conflicts. Spaces are allowed, and are not converted to underscores like in page titles.",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_real_name",
+ "comment": "Optional 'real name' to be displayed in credit listings",
+ "type": "binary",
+ "options": { "notnull": true, "length": 255, "default": "" }
+ },
+ {
+ "name": "user_password",
+ "comment": "Password hashes",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpassword",
+ "comment": "When using 'mail me a new password', a random password is generated and the hash stored here. The previous password is left in place until someone actually logs in with the new password, at which point the hash is moved to user_password and the old password is invalidated.",
+ "type": "blob",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_newpass_time",
+ "comment": "Timestamp of the last time when a new password was sent, for throttling and expiring purposes. Emailed passwords will expire $wgNewPasswordExpiry (a week) after being set. If user_newpass_time is NULL (eg. created by mail) it doesn't expire.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email",
+ "comment": "User email. Non public info.",
+ "type": "text",
+ "options": { "notnull": true, "length": 255 }
+ },
+ {
+ "name": "user_touched",
+ "comment": "If the browser sends an If-Modified-Since header, a 304 response is suppressed if the value in this field for the current user is later than the value in the IMS header. That is, this field is an invalidation timestamp for the browser cache of logged-in users. Among other things, it is used to prevent pages generated for a previously logged in user from being displayed after a session expiry followed by a fresh login.",
+ "type": "mwtimestamp",
+ "options": { "notnull": true, "length": 14 }
+ },
+ {
+ "name": "user_token",
+ "comment": "A pseudorandomly generated value that is stored in a cookie when the 'remember password' feature is used (previously, a hash of the password was used, but this was vulnerable to cookie-stealing attacks)",
+ "type": "binary",
+ "options": { "notnull": true, "default": "", "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_authenticated",
+ "comment": "Initially NULL; when a user's e-mail address has been validated by returning with a mailed token, this is set to the current timestamp.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_email_token",
+ "comment": "Randomly generated token created when the e-mail address is set and a confirmation test mail sent.",
+ "type": "binary",
+ "options": { "notnull": false, "length": 32, "fixed": true }
+ },
+ {
+ "name": "user_email_token_expires",
+ "comment": "Expiration date for the user_email_token.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_registration",
+ "comment": "Timestamp of account registration. Accounts predating this schema addition may contain NULL.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false, "length": 14 }
+ },
+ {
+ "name": "user_editcount",
+ "comment": "Count of edits and edit-like actions. Not intended to be an accurate copy of 'COUNT(*) WHERE rev_actor refers to a user's actor_id'. May contain NULL for old accounts if batch-update scripts haven't been run, as well as listing deleted edits and other myriad ways it could be out of sync.Meant primarily for heuristic checks to give an impression of whether the account has been used much.",
+ "type": "integer",
+ "options": { "notnull": false }
+ },
+ {
+ "name": "user_password_expires",
+ "comment": "Expiration date for user password.",
+ "type": "mwtimestamp",
+ "options": {
+ "notnull": false,
+ "CustomSchemaOptions": {
+ "allowInfinite": true
+ }
+ }
+ }
+ ],
+ "indexes": [
+ { "name": "user_name", "columns": [ "user_name" ], "unique": true },
+ { "name": "user_email_token", "columns": [ "user_email_token" ], "unique": false },
+ { "name": "user_email", "columns": [ "user_email" ], "unique": false, "options": { "lengths": [ 50, null, null ] } }
+ ],
+ "pk": [ "user_id" ]
+ }
+}
diff --git a/sql/abstractSchemaChanges/patch-watchlist-namespace_title-rename-index.json b/sql/abstractSchemaChanges/patch-watchlist-namespace_title-rename-index.json
new file mode 100644
index 000000000000..2a29e5767344
--- /dev/null
+++ b/sql/abstractSchemaChanges/patch-watchlist-namespace_title-rename-index.json
@@ -0,0 +1,107 @@
+{
+ "comment": "Rename namespace_title index to wl_namespace_title on watchlist (T266228)",
+ "before": {
+ "name": "watchlist",
+ "columns": [
+ {
+ "name": "wl_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "wl_user",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "wl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": false, "default": 0 }
+ },
+ {
+ "name": "wl_title",
+ "type": "binary",
+ "options": { "length": 255, "notnull": true, "default": "" }
+ },
+ {
+ "name": "wl_notificationtimestamp",
+ "comment": "Timestamp used to send notification e-mails and show 'updated since last visit' markers. Set to NULL when the user visits the latest revision of the page, which means that they should be sent an e-mail on the next change.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "wl_user",
+ "columns": [ "wl_user", "wl_namespace", "wl_title" ],
+ "comment": "Special:Watchlist",
+ "unique": true
+ },
+ {
+ "name": "namespace_title",
+ "columns": [ "wl_namespace", "wl_title" ],
+ "comment": "Special:Movepage (WatchedItemStore::duplicateEntry)",
+ "unique": false
+ },
+ {
+ "name": "wl_user_notificationtimestamp",
+ "columns": [ "wl_user", "wl_notificationtimestamp" ],
+ "comment": "ApiQueryWatchlistRaw changed filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "wl_id" ]
+ },
+ "after": {
+ "name": "watchlist",
+ "columns": [
+ {
+ "name": "wl_id",
+ "type": "integer",
+ "options": { "unsigned": true, "notnull": true, "autoincrement": true }
+ },
+ {
+ "name": "wl_user",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": true }
+ },
+ {
+ "name": "wl_namespace",
+ "type": "integer",
+ "options": { "notnull": true, "unsigned": false, "default": 0 }
+ },
+ {
+ "name": "wl_title",
+ "type": "binary",
+ "options": { "length": 255, "notnull": true, "default": "" }
+ },
+ {
+ "name": "wl_notificationtimestamp",
+ "comment": "Timestamp used to send notification e-mails and show 'updated since last visit' markers. Set to NULL when the user visits the latest revision of the page, which means that they should be sent an e-mail on the next change.",
+ "type": "mwtimestamp",
+ "options": { "notnull": false }
+ }
+ ],
+ "indexes": [
+ {
+ "name": "wl_user",
+ "columns": [ "wl_user", "wl_namespace", "wl_title" ],
+ "comment": "Special:Watchlist",
+ "unique": true
+ },
+ {
+ "name": "wl_namespace_title",
+ "columns": [ "wl_namespace", "wl_title" ],
+ "comment": "Special:Movepage (WatchedItemStore::duplicateEntry)",
+ "unique": false
+ },
+ {
+ "name": "wl_user_notificationtimestamp",
+ "columns": [ "wl_user", "wl_notificationtimestamp" ],
+ "comment": "ApiQueryWatchlistRaw changed filter",
+ "unique": false
+ }
+ ],
+ "pk": [ "wl_id" ]
+ }
+}