使用PostgreSQL时如何安全地将参数传递给ActiveRecord#select()

时间:2013-07-03 16:02:04

标签: ruby-on-rails postgresql

我有一个方法,它采用列名并在我的模型上定义范围。范围使用PostgreSQL窗口函数(如rank()和row_number()),在结果数据集中添加一个额外的列。例如,User.ranked_on_score应添加别名为rank()的{​​{1}}列。

目前,我通过简单的字符串插值(伪代码)来实现它:

score_ranking

考虑到,范围应事先定义为宏,不接受用户的输入,这种方法应该是安全的;尽管如此,我不喜欢它。

我知道window_alias = "#{attr}_rankings" result_alias = "#{attr}_ranking" select("users.*, #{window_alias}.#{result_alias}") .join("JOIN (SELECT id, rank() OVER (ORDER BY #{attr} ASC) as #{result_alias} ...") 方法,但它在我的情况下不起作用。它将参数包装在单引号中,这在sanitize_sql子句中很好,但如果在WHERE子句中使用(PG要求标识符用双引号括起来),则会引发语法错误。

是否有任何内置的标识符清理方法?或者我应该这样离开呢?

1 个答案:

答案 0 :(得分:3)

你试过quote_column_name吗?由于某些原因,它没有文档,但应该做你需要的。

window_alias = quote_column_name("#{attr}_rankings")
result_alias = quote_column_name("#{attr}_ranking")

在幕后,它相当于在使用PostgreSQL时调用PGconn.quote_ident