Pure RubyでSQLを書く

Rubyは柔軟な言語であり、さまざまなDSLを作成できます。 SQLクエリ(SELECT)のDSLを可能な限りオリジナルに近いものにするというアイデアがありました。 うまくいくようです。 結果の作品はBorodaと呼ばれます。 以下はコード例です。



 「ボロダ」が必要

 sql = Boroda.build do
   from:posts ,: users
  投稿を選択*
  ここで、(posts.author_id == users.id)&(users.name == 'Vlad Semenov')
終わり


取得するもの:



SELECT posts.*

FROM posts, users

WHERE (posts.author_id = users.id) AND (users.name = 'Vlad Semenov')








誰も理解していない場合は、純粋なRubyでSQLクエリを記述します。 それでは、もっと複雑なものを試してみましょう。



  min_rating = 5
 sql = Boroda.build do
   from:posts =>:p
  左結合:コメント=>:c
   on c.post_id == p.id
   p.id、p.title、p.content、c.id.count =>:comment_countを選択します
   p.idによるグループ化
   where(p.title.like '%programming%')|  #「プログラミング」ヘッダーを含むすべての投稿を選択
         (p.rating> min_rating)#または5以上の評価
   p.created_at.descによる注文
  制限10
  オフセット20
終わり


取得するもの:



  SELECT p.id、p.title、p.content、COUNT(c.id)AS comment_count
 pからの投稿から
 LEFT JOINコメントAS c
 ON c.post_id = p.id
 WHERE(p.title LIKE '%programming%')または(p.rating> 5)
 GROUP BY p.id
 ORDER BY p.created_at DESC
制限10
オフセット20 




次に、Borodaを使用してクエリを作成する方法について説明します。 いくつかの技術的な問題により、SQLステートメントの順序を変更する必要がありました。 まず、から行かなければなりません。 その中で、テーブル名はシンボルとして示されています。 2番目の例で行われているように、ハッシュの形式でリストを指定することにより、テーブルのエイリアスを指定できます。 参加する必要があります。 次の形式でメソッドを呼び出す可能性のある順序を書き留めておくと簡単です。



 テーブルから
 [[左|右] [外側|内側]結合テーブル
条件付き| 列を使用する
 [..]]
 [列を選択]
 [どこ条件
 | 列ごとにグループ化する
 | 状態がある
 | 列順
 | 制限数
 | オフセット番号] * 




つまり、最後のグループのすべてのメソッドを任意の順序で呼び出すことができます。 Borodaは、正しいSQLクエリを取得するよう注意します。



ここで、どこでどのように使用されるかについて詳しく説明します。 次のステートメントの使用は、SQLの場合とまったく同じ意味を持ちます。

+、-、*、/、>、<、> =、<=。



演算子のオーバーロードに関するRubyの制限のいくつかのために、私は少しひねりが必要でした。

  a == b#=> a = b
 a <=> b#=> a <> b
 (a)&(b)#=>(a)AND(b)
 (a)|  (b)#=>(a)OR(b)


これは非常に重要です。最後の2つの演算子を使用するときは、オペランドを括弧で囲む必要があります。そうしないと、SQLクエリで期待どおりの結果が得られない場合があります。 これは、Rubyではこれら2つの演算子の優先度が高いためです。



Borodaは現在、SELECTクエリ用のSQLを生成する小さなモジュールです。 モジュールコードはGitHubにあります 。 誰かが欲望を持っているなら、ボロダは宝石になることができます。



このコードはまだ十分にテストされておらず、SQLインジェクションに対して不安定になる可能性があるため、production'eでこのコードを使用することはお勧めできないことを事前に警告します。



このDSLについてのあなたの意見を聞いて、改善のための有用なヒントを得るのは非常に興味深いです:)



All Articles