Search code examples
sqlrubyruby-on-rails-5

SQL Sub Query is being appended as a string instead of a proper query


I have been trying to use Rails find_by_sql functionality and pass a Sub Query as a parameter. The sub query is being appended to the parent query as a string instead of a proper query. Below is my SQL.

sql =  <<~SQL
    SELECT
      column_1,
      column_2
    FROM (
        ?
      ) AS sample_table
    GROUP BY
      column_1,
      column_2
SQL

somemodel = SomeModel.find_by_sql [sql, someotherquery.to_sql]

The someotherquery.to_sql is as below

SELECT * FROM someothertable WHERE column_1 in ('test') and column_2 in ('new test')

This when append to the parent query results in the below SQL which has the subquery as a String instead of a proper query.

SELECT
      column_1,
      column_2
    FROM (
        'SELECT * FROM someothertable WHERE column_1 in (''test'') and column_2 in (''new test'')'
      ) AS sample_table
    GROUP BY
      column_1,
      column_2

Solution

  • The thing is that, that the syntax:

    sql  = "select * from model where column = ?"
    data = Model.find_by_sql [sql, 'some value']
    

    was designed to prevent SQL injection. What you are trying to do here is exactly the thing that this syntax is trying to prevent. That is why it doesn't work.

    You have to replace the question mark manually in your SQL before you send it to the find_by_sql method.

    eg during the creation of the SQL string:

    sql =  <<~SQL
        SELECT
          column_1,
          column_2
        FROM (
            #{someotherquery.to_sql}
          ) AS sample_table
        GROUP BY
          column_1,
          column_2
    SQL
    

    or by doing replace:

    sql.sub!('?', someotherquery.to_sql)
    

    Finally, now you can send it to find_by_sql to execute the query

    somemodel = SomeModel.find_by_sql(sql)