Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7: ArelにSQLのFILTER句のサポートが追加(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

この改修は、7-0-stableにマージ済みです。

Rails 7: ArelにSQLのFILTER句のサポートが追加(翻訳)

Arelについて

ArelはRuby向けのSQLジェネレータライブラリです。SQLのAST(抽象構文木: Abstract Syntax Tree)アプローチを用いて、複雑なSQLクエリを意味のわかる再利用可能な形で記述できます。

数式の表現に式木(Expression Tree)を使うのと同様に、ArelではSQL構文をノードとして表現します。

Arelでは、counteqnot_eqgtといったさまざまな述語(式木の演算子に相当)を用いてSQLをビルドします。

t = User.arel_table
User.where(t[:first_name].eq('Rohit')).to_sql
#=> "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"first_name\" = 'Rohit'"
t.

SQLのFILTER句について

SQLのFILTER句は、sumavgcountなどの集約関数をWHERE句で拡張します。

COUNT(<式>) FILTER(WHERE <条件>)

Rails 7でFILTERの2項予測(binary prediction)のサポートが追加され、Arelでこのfilter句をサポートおよび生成できるようになりました(#40491)。

改修前

t = User.arel_table
Arel.star.count.filter(t[:first_name].eq("Rohit")).to_sql
#=> NoMethodError: undefined method `filter' for #<Arel::Nodes::Count:0x00007f7f71fd1dd8>

改修後

t = User.arel_table
Arel.star.count.filter(t[:first_name].eq("Rohit")).to_sql
#=> "COUNT(*) FILTER (WHERE \"users\".\"first_name\" = 'Rohit')"

t = Order.arel_table
t[:amount].sum.filter(t(:item_count).lt(2)).to_sql
#=> "SUM(\"orders\".\"amount\") FILTER (WHERE \"orders\".\"item_count\" < 2)"

# With alias
t[:amount].sum.filter(t[:item_count].lteq(3).as('small_orders_total_amount')).to_sql
#=> "SUM(\"orders\".\"amount\") FILTER (WHERE \"orders\".\"item_count\" <= 3 AS small_orders_total_amount)"

原注: このFILTER句を現在サポートしているデータベースは、PostgreSQL(9.4以降)およびSQLite(3.30以降)です。

関連記事

Rails 7: connected_toでロールの指定が必須でなくなった(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。