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 < AbstractMysqlAdapter

      def 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
  end

end