Передача данных между запросами SQL и отдельным файлом Ruby

Я использую tiny_tds для извлечения данных из нескольких разных баз данных. На данный момент у меня есть файл Ruby с несколькими методами, каждый из которых посвящен определенному запросу (поскольку базы данных очень большие, и не все сценарии, которые я использую, требуют одинакового вида/количества данных). Чтобы все было чище и проще, я хотел выделить сами SQL-запросы в один файл, а не встраивать их в файл Ruby, содержащий функции. Но SQL-запросы зависят от определенных полей, имеющих определенные значения. По сути, я пытаюсь отправить переменную в SQL-запрос, получить данные на основе этого конкретного значения в поле и передать эти данные обратно в файл Ruby.

Итак, упрощенная версия того, что я сейчас делаю, такова:

def initialize
    @client = TinyTds::Client.new(:username => '', :password => '', :host => '', timeout: 0)
end

def query_example(value)
    results = @client.execute("SELECT DISTINCT field1, field2, field3
        FROM db
        WHERE field1 = '#{value}'
    ")
    results.each {|x| return x}
end

Сценарий вызывает функцию query_example(value) и на основе переменной value получает соответствующие данные для этого случая.

Но я хотел бы, по сути, иметь один файл, в котором нет ничего, кроме необработанных SQL-запросов, например:

SELECT DISTINCT field1, field2, field3
    FROM db
    WHERE field1 = '#{value}'

где #{value} заполняется внешним значением, переданным ему (хотя я не уверен, как здесь будет объявлен такой подстановочный знак). Скажем, я сохраняю этот файл как «query.sql», тогда я просто хочу прочитать этот файл в функции Ruby, например:

def query_example(value)
    query = File.read("query.sql")
    results = @client.execute(query)
end

Проблема в том, что я на самом деле не знаю, как передать этот аргумент value в сам файл SQL, чтобы данные, извлекаемые с помощью команды execute, были конкретными данными для этого значения. Возможно ли это с помощью tiny_tds, или tiny_tds просто не предназначена для такого двустороннего взаимодействия между внешними SQL-запросами и функциями Ruby, которые их вызывают? Я открыт для рассмотрения других библиотек SQL, я просто очень не знаком с опциями, так как в основном имею дело с Ruby.


person lumos    schedule 18.01.2019    source источник
comment
ВНИМАНИЕ. Будьте предельно осторожны при составлении запросов вручную и по возможности используйте подготовленные операторы со значениями-заполнителями. В нем есть огромная дыра для SQL-инъекций, которую необходимо исправить.   -  person tadman    schedule 19.01.2019
comment
Вы можете использовать тонкий слой базы данных, такой как Sequel, который поможет оградить вас от особенностей низкоуровневого Драйвер ТДС.   -  person tadman    schedule 19.01.2019


Ответы (1)


Вы можете использовать метод format для замены заполнителей фактическими значениями. Вот самый простой пример:

template = "Hello, %{name}!"
format(template, name: "World")
=> "Hello, World!"

И ваш код может выглядеть так:

# query.sql
SELECT DISTINCT field1, field2, field3
FROM db
WHERE field1 = '%{value}'

# ruby file
def query_example(value)
  query = File.read("query.sql")
  results = @client.execute(format(query, value: value))
end
person Michał Młoźniak    schedule 19.01.2019