From 73ff6797ef3e6fd0a3ee4b860061cf6869fe835d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 9 May 2011 13:53:46 -0700 Subject: use a null byte as a bind parameter substitute as it is not allowed in normal SQL. fixes #411, #417 --- .../abstract/database_statements.rb | 10 +---- .../connection_adapters/mysql2_adapter.rb | 11 +++-- .../cases/adapters/mysql2/bind_parameter_test.rb | 50 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 3045e30407..b3eb23bbb3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -6,15 +6,7 @@ module ActiveRecord # Returns an array of record hashes with the column names as keys and # column values as values. def select_all(sql, name = nil, binds = []) - if supports_statement_cache? - select(sql, name, binds) - else - return select(sql, name) if binds.empty? - binds = binds.dup - select sql.gsub('?') { - quote(*binds.shift.reverse) - }, name - end + select(sql, name, binds) end # Returns a record hash with the column names as keys and column values diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 8af22fe9f5..ac2da73a84 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -184,6 +184,10 @@ module ActiveRecord QUOTED_FALSE end + def substitute_at(column, index) + Arel.sql "\0" + end + # REFERENTIAL INTEGRITY ==================================== def disable_referential_integrity(&block) #:nodoc: @@ -292,14 +296,14 @@ module ActiveRecord binds = binds.dup # Pretend to support bind parameters - execute sql.gsub('?') { quote(*binds.shift.reverse) }, name + execute sql.gsub("\0") { quote(*binds.shift.reverse) }, name end def exec_delete(sql, name, binds) binds = binds.dup # Pretend to support bind parameters - execute sql.gsub('?') { quote(*binds.shift.reverse) }, name + execute sql.gsub("\0") { quote(*binds.shift.reverse) }, name @connection.affected_rows end alias :exec_update :exec_delete @@ -646,7 +650,8 @@ module ActiveRecord # Returns an array of record hashes with the column names as keys and # column values as values. def select(sql, name = nil, binds = []) - exec_query(sql, name, binds).to_a + binds = binds.dup + exec_query(sql.gsub("\0") { quote(*binds.shift.reverse) }, name).to_a end def exec_query(sql, name = 'SQL', binds = []) diff --git a/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb b/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb new file mode 100644 index 0000000000..cd9c1041dc --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb @@ -0,0 +1,50 @@ +require "cases/helper" +require 'models/topic' + +module ActiveRecord + module ConnectionAdapters + class Mysql2Adapter + class BindParameterTest < ActiveRecord::TestCase + fixtures :topics + + def test_update_question_marks + str = "foo?bar" + x = Topic.find :first + x.title = str + x.content = str + x.save! + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + + def test_create_question_marks + str = "foo?bar" + x = Topic.create!(:title => str, :content => str) + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + + def test_update_null_bytes + str = "foo\0bar" + x = Topic.find :first + x.title = str + x.content = str + x.save! + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + + def test_create_null_bytes + str = "foo\0bar" + x = Topic.create!(:title => str, :content => str) + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + end + end + end +end -- cgit v1.2.3