Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INDEX `xxx` TO `yyy`' at line 1: ALTER TABLE `zzz` RENAME INDEX `xxx` TO `yyy`
とあるRuby製Webアプリの移管作業で発生したトラブルです。
データベースを作成するため、マイグレーションを実行したら、以下のようなエラーが発生しました。
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INDEX `xxx` TO `yyy`' at line 1: ALTER TABLE `zzz` RENAME INDEX `xxx` TO `yyy`
エラーの内容は、Rename Indexを実行したけど、SQLシンタックスエラーだよと。
Rename Indexは、MySQL5.7で追加された新機能ですが、当環境は、MySQL5.6を使用しています。
つまり、MySQL5.6には存在しないクエリを、ActiveRecordが発行したため、エラーになったわけです。
今までは動いていたと、聞いていたので、どういうことかと思い調べてみたら、ActiveRecordのバージョン5未満には、MySQLのバージョン判定に問題があることが、わかりました。
問題のコードは以下です。
/Project/Top/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/mysql2_adapter.rb
module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter < AbstractMysqlAdapterdef full_version
@full_version ||= @connection.info[:version]
end
end
end
end
これは、サーバ側のバージョンを取得せず、MySQLクライアントのバージョンを取得しているのです。
そこで、libmysql-devのバージョンを調べてみると、以前の環境は、5.5で、現在の環境は、5.7でした。
どうやら、libmysql-devのバージョンを取得し、MySQL5.7と判定して、MySQL5.7向けのクエリを作成してしまっているようです。
libmysql-devのバージョンをダウングレードができなかったので、問題のコードにパッチをあてて、サーバのバージョンを取得するように修正しました。
パッチは、こちらです。ネームスペース(module, class, method)を同一にして、上書きします。
/Project_Top/config/initializers/activerecord_patch.rb
module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter < AbstractMysqlAdapter
def full_version
@full_version ||= @connection.server_info[:version]
end
end
end
end
パッチを読み込むようにします。上書きするので、読み込みのタイミングは最後になるように、`Padrino.after_load do`で、実行します。
config/boot.rb
Padrino.after_load do
Dir.glob(Padrino.root + "/config/initializers/*.rb").each do |initlib|
load initlib
endend