Manual:スキーマの変更

This page is a translated version of the page Manual:Schema changes and the translation is 82% complete.

このページは開発作業の一部としてデータベースのレイアウトを変更する必要がある人々のために、MediaWiki コアとその拡張機能のためのスキーマ変更パッチを構築する方法を説明するヘルプ ページです。

用語集

  • スキーマ - MediaWiki の現在のデータベース レイアウト
  • スキーマの変更 - スキーマ移行のアトミックな部分で、コミットによって追加されるもの。 例えば、「テーブル foo を追加」、「テーブル baz からカラム bar を削除」などです。
  • データベース管理システム (DBMS) - MediaWiki のデータベースを扱う基盤技術。 MediaWiki コアでサポートされているものは以下の通りです: MySQLSQLitePostgreSQL。 拡張機能を使用するとより多くなる可能性があります。
  • データ定義言語 (DDL) - スキーマやスキーマ変更を定義する構文 (DBMS によって異なる場合がある)。 例: 「ALTER TABLE」「DROP COLUMN」。 「.sql」ファイルとして保存されます。
  • データベース抽象レイヤー (DBAL) - DBMS に依存しないデータベース スキーマおよびスキーマ変更定義と実際の DDL との間の橋渡し。

概要

各スキーマの変更では、2 つの部分を処理する必要があります。 第一に、新しいインストレーションは古いスキーマではなく新しいスキーマを持つ必要があり、第二に、古いインストレーションは新しいスキーマにアップグレードできる必要があります。 最初のパートでは、スキーマ DDL ファイル (tables.sql という名前で保存) を修正し、2 番目のパートでは、「ALTER TABLE」パッチを提供し、それをアップデーターのロジックに配線します。

DBMS ごとに 1 つずつある専用 DDL を、1 つの抽象スキーマに移行している真っ最中です。 テーブルによっては、複数の生の SQL ファイルを変更したり、1 つの json ファイルのみを変更し、メンテナンス スクリプトを使用して SQL ファイルを生成することがあります。

手動 (廃止予定)

メインのページ: Manual:SQL patch file

2020年まで使用されるこの方式では、スキーマを変更する際に:

  1. 2 か所にある tables.sql を変更 (MySQL は maintenance/tables.sql、PostgreSQL は maintenance/postgres/tables.sql)
  2. MySQL の現行インストレーションのアップグレード パスとして、スキーマ変更 DDL ファイルを作成し、maintenance/archives/ に配置します
    • 他の種類の DBMS でそのパッチが動作しない場合は、専用のパッチを作成する必要があります。 例えば、SQLite には ALTER TABLE がありません。つまり、一時テーブルを作成してデータをコピーし、古いテーブルを削除して、新しいテーブルの名前を古い名前に変更する必要があるのです。
  3. これらの DDL ファイル (ステップ 2 より) を MysqlUpdater, SqliteUpdater, PostgresUpdater に配線します

自動的な生成

MediaWiki バージョン:
1.35

MediaWiki コアのすべてのテーブルの抽象スキーマは「sql/tables.json」にあります。 この抽象化では、Doctrine DBAL ライブラリを使用して DDL ファイルを生成しています。 On your local working MediaWiki install, with the relevant extension installed, you should:

  1. tables.json 構造を変更します。
  2. メンテナンス スクリプトを実行し、3 つの DDL ファイルを生成します:
    php maintenance/run.php generateSchemaSql --json sql/tables.json --sql sql/ --type=all
    
  3. 抽象スキーマ変更の .json ファイル (下記を参照) を作成し、sql/abstractSchemaChanges/ ディレクトリに配置します
  4. メンテナンス スクリプトを使用してスキーマ パッチを構築します。例:
    php maintenance/run.php generateSchemaChangeSql --json sql/abstractSchemaChanges/patch-logging-rename-indexes.json --sql sql/ --type=all
    
  5. MysqlUpdater, SqliteUpdater, PostgresUpdater に追加します
  6. パッチを作成する際には、変更点と自動生成された DDL ファイルを git でチェックインする (コミットに含める) ことを忘れないでください。

パッチの例

抽象スキーマの例

[
	{
		"name": "actor",
		"comment": "The \"actor\" table associates user names or IP addresses with integers for the benefit of other tables that need to refer to either logged-in or logged-out users. If something can only ever be done by logged-in users, it can refer to the user table directly.",
		"columns": [
			{
				"name": "actor_id",
				"comment": "Unique ID to identify each actor",
				"type": "bigint",
				"options": { "unsigned": true, "notnull": true, "autoincrement": true }
			},
			{
				"name": "actor_user",
				"comment": "Key to user.user_id, or NULL for anonymous edits",
				"type": "integer",
				"options": { "unsigned": true, "notnull": false }
			},
			{
				"name": "actor_name",
				"comment": "Text username or IP address",
				"type": "binary",
				"options": { "length": 255, "notnull": true }
			}
		],
		"indexes": [
			{ "name": "actor_user", "columns": [ "actor_user" ], "unique": true },
			{ "name": "actor_name", "columns": [ "actor_name" ], "unique": true }
		],
		"pk": [ "actor_id" ]
	}
]

Data types

  • Doctrine DBAL の既定値は "notnull": true です。 null 可能 (nullable) にしたい場合は、"notnull": false で明示的に指定します。
  • Doctrine DBAL のカラム型の一覧はこちらにあります: https://github.com/doctrine/dbal/blob/3.3.8/src/Types/Types.php
    • Since MediaWiki 1.38, Doctrine DBAL types which are not listed in the following table are unavailable.
共通の Doctrine DBAL 型とそれらと同等の型
Doctrine DBAL/抽象スキーマ MySQL SQLite PostgreSQL Version
bigint BIGINT BIGINT BIGSERIAL (自動インクリメントの場合)/BIGINT
binary VARBINARY BLOB TEXT
blob TINYBLOB/BLOB/MEDIUMBLOB/LONGBLOB (サイズに基づく) BLOB TEXT
datetimetz DATETIME DATETIME TIMESTAMPTZ (1.36+)
TIMESTAMP(0) WITH TIME ZONE (1.35)
float FLOAT/DOUBLE PRECISION (if "doublePrecision":true) (1.36+)
DOUBLE PRECISION (1.35)
DOUBLE PRECISION FLOAT/DOUBLE PRECISION (if "doublePrecision":true) (1.36+)
DOUBLE PRECISION (1.35)
integer INT INTEGER INT
smallint SMALLINT SMALLINT SMALLINT
string VARCHAR VARCHAR VARCHAR
text TINYTEXT/TEXT/MEDIUMTEXT/LONGTEXT (サイズに基づく) CLOB TEXT
mwenum ENUM TEXT TEXT
1.36
mwtimestamp BINARY(14)/VARBINARY(14) (if "allowInfinite":true) BLOB TIMESTAMPTZ
1.36
mwtinyint TINYINT SMALLINT SMALLINT
1.36

In particular:

  • For timestamps, use mwtimestamp datatype (phab:T42626).
  • Instead of VARCHAR or CHAR, use VARBINARY or BINARY (otherwise you have to deal with encodings in databases)
  • Unless you actually need the negative value, use UNSIGNED for any type of integer value to double its capacity.
  • Using ENUM is highly discouraged (phab:T119173).
  • Use mwtinyint instead of boolean for Postgres compatibility (phab:T257755#6863029).

抽象スキーマの変更

スキーマの変更については、テーブルの抽象スキーマの変更前と変更後のスナップショットを json ファイルで作成します (1 テーブルにつき 1 つのスキーマ変更でお願いします)。 その後、同様の方法でメンテナンス スクリプトを実行すると、2 つのテーブル間の差分を取り、スキーマ変更用の DDL ファイルを自動生成します。

抽象スキーマの変更の例

{
	"before": {
		"name": "actor",
		"columns": [
			{
				"name": "actor_id",
				"type": "bigint",
				"options": { "unsigned": true, "notnull": true, "autoincrement": true }
			},
			{
				"name": "actor_user",
				"type": "integer",
				"options": { "unsigned": true, "notnull": false }
			},
			{
				"name": "actor_name",
				"type": "binary",
				"options": { "length": 255, "notnull": true }
			}
		],
		"indexes": [
			{ "name": "actor_user", "columns": [ "actor_user" ], "unique": true },
			{ "name": "actor_name", "columns": [ "actor_name" ], "unique": true }
		],
		"pk": [ "actor_id" ]
	},
	"after": {
		"name": "actor",
		"columns": [
			{
				"name": "actor_id",
				"type": "bigint",
				"options": { "unsigned": true, "notnull": true, "autoincrement": true }
			},
			{
				"name": "actor_user",
				"type": "bigint",
				"options": { "unsigned": true, "notnull": false }
			},
			{
				"name": "actor_name",
				"type": "binary",
				"options": { "length": 255, "notnull": true }
			}
		],
		"indexes": [
			{ "name": "actor_user", "columns": [ "actor_user" ], "unique": true },
			{ "name": "actor_name", "columns": [ "actor_name" ], "unique": true }
		],
		"pk": [ "actor_id" ]
	}
}

2 つのテーブルは、「actor_user」の型が「integer」から「bigint」に変更されている点を除いて同じです。 変更自体を抽象化するのではなく差分を取る理由は、SQLite はほとんどの場合 ALTER TABLE を持っておらず、つまり DBAL は一時テーブルを使ってスキーマ変更 DDL ファイルを構築するためにスキーマを知る必要があるからです。

Structure tests

MediaWiki provides the AbstractSchemaTestBase class that can be used to test validity and consistency of the schema. Tests in this class verify that the asbtract database schema validates successfully against its schema, and that the autogenerated SQL is up-to-date.

If you would like to enable these tests in an extension, create a test class that extends AbstractSchemaTestBase and override its abstract methods to specify the location of the schema. See example patches.