原始数据库在Rails中查询

gmi*_*ile 15 sql postgresql ruby-on-rails pg ruby-on-rails-4

我试图在rails中运行以下原始查询,只是为了看到它失败:

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

我究竟做错了什么?

我得到的错误从这开始:

Could not log "sql.active_record" event. NoMethodError: undefined method `binary?' for 1:Fixnum
Run Code Online (Sandbox Code Playgroud)

显然,我在[1, 2]某种程度上滥用了绑定参数,但我自己找不到合适的例子.

PS这是最小的失败示例,派生自更高级的查询,无法转换为ActiveRecord调用链.换句话说 - 在构建查询时我不能依赖Arel.

PPS我正在使用rails 4.0.1postgresql 9.3

mu *_*ort 14

我很确定你的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)...
Run Code Online (Sandbox Code Playgroud)

然后,如果我们看一下exec_cache,我们就会看到:

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

所以binds应该是列/值对.PostgreSQL驱动程序希望col是一个列对象,以便它可以询问它的名称是什么以及它应该如何格式化val,log调用该信息用于exec_query在Rails日志中生成漂亮且易读的内容.实验的一点建议您可以使用nilcol,一切都是幸福的.

这意味着我们已经转向了这个:

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

底层驱动程序可能知道或者可能不知道如何处理[1,2]数组,我只有Rails3可以测试PostgreSQL扩展,它不喜欢[1,2].如果Rails4也不喜欢该数组,那么你可以逐个传递参数:

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