はじめに
デプロイを行った際にSQLでエラーが発生しました。
ActionView::Template::Error (Mysql2::Error: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'):
エラーの内容
Google翻訳より…
このバージョンの MySQL はまだ「LIMIT & IN/ALL/ANY/SOME サブクエリ」をサポートしていません
LIMIT句が使用されている箇所の構文が、MySQLのバージョンで使用できない記述になっているようです。
さらにエラーメッセージを見ると、以下のビューを表示する際に引っかかっているようでした。
<%= image_tag @shop.get_shop_image(500,500), class: "w-100 p-1" %>
<%= render 'public/favorite_shops/btn', shop: @shop %>
<%= link_to review_path(@shop), class: "btn btn-outline-info d-grid mt-2" do %>
ショップの口コミを見る (<%= @reviews.count %>)
<% end %>
<% if current_shop == @shop %>
<% unless current_shop.guest_shop? %>
そもそもサブクエリって何だろう…?ということで検索…
サブクエリ(副問い合わせ)とは、クエリの中で使用される別のクエリのことを指します。サブクエリを使用すると、複雑な条件を持つクエリを簡潔に表現でき、データの抽出や加工をより柔軟に行うことができます。
つまり、今回のエラーはINかALLかANYかSOMEのサブクエリが生成されているということ…?
コントローラの確認
先ほどのビューを表示するためのアクション(show)を確認してみます。
class Public::ShopsController < ApplicationController
def show
@member = current_member
@shop = Shop.find(params[:id])
@items = @shop.items.order(id: "DESC").page(params[:page])
# ↓怪しいのはこれ
shop_pre_orders = PreOrder.where(item_id: @items)
@reviews = Review.where(pre_order_id: shop_pre_orders)
.where(is_active: 'true')
@tag_rank = Tag.tag_rank_item
end
end
shop_pre_orders = PreOrder.where(item_id: @items)を見ると、ここで必要なのは@itemsのidのみなのに、@items全てから参照しようとしてしまっています。
これによって、クエリの中にサブクエリが生成されてしまっているのでしょうか…?
確かにSQLの内容を見てもIN(...IN (...))みたいに書かれていたような…
この中のIN(...)がサブクエリということ…?
先ほどのエラーメッセージにも「LIMIT & IN/ALL/ANY/SOME サブクエリ」をサポートしていませんとあったので、INになっている部分が怪しいような気もしてきました。
これを修正していきます。
class Public::ShopsController < ApplicationController
def show
@member = current_member
@shop = Shop.find(params[:id])
@items = @shop.items.order(id: "DESC").page(params[:page])
- shop_pre_orders = PreOrder.where(item_id: @items)
- @reviews = Review.where(pre_order_id: shop_pre_orders)
+ shop_pre_order_ids = PreOrder.where(item_id: @items.pluck(:id)).pluck(:id)
+ @reviews = Review.where(pre_order_id: shop_pre_order_ids)
.where(is_active: 'true')
@tag_rank = Tag.tag_rank_item
end
end
pluckでidのみを呼び出しています。
これでビューを表示してみるとSQL文もさっきの形と変わっていました。
(SQL文を記録していなかったので曖昧な表現になっています。)
これを本番環境で実行してみると…エラーが表示されなくなりました!
おわりに
ツールの違いによって開発環境ではエラーは出ないけど、デプロイ時にエラーが出るということもあるんだなと勉強になりました。
SQLのことも全然分からないまま学習を進めていたので、きちんと調べてみようと思います。