mysql - para - procedimientos almacenados sql
¿Por qué los procedimientos almacenados aún no son compatibles con Rails(3+)? (3)
Estoy familiarizado con la larga relación de amor-odio entre Ruby on Rails, controladores DB (MS) y Stored Procedures y he estado desarrollando aplicaciones Rails desde la versión 2.3.2.
Sin embargo, de vez en cuando surge una situación en la que un SP es simplemente una mejor opción que combinar datos en el nivel de aplicación (mucho más lento). Específicamente, la ejecución de informes que combina datos de múltiples tablas suele ser más adecuada para un SP.
¿Por qué los procedimientos almacenados aún están tan mal integrados en Rails o en la gema MySQL? Actualmente estoy trabajando en un proyecto con Rails 3.0.10 y MySQL2 gem 0.2.13, pero hasta donde puedo ver, incluso las últimas versiones de Edge Rails y MySQL gem 0.3+ todavía generan rabietas cuando usas SP.
El problema que ha sido, y sigue siendo, es que la conexión de la base de datos se pierde después de que se llama a un SP.
>> 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
¿Es este un problema realmente difícil de abordar, técnicamente, o es una elección de diseño de Rails?
Esto es para postgres para ejecutar un procedimiento almacenado que devuelve instancias de 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]);
Reemplace la lista de columnas dentro de foo () con las columnas de su modelo y los resultados del procedimiento almacenado. Estoy seguro de que esto podría hacerse genérico al inspeccionar las columnas de la clase.
Los procedimientos almacenados se admiten en rieles. El error de desincronización que está recibiendo se debe a que el indicador MULTI_STATEMENTS
para MySQL no está habilitado de manera predeterminada en Rails. Este indicador permite que los procedimientos devuelvan más de 1 conjunto de resultados.
Vea aquí un ejemplo de código sobre cómo habilitarlo: https://gist.github.com/wok/1367987
Los procedimientos almacenados funcionan de la caja con MS SQL Server.
He estado utilizando procedimientos almacenados en casi todos mis proyectos de rieles basados en mySQL y SQL Server sin ningún tipo de emisión.
Quienes obtienen errores de sincronización pueden tener procedimientos que generan resultados múltiples. Tendrá que hacer algo como esto para manejarlos:
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
Llamar así:
ActiveRecord::Base.connection.call_stored_procedure("CALL your_procedure(''foo'')")