I\'ve tried using google to answer this seemingly simple question, but to my surprise, it didn\'t help.
I have code in my rails application currently using the \'pre
I'm also surprised that the prepare method is missing. Surely in a common ActiveRecord and Mysql2 setup, ActiveRecord must be escaping the strings rather then using libmysql, which I find a tiny bit worrying.
In the meantime, you can use https://github.com/brianmario/mysql2/tree/stmt
Rails and the MySQL Active Record adaptor does not have any support for prepared statements as far as I know:
http://patshaughnessy.net/2011/10/22/show-some-love-for-prepared-statements-in-rails-3-1
This is because they actually don't have any use in speeding statements up and can actually slow things down due to MySQL's lack of query planning.
UPDATE
As Ryan Rapp pointed out correctly, mysql2 now supports prepared statements. Following snippet is extracted from the readme:
statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
result1 = statement.execute(1)
result2 = statement.execute(2)
statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
result = statement.execute(1, "CA")
Thanks Ryan!
Original Post
I found no such function either; neither in source nor in the documentation. Maybe the following snippet is a helpful replacement for your needs? (found in the documentation of mysql2 gem):
escaped = client.escape("gi'thu\"bbe\0r's")
results = client.query("SELECT * FROM users WHERE group='#{escaped}'")
I swapped out to use https://github.com/tmtm/ruby-mysql instead of mysql2. I'm surprised this isn't a bigger deal-breaker for people using the mysql2 gem. I guess people who dig this deep into writing SQL have swapped to Postgresql?
In case others are having trouble with gem install ruby-mysql
followed by require "mysql"
where you get a Ruby error like 'read_eof_packet': packet is not EOF (Mysql::ProtocolError)
the trick is to gem uninstall ruby-mysql
and instead gem install ruby-mysql-ext
(or use gem 'ruby-mysql-ext'
in your Gemfile) which will swap out the Ruby implementation which isn't yet Ruby 2.0 compatible (or at least, didn't work for me) for simple C bindings.
To be clear, if you do require 'mysql'
while both ruby-mysql-ext
and ruby-mysql
are installed, it will load the Ruby version. There may be a way to require within a specific gem, but I didn't have time to look it up.
You may also use mysql2-cs-bind gem: https://github.com/tagomoris/mysql2-cs-bind
Yes, mysql2 adapter doesn't support binding till the current Rails 4.0. I'm being surprised! You could tell this by the code snip from ~/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.1/lib/active_record/connection_adapters/mysql2_adapter.rb
def exec_query(sql, name = 'SQL', binds = [])
result = execute(sql, name)
ActiveRecord::Result.new(result.fields, result.to_a)
end
alias exec_without_stmt exec_query
# Returns an ActiveRecord::Result instance.
def select(sql, name = nil, binds = [])
exec_query(sql, name)
end
also this is helpful for you understanding:
(in ~/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb)
# Returns an ActiveRecord::Result instance.
def select_all(arel, name = nil, binds = [])
if arel.is_a?(Relation)
relation = arel
arel = relation.arel
if !binds || binds.empty?
binds = relation.bind_values
end
end
select(to_sql(arel, binds), name, binds)
end
That's it! And I guess I may turn to Postgres!!