use a null byte as a bind parameter substitute as it is not allowed in normal SQL. fixes #411, #417

This commit is contained in:
Aaron Patterson 2011-05-09 13:53:46 -07:00
parent c56f4b272d
commit 73ff6797ef
3 changed files with 59 additions and 12 deletions

View File

@ -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

View File

@ -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 = [])

View File

@ -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