Fix test failures when prepared statements are disabled

This also reverts the change to enable prepared statements by default on
MySQL (though I suspect we could enable them and it'd be great). This
change brings back a collector closer to the old `Bind` collector in
Arel. However, this one lives in AR, since this is an AR specific need.
Additionally, we only use it for statement caching, since the new
substitute collector in Arel is higher performance for most cases.
This commit is contained in:
Sean Griffin 2017-07-24 12:28:26 -04:00
parent a698424477
commit 846832ae54
3 changed files with 35 additions and 14 deletions

@ -29,8 +29,9 @@ def cacheable_query(klass, arel) # :nodoc:
sql, binds = visitor.accept(arel.ast, collector).value
query = klass.query(sql)
else
query = klass.partial_query(arel.ast)
binds = []
collector = PartialQueryCollector.new
parts, binds = visitor.accept(arel.ast, collector).value
query = klass.partial_query(parts)
end
[query, binds]
end
@ -457,6 +458,28 @@ def with_yaml_fallback(value)
value
end
end
class PartialQueryCollector
def initialize
@parts = []
@binds = []
end
def << str
@parts << str
self
end
def add_bind obj
@binds << obj
@parts << Arel::Nodes::BindParam.new(1)
self
end
def value
[@parts, @binds]
end
end
end
end
end

@ -39,7 +39,7 @@ class Mysql2Adapter < AbstractMysqlAdapter
def initialize(connection, logger, connection_options, config)
super
@prepared_statements = true unless config[:prepared_statements] == false
@prepared_statements = false unless config.key?(:prepared_statements)
configure_connection
end

@ -41,20 +41,18 @@ def sql_for(binds, connection)
end
class PartialQuery < Query # :nodoc:
def initialize(arel)
@arel = arel
def initialize(values)
@values = values
@indexes = values.each_with_index.find_all { |thing, i|
Arel::Nodes::BindParam === thing
}.map(&:last)
end
def sql_for(binds, connection)
val = @arel.dup
val.grep(Arel::Nodes::BindParam) do |node|
node.value = binds.shift
if binds.empty?
break
end
end
sql, _ = connection.visitor.accept(val, connection.send(:collector)).value
sql
val = @values.dup
casted_binds = binds.map(&:value_for_database)
@indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
val.join
end
end