Permalink
Browse files

prepared statements can be disabled

  • Loading branch information...
1 parent 995d792 commit f290d6f516a3f8ef46f0055b129b95e852d791d7 @tenderlove tenderlove committed Feb 21, 2012
@@ -4,9 +4,11 @@ module ActiveRecord
module ConnectionAdapters # :nodoc:
module DatabaseStatements
# Converts an arel AST to SQL
- def to_sql(arel)
+ def to_sql(arel, binds = [])
if arel.respond_to?(:ast)
- visitor.accept(arel.ast)
+ visitor.accept(arel.ast) do
+ quote(*binds.shift.reverse)
+ end
else
arel
end
@@ -15,7 +17,7 @@ def to_sql(arel)
# Returns an array of record hashes with the column names as keys and
# column values as values.
def select_all(arel, name = nil, binds = [])
- select(to_sql(arel), name, binds)
+ select(to_sql(arel, binds), name, binds)
end
# Returns a record hash with the column names as keys and column values
@@ -35,7 +37,7 @@ def select_value(arel, name = nil)
# Returns an array of the values of the first column in a select:
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
def select_values(arel, name = nil)
- result = select_rows(to_sql(arel), name)
+ result = select_rows(to_sql(arel, []), name)
result.map { |v| v[0] }
end
@@ -86,19 +88,19 @@ def exec_update(sql, name, binds)
# If the next id was calculated in advance (as in Oracle), it should be
# passed in as +id_value+.
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
- sql, binds = sql_for_insert(to_sql(arel), pk, id_value, sequence_name, binds)
+ sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
value = exec_insert(sql, name, binds)
id_value || last_inserted_id(value)
end
# Executes the update statement and returns the number of rows affected.
def update(arel, name = nil, binds = [])
- exec_update(to_sql(arel), name, binds)
+ exec_update(to_sql(arel, binds), name, binds)
end
# Executes the delete statement and returns the number of rows affected.
def delete(arel, name = nil, binds = [])
- exec_delete(to_sql(arel), name, binds)
+ exec_delete(to_sql(arel, binds), name, binds)
end
# Checks whether there is currently no transaction active. This is done
@@ -57,7 +57,7 @@ def clear_query_cache
def select_all(arel, name = nil, binds = [])
if @query_cache_enabled
- sql = to_sql(arel)
+ sql = to_sql(arel, binds)
cache_sql(sql, binds) { super(sql, name, binds) }
else
super
@@ -130,7 +130,7 @@ def initialize(connection, logger, connection_options, config)
end
def self.visitor_for(pool) # :nodoc:
- Arel::Visitors::MySQL.new(pool)
+ BindSubstitution.new pool
end
def adapter_name
@@ -297,17 +297,11 @@ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
alias :create :insert_sql
def exec_insert(sql, name, binds)
- binds = binds.dup
-
- # Pretend to support bind parameters
- execute sql.gsub("\0") { quote(*binds.shift.reverse) }, name
+ execute to_sql(sql, binds), name
end
def exec_delete(sql, name, binds)
- binds = binds.dup
-
- # Pretend to support bind parameters
- execute sql.gsub("\0") { quote(*binds.shift.reverse) }, name
+ execute to_sql(sql, binds), name
@connection.affected_rows
end
alias :exec_update :exec_delete
@@ -678,8 +672,7 @@ def configure_connection
# Returns an array of record hashes with the column names as keys and
# column values as values.
def select(sql, name = nil, binds = [])
- binds = binds.dup
- exec_query(sql.gsub("\0") { quote(*binds.shift.reverse) }, name).to_a
+ exec_query(sql, name).to_a
end
def exec_query(sql, name = 'SQL', binds = [])
@@ -3,6 +3,7 @@
require 'active_support/core_ext/object/blank'
require 'set'
require 'active_record/connection_adapters/statement_pool'
+require 'arel/visitors/bind_visitor'
gem 'mysql', '~> 2.8.1'
require 'mysql'
@@ -228,8 +229,18 @@ def initialize(connection, logger, connection_options, config)
connect
end
+ class BindSubstitution < Arel::Visitors::MySQL # :nodoc:
+ include Arel::Visitors::BindVisitor
+ end
+
def self.visitor_for(pool) # :nodoc:
- Arel::Visitors::MySQL.new(pool)
+ config = pool.spec.config
+
+ if config.fetch(:prepared_statements) { true }
+ Arel::Visitors::MySQL.new pool
+ else
+ BindSubstitution.new pool
+ end
end
def adapter_name #:nodoc:
@@ -2,6 +2,7 @@
require 'active_support/core_ext/kernel/requires'
require 'active_support/core_ext/object/blank'
require 'active_record/connection_adapters/statement_pool'
+require 'arel/visitors/bind_visitor'
# Make sure we're using pg high enough for PGResult#values
gem 'pg', '~> 0.11'
@@ -300,9 +301,16 @@ def connection_active?
end
end
+ class BindSubstitution < Arel::Visitors::PostgreSQL # :nodoc:
+ include Arel::Visitors::BindVisitor
+ end
+
# Initializes and connects a PostgreSQL adapter.
def initialize(connection, logger, connection_parameters, config)
super(connection, logger)
+
+ connection_parameters.delete :prepared_statements
+
@connection_parameters, @config = connection_parameters, config
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
@@ -321,7 +329,12 @@ def initialize(connection, logger, connection_parameters, config)
end
def self.visitor_for(pool) # :nodoc:
- Arel::Visitors::PostgreSQL.new(pool)
+ config = pool.spec.config
+ if config.fetch(:prepared_statements) { true }
+ Arel::Visitors::PostgreSQL.new pool
+ else
+ BindSubstitution.new pool
+ end
end
# Clears the prepared statements cache.
@@ -2,6 +2,7 @@
require 'active_support/core_ext/kernel/requires'
require 'active_record/connection_adapters/statement_pool'
require 'active_support/core_ext/string/encoding'
+require 'arel/visitors/bind_visitor'
module ActiveRecord
module ConnectionAdapters #:nodoc:
@@ -85,6 +86,10 @@ def dealloc(stmt)
end
end
+ class BindSubstitution < Arel::Visitors::SQLite # :nodoc:
+ include Arel::Visitors::BindVisitor
+ end
+
def initialize(connection, logger, config)
super(connection, logger)
@statements = StatementPool.new(@connection,
@@ -93,7 +98,13 @@ def initialize(connection, logger, config)
end
def self.visitor_for(pool) # :nodoc:
- Arel::Visitors::SQLite.new(pool)
+ config = pool.spec.config
+
+ if config.fetch(:prepared_statements) { true }
+ Arel::Visitors::SQLite.new pool
+ else
+ BindSubstitution.new pool
+ end
end
def adapter_name #:nodoc:
@@ -81,6 +81,7 @@ def new(*args, &block)
end
def initialize_copy(other)
+ @bind_values = @bind_values.dup
reset
end
@@ -394,7 +395,7 @@ def reset
end
def to_sql
- @to_sql ||= klass.connection.to_sql(arel)
+ @to_sql ||= klass.connection.to_sql(arel, @bind_values.dup)
end
def where_values_hash
@@ -208,7 +208,7 @@ def exists?(id = false)
def find_with_associations
join_dependency = construct_join_dependency_for_association_find
relation = construct_relation_for_association_find(join_dependency)
- rows = connection.select_all(relation, 'SQL', relation.bind_values)
+ rows = connection.select_all(relation, 'SQL', relation.bind_values.dup)
join_dependency.instantiate(rows)
rescue ThrowResult
[]

0 comments on commit f290d6f

Please sign in to comment.