つらい思いをした
テストコードが破城しているプロジェクトのシステム(Laravel5.6)に対して、とりあえず正常にテストが走るようにリファクタしようと思い、
まずはテストのDBをSQLiteに設定して個々のテストコードを直そうと思った矢先、マイグレーションの書き方が不味かったらしく、
SQLiteの仕様でこけました。
のでとりあえずマイグレーションの記述をSQLiteでも対応できるように直しました。
SQLiteは1回の変更でdropColumn
やrenameColumn
を複数回呼び出すことはできない
どうやらSQLiteは1回の変更でdropColumn
やrenameColumn
を複数回呼び出すことはできないらしい
ので以下のようにマイグレーションを記述していると、MySQLでは正常に処理されるがSQLiteではエラーが発生する。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DeleteNameAndKanaOnUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->dropColumn('name');
$table->dropColumn('kana');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('user', function (Blueprint $table) {
$table->string('name');
$table->string('kana');
});
}
}
以下エラー内容
BadMethodCallException: SQLite doesn't support multiple calls to dropColumn / renameColumn in a single modification.
なので複数の処理は以下のように修正する必要があります。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DeleteNameAndKanaOnUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->dropColumn('name');
});
Schema::table('user', function (Blueprint $table) {
$table->dropColumn('kana');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('user', function (Blueprint $table) {
$table->string('name');
});
Schema::table('user', function (Blueprint $table) {
$table->string('kana');
});
}
}
テーブル作成時はNOT NULL制約
を指定できるが、列追加する際はNOT NULL制約
をつけることができない
テーブルを作成するときはNOT NULL制約
をつけることはできるみたいですが、後で列を追加するときにNOT NULL制約
をつけることはできないみたいです。
なので以下のように書いている場合、エラーが発生します。
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->string('hoge');
});
Schema::table('user', function (Blueprint $table) {
$table->string('huga');
});
}
以下エラー内容
PDOException: SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL
もしNOT NULL制約
でない場合は以下のようにデフォルトでNULLを入れてやれば大丈夫のようです
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->string('hoge')->nullable();
});
Schema::table('user', function (Blueprint $table) {
$table->string('huga')->nullable();
});
}
もしNOT NULL制約
があるカラムの場合は以下のように一旦NULLを許可して、後でNOT NULL制約にする必要があるみたいです
(もっと他にやり方がありそうな気もしますが・・・)
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->string('tell')->nullable();
});
Schema::table('user', function (Blueprint $table) {
$table->string('tell')->nullable(false)->change();
});
}
おわり
- そもそもテストDBにSQLiteを設定するのがいいのかわからない・・・