原始数据库在Rails中查询

时间:2014-01-28 18:07:00

标签: sql ruby-on-rails postgresql ruby-on-rails-4 pg

我正在尝试在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]绑定参数,但我自己找不到合适的例子。

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

P.P.S。我正在使用rails 4.0.1postgresql 9.3

2 个答案:

答案 0 :(得分:13)

我很确定你的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成为列对象,以便它可以询问它的名称是什么以及它应该如何格式化vallog调用exec_query使用该信息。 {1}}在Rails日志中生成一些漂亮且易读的东西。一些实验表明,您可以使用nil作为col,一切都很愉快。

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

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

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

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

答案 1 :(得分:2)

我最近遇到了类似的问题。事实证明,在where in (?)中,ActiveRecord期待一个字符串,而不是一个数组。所以你可以尝试传入一串逗号分隔的ID,这应该可以解决问题。