スキーマの変更にデータベースを追随させるsfPropelSqlDiffPlugin

データベースを用いたアプリケーションでは、開発途中に仕様変更などでデータベースを変更したい事があります。 通常は、ALTER等のSQLを駆使して差分のSQLを作成し、適用しますが、意外と面倒です。 propel-build-sqlタスクでは、CREATE TABLE文は作成してくれますが、既存のテーブル構造をかえる為のでALTER文は生成しません。 この作業を自動化してくれるのが、sfPropelSqlDiffPluginです。 sfPropelSqlDiffPluginは現在のconfig/schema.ymlとデータベースを比較して、差分のALTER文を生成するプラグインします。以下の図が概要になります。

sfPropelSqlDiff

sfPropelSqlDiffPluginは、./symfonyコマンドに、以下のタスクを追加します。

  • propel:build-sql-diff > 差分SQLを生成します。
  • propel:insert-sql-diff > 上のSQLを実行します。
  • propel:build-all-diff > propel:build-modelのあとpropel:insert-sql-diffします。

プラグインページ

本家のプラグインページ

インストール

$ symfony plugin-install http://plugins.symfony-project.com/sfPropelSqlDiffPlugin
$ symfony cc

利用例

以下のようなschema.ymlのデータベースが存在しているとします:

    users:
      id:
      name:
        type: varchar
        size: 255
      updated_at:

このスキーマを以下のように変えて、年齢(age)を追加します:

    users:
      id:
      name:
        type: varchar
        size: 255
      age:
        type: integer
        default: 1
      updated_at:

この状態で、差分sqlを生成します。

./symfony propel:build-sql-diff

するとdata/sql/diff.sqlが生成されます:

ALTER TABLE `users` ADD `age` INTEGER DEFAULT 1;

中には正しいALTER文が生成されています。これを適用するには以下のようにします:

./symfony propel:insert-sql-diff

本当は、propel:build-sqlせずにpropel:insert-sqlしても良いのですが、確認のため作業を分離しています。

次に年齢のデフォルトを18にしてみます。以下のように、schema.ymlを修正して:

  users:
    id:
    name:
      type: varchar
      size: 255
    age:
      type: integer
      default: 18
    updated_at:

タスクを実行します。

./symfony propel:insert-sql-diff

すると以下のような意図通りのALTER文が生成されます。

/* old definition: int(11) DEFAULT '1'
   new definition: INTEGER default 18 */
ALTER TABLE `users` CHANGE `age` `age` INTEGER DEFAULT 18;

次にageを消して、birthdayを追加します:

 users:
    id:
    name:
      type: varchar
      size: 255
    birthday:
      type: date
    updated_at:

sfPropelSqlDiffPluginは存在しないテーブル、フィールド、インデックス、キーのためにCREATE、なくなってしまったものにはDROP文を発行します。 従って以下のようになります。

ALTER TABLE `users` ADD `birthday` DATE;
ALTER TABLE `users` DROP `age`;

これは意図通りの結果です。

次に、usersテーブルをmemberテーブルに変えてみます:

  member:
    id:
    name:
      type: varchar
      size: 255
    birthday:
      type: date
    updated_at:

以下のようにCREATE TABLEDROP TABLEが生成されてしまいます:

CREATE TABLE `member`
(
	`id` INTEGER  NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(255),
	`birthday` DATE,
	`updated_at` DATETIME,
	PRIMARY KEY (`id`)
)Type=InnoDB;
DROP TABLE `users`;

これではusersテーブルの内容が削除されてしまいますので注意が必要です。


sfPropelSqlDiffPluginは非常に便利なプラグインですが、差分SQLは完璧ではなく、正しく変換できないことがあるのでpropel-insert-sql-diffをいきなり実行する前にpropel:build-sql-diffを実行して、生成されるdata/sql/diff.sqlをみて、発行されるSQLを確認してから実行するようにしてください。

Leave a Reply

Name (required)
Mail (will not be published) (required)

Your Comments:

Spam Protection by WP-SpamFree