Предложение WHERE Postgresql добавляет '' вокруг?

Этим утром я переключился на postgresql, и теперь мой выбор больше не работает.

То, что я пытаюсь сделать, очень просто:

shirt_ids = "1,5,6" # String generated by javascript
Shirt.where("id in (?)", shirt_ids)

Это дает мне:

PG::Error: ERROR:  invalid input syntax for integer: "1,5,6"
LINE 1: SELECT "shirts".* FROM "shirts"  WHERE (id in ('1,5,6'))

Это работает, хотя:

Shirt.where("id in (#{shirt_ids})")

Но, как известно, небезопасно.

Я использую:

pg (0.13.2 x86-mingw32)
rails (3.2.2)

База данных Postgresql — самая новая версия, я установил ее сегодня утром.

Спасибо за помощь. ^


person Stephan1990    schedule 07.05.2012    source источник


Ответы (1)


Я считаю, что Postgres ожидает массив, а не строку для функции IN. Если вы преобразуете свою строку в массив, она должна работать:

shirt_ids = "1,5,6"
Shirt.where('id in (?)', shirt_ids.split(','))

Кроме того, вы можете сделать это, что выглядит немного чище:

Shirt.where(:id => shirt_ids.split(','))
person MrTheWalrus    schedule 07.05.2012
comment
Спасибо за быструю помощь :) - person Stephan1990; 07.05.2012
comment
Может быть, слишком быстро ... Я понял, что мой первоначальный ответ «работает», но на самом деле возвращает только один объект. Отредактированный соответственно, этот должен быть в порядке. - person MrTheWalrus; 07.05.2012
comment
Точнее говоря, ActiveRecord видит ? во фрагменте SQL и строку в качестве значения, а затем преобразует эту строку Ruby в строковый литерал SQL '1,2,3'. Я думаю, что shirt_ids.split(',').map(&:to_i) будет безопаснее. - person mu is too short; 07.05.2012
comment
В любом случае довольно уродливо по сравнению с простым Shirt.where("id in (?)", shirt_ids) или даже более простым (хотелось бы, чтобы это работало) Shirt.where(id: in(shirt_ids)). Думаю, я пойду с Shirt.where(id: shirt_ids.split(",")). @muistooshort Зачем .map(&:to_i) делать это безопаснее? Разве postgresql автоматически не выдает ошибку, если какой-нибудь злой хакер попытается отправить строку? (Что очень просто, так как это происходит из формы) - person Stephan1990; 07.05.2012
comment
@Stefano: значения id являются целыми числами и должны быть указаны как таковые, обычно вы можете избежать использования '1' вместо 1, но не всегда. Если вы используете массив строк, вы получаете id in ('1','2','3'), когда хотите id in (1,2,3). - person mu is too short; 07.05.2012