Goldstine研究所

mosuke5's tech blog

ブログ移転しました。5秒後にリダイレクトします。

PostgreSQL環境でFuelPHPのDBマイグレーションを使う

今更FuelPHP感はあるのだが、
postgresql利用時のFuelPHPのmigration導入について、注意点をまとめた。
でも、結論は納得がいっていない。

0. 前提

下記の環境で行ったものです。
PHP: 5.5.7
FuelPHP: 1.7
Postgresql: 9.4

1. テーブル文字コードの問題

事象

公式サイトのサンプルの通りはじめにapp/migrations/001_example.phpを作り、migrationを実行した。

app/migrations/001_example.phpの作成

<?php
namespace Fuel\Migrations;
class Example
{
    function up()
    {
        \DBUtil::create_table('posts', array(
            'id' => array('type' => 'int', 'constraint' => 5),
            'title' => array('type' => 'varchar', 'constraint' => 100),
            'body' => array('type' => 'text'),
        ), array('id'));
    }
    
    function down()
    {
        \DBUtil::drop_table('posts');
    }
}

マイグレーション実行すると以下のエラーに襲われた。

$ php oil refine migrate
Uncaught exception Fuel\Core\Database_Exception: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "DEFAULT"
LINE 5: )DEFAULT CHARACTER SET utf8;
^ with query: "CREATE TABLE IF NOT EXISTS "migration" (
"type" varchar(25) NOT NULL,
"name" varchar(50) NOT NULL,
"migration" varchar(100) DEFAULT '' NOT NULL
)DEFAULT CHARACTER SET utf8;"

理由

しょっぱなから躓くわけだが…

初めてマイグレーションを実行する際にはマイグレーション管理用のテーブルを作る。
そのテーブルを作るSQLが下記の通り発行されている。

CREATE TABLE IF NOT EXISTS "migration" (
"type" varchar(25) NOT NULL,
"name" varchar(50) NOT NULL,
"migration" varchar(100) DEFAULT '' NOT NULL
)DEFAULT CHARACTER SET utf8;

理由は単純で、postgresqlのcreate tableでは次のdefault構文は利用できないから。

create table xxxx ( ) default character set xxx;

なぜ、利用できない構文のSQLが発行されたのか?
それは単にFuelPHPの問題です。次期バージョンでは解決されることを祈る。

解決方法

解決方法は下記の記事がわかりやすかった。 qiita.com

簡単に言うとdbのコンフィグで、charsetをnullにするとDEFAULT CHARACTER SET xxx部分が発行されない。

'charset' => NULL,

2. PRIMARY KEYの問題

事象

1.の文字コードの問題は解決して、さあもう一度マイグレーションを!と思って実行するもさらなるエラーに阻まれる。

$ php oil refine migrate
Uncaught exception Fuel\Core\Database_Exception: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "("
LINE 2: "id" int(5) NOT NULL,
^ with query: "CREATE TABLE IF NOT EXISTS "users" (
"id" int(5) NOT NULL,
"name" text NOT NULL,
PRIMARY KEY "id" ("id")
);"

理由は1のときと一緒。
postgresqlでは以下の構文は使えないのだ…

PRIMARY KEY "id" ("id")

3. 結局

つまるところFuelPHP(すくなくとも1.7までは)では、postgresqlマイグレーションを行う環境がちゃんと整っていないということ。
しかたないので、マイグレーションSQLは生SQLを書くことにしました。

PRIMARY KEYを後から別途で付与するとか考えたけど、
ほかにも罠がありそうだったので、安全な生SQLを採用しました。
バージョン1.8では直っている?とのことだが、まだdevelopmentだったのでこれも見送り。

うむ。。。

<参考> improve-future.com