Why are stored procedures still not supported in Rails (3+)?

假如想象 提交于 2019-12-04 11:24:18

问题


I am familiar with the long standing love-hate relationship between Ruby on Rails, DB(MS)-drivers and Stored Procedures and I have been developing Rails applications since version 2.3.2.

However, every once in a while a situation arises where a SP is simply a better choice than combining data on the (much slower) application level. Specifically, running reports which combines data from multiple tables is usually better suited for a SP.

Why are stored procedures still so poorly integrated into Rails or the MySQL gem. I am currently working on a project with Rails 3.0.10 and MySQL2 gem 0.2.13 but as far as I can see, even the latest Edge Rails and MySQL gem 0.3+ still throw tantrums when you use SPs.

The problem which has been, and still is, is that the database connection is lost after a SP is called.

>> ActiveRecord::Base.connection.execute("CALL stored_proc")
=> #<Mysql::Result:0x103429c90>
>> ActiveRecord::Base.connection.execute("CALL stored_proc")
ActiveRecord::StatementInvalid: Mysql::Error: Commands out of sync; 
[...]
>> ActiveRecord::Base.connection.active?
=> false
>> ActiveRecord::Base.connection.reconnect!
=> nil
>> ActiveRecord::Base.connection.execute("CALL proc01")
=> #<Mysql::Result:0x1034102e0>
>> ActiveRecord::Base.connection.active?
=> false

Is this a really difficult problem to tackle, technically, or is this a design choice by Rails?


回答1:


Stored procedures are supported in rails. The out of of sync error you are getting is because the MULTI_STATEMENTS flag for MySQL is not enabled by default in Rails. This flag allows for procedures to return more than 1 result set.

See here for a code sample on how to enable it: https://gist.github.com/wok/1367987

Stored procedures work out of the box with MS SQL Server.

I have been using stored procedures in almost all of my mySQL and SQL Server based rails projects without any issued.




回答2:


This is for postgres to execute a stored procedure that returns instances of MyClass.

sql=<<-SQL
select * from my_cool_sp_with_3_parameters(?, ?, ?) as 
foo(
  column_1 <type1>,
  column_2 <type2>
)
SQL

MyClass.find_by_sql([sql, param1, param2, param3]);

Replace the column list inside of foo() with the columns from your model and the stored procedure results. I'm sure this could be made generic by inspecting the columns of the class.




回答3:


Those who are getting sync errors may have procedures that generate multiple results. You will need to do something like this to handle them:

raise 'You updated Rails. Check this duck punch is still valid' unless Rails.version == "3.2.15"
module ActiveRecord
  module ConnectionAdapters
    class Mysql2Adapter
      def call_stored_procedure(sql)
        results = []
        results << select_all(sql)
        while @connection.more_results?
          results << @connection.next_result
        end
        results
      end
    end
  end
end

Call like this:

ActiveRecord::Base.connection.call_stored_procedure("CALL your_procedure('foo')")


来源:https://stackoverflow.com/questions/11657160/why-are-stored-procedures-still-not-supported-in-rails-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!