1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Check if the SQL is not a prepared statement

When the adapter is with prepared statement disabled and the binds array
is not empty the connection adapter will try to set the binds values and
will fail. Now we are checking if the adapter has the prepared statement
disabled.

Fixes #12023
This commit is contained in:
Rafael Mendonça França 2013-08-27 23:41:29 -03:00
parent 3d60e9d550
commit f13b278568
10 changed files with 29 additions and 7 deletions

View file

@ -1,3 +1,9 @@
* Fix inserts with prepared statements disabled.
Fixes #12023.
*Rafael Mendonça França*
* Setting a has_one association on a new record no longer causes an empty
transaction.

View file

@ -97,6 +97,7 @@ module ActiveRecord
@pool = pool
@schema_cache = SchemaCache.new self
@visitor = nil
@prepared_statements = false
end
def valid_type?(type)
@ -440,6 +441,10 @@ module ActiveRecord
# override in derived class
ActiveRecord::StatementInvalid.new(message, exception)
end
def without_prepared_statement?(binds)
@prepared_statements || binds.empty?
end
end
end
end

View file

@ -174,6 +174,7 @@ module ActiveRecord
@quoted_column_names, @quoted_table_names = {}, {}
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@prepared_statements = true
@visitor = Arel::Visitors::MySQL.new self
else
@visitor = unprepared_visitor

View file

@ -283,7 +283,7 @@ module ActiveRecord
# always be empty, since the bind variables will have been already
# substituted and removed from binds by BindVisitor, so this will
# effectively disable prepared statement usage completely.
if binds.empty?
if without_prepared_statement?(binds)
result_set, affected_rows = exec_without_stmt(sql, name)
else
result_set, affected_rows = exec_stmt(sql, name, binds)

View file

@ -135,7 +135,7 @@ module ActiveRecord
def exec_query(sql, name = 'SQL', binds = [])
log(sql, name, binds) do
result = binds.empty? ? exec_no_cache(sql, binds) :
result = without_prepared_statement?(binds) ? exec_no_cache(sql, binds) :
exec_cache(sql, binds)
types = {}

View file

@ -531,6 +531,7 @@ module ActiveRecord
super(connection, logger)
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@prepared_statements = true
@visitor = Arel::Visitors::PostgreSQL.new self
else
@visitor = unprepared_visitor

View file

@ -113,6 +113,7 @@ module ActiveRecord
@config = config
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@prepared_statements = true
@visitor = Arel::Visitors::SQLite.new self
else
@visitor = unprepared_visitor
@ -293,8 +294,8 @@ module ActiveRecord
def exec_query(sql, name = nil, binds = [])
log(sql, name, binds) do
# Don't cache statements without bind values
if binds.empty?
# Don't cache statements if they are not prepared
if without_prepared_statement?(binds)
stmt = @connection.prepare(sql)
cols = stmt.columns
records = stmt.to_a

View file

@ -565,6 +565,14 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal [topic_2, topic_1].sort, [topic_1, topic_2]
end
def test_create_without_prepared_statement
topic = Topic.connection.unprepared_statement do
Topic.create(:title => 'foo')
end
assert_equal topic, Topic.find(topic.id)
end
def test_comparison_with_different_objects
topic = Topic.create
category = Category.create(:name => "comparison")