2013-06-04 4 views
0

У меня есть ситуация, когда мне нужно разрешить создание SQL вручную из формы. У меня есть что-то вроде этого:Проверка SQL в where where

SomeModel.where("id in (#{custom_sql})") 

где custom_sql является оператор выбора следующим образом:

SELECT u.id FROM some_model u WHERE country_iso = 'AU' 

Я хочу, чтобы иметь возможность поймать исключение StatementInvalid, возникающее, когда недопустим SQL в WHERE , но я не могу понять, как это сделать.

begin 
    SomeModel.where("id in (#{custom_sql})") 
rescue 
    puts "Error" 
end 

Но он продолжает падать без ошибок. Тем не менее в rails c, когда я делаю User.where("id in (#{custom_sql})"), он будет корректно ошибочным. Есть идеи?

+0

Считаете ли вы использование объединений? Кажется, это идеальное решение для вашего образца кода. –

ответ

0

Во-первых, это SQL-инъекция в лучшем виде. вы должны пересмотреть все, что вы хотите выполнить.

во-вторых, User.where возвращается отношение. отношения ленивы. ленивые заявления еще не выполнены. так что если вы делаете User.where(...).all, это должно помочь.

+0

Да, это дыра в безопасности, которую мы знаем. Это функция только для администратора и использует пользователя только для чтения, который может выбирать только из нескольких таблиц. Это скорее инструмент запросов. Проблема с .all в том, что этот запрос будет вызван как отложенное задание на рабочем компьютере. Если я вызову .first, будет ли он запущен мой сервер приложений? –

+0

Хотя верно, что 'User.where()' возвращает 'ActiveRecord :: Relation' и' User.where (...). All' возвращает массив, недопустимый поиск в любом сценарии будет вызывать 'ActiveRecord: : Ошибка StatementInvalid'. – zeantsoi

+0

@zeantsoi нет, это не так. попробуйте это в своем контроллере: 'render text: User.where ('murks'). to_s' – phoet

2

Проверьте правильность вашего оператора SQL с помощью ActiveRecord::Base.connection.execute. Он выдаст ошибку, если ваш оператор недействителен.

begin 
    ActiveRecord::Base.connection.execute custom_sql 
    User.where("id in (#{custom_sql})") 
rescue 
    puts "Error" 
end 
1

Прежде всего, ваш пример является неясным или вводящие в заблуждение (вероятно, из-за ваших усилий, чтобы замаскировать свои реальные имена модели)

Потому что, если вы действительно хотите, чтобы запустить сценарий вы предлагаете, ваш результирующий запрос будет быть

select * from some_model where id in (select u.id from some_model u where country_iso = "AU" 

(игнорируя тот факт, что ваш country_iso поля двусмысленно) Вы просто работаете

SomeModel.where country_iso: "AU" 

Так что вам нужно уточнить ваш пример и правильно проиллюстрировать вашу проблему, потому что, хотя @zeantsoi предлагает способ помочь вам подтвердить ваши утверждения, я согласен с @phoet, что вы, вероятно, приближаетесь к ситуации неправильно.

+0

Договорились, что усилия по запутыванию имен моделей затрудняют понимание фрагментов кода.Это поможет обновить фактический пример ошибочного запроса SQL, который вы хотите поймать. – zeantsoi