Rails での生の DB クエリ 質問する

Rails での生の DB クエリ 質問する

Rails で次の生のクエリを実行しようとしていますが、失敗します。

query   = 'SELECT * FROM users WHERE id IN ($1);'
results = ActiveRecord::Base.connection.exec_query(query, "My query", [ [1,2] ]);

何が間違っているのでしょうか?

私が受け取ったエラーは次のように始まります:

Could not log "sql.active_record" event. NoMethodError: undefined method `binary?' for 1:Fixnum

明らかに、私は[1, 2]何らかの方法でバインドパラメータを誤用していますが、適切な例を自分で見つけることができませんでした。

PS これは、ActiveRecord の呼び出しチェーンに変換できない、はるかに高度なクエリから派生した、最小限の失敗例です。言い換えると、クエリを構築するときに Arel に頼ることはできません。

PPS私は使用しておりrails 4.0.1postgresql 9.3

ベストアンサー1

NoMethodErrorはログ記録から来ていると思います。exec_query、次のようになります:

def exec_query(sql, name = 'SQL', binds = [])
  log(sql, name, binds) do
    # call exec_no_cache(sql, binds) or exec_cache(sql, binds)...

次に、exec_cache、次のようになります:

def exec_cache(sql, binds)
  #..
  @connection.send_query_prepared(stmt_key, binds.map { |col, val|
    type_cast(val, col)
  })

したがって、 はbinds列/値のペアであるはずです。PostgreSQL ドライバーは、 がcol列オブジェクトであることを期待しているため、 にその名前と のフォーマット方法を尋ねることができます。その情報は、の呼び出しvalによって使用され、 Rails ログにきれいで人間が読めるものを生成します。少し実験してみると、を として使用でき、すべてがうまくいくことがわかります。logexec_querynilcol

つまり、私たちは次の段階に進みました:

exec_query(
  'SELECT * FROM users WHERE id IN ($1)',
  'my query',
  [ [nil, [1,2]] ]
)

基盤となるドライバーは配列の処理方法を知っている場合と知らない場合があります[1,2]。テストに使用できるのは PostgreSQL 拡張機能を備えた Rails3 のみで、 は使用されません[1,2]。Rails4 でも配列が使用できない場合は、引数を 1 つずつ渡すことができます。

exec_query(
  'SELECT * FROM users WHERE id IN ($1, $2)',
  'my query',
  [ [nil,1], [nil,2] ]
)

おすすめ記事