diff options
Diffstat (limited to 'activerecord/lib')
13 files changed, 62 insertions, 65 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 06b9bc5765..37a9d216df 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -184,16 +184,6 @@ module ActiveRecord end end - # Verify active connections and remove and disconnect connections - # associated with stale threads. - def verify_active_connections! #:nodoc: - synchronize do - @connections.each do |connection| - connection.verify! - end - end - end - def clear_stale_cached_connections! # :nodoc: end deprecate :clear_stale_cached_connections! @@ -364,11 +354,6 @@ module ActiveRecord connection_pools.each_value {|pool| pool.disconnect! } end - # Verify active connections. - def verify_active_connections! #:nodoc: - connection_pools.each_value {|pool| pool.verify_active_connections! } - end - # Locate the connection of the nearest super class. This can be an # active or defined connection: if it is the latter, it will be # opened and set as the active connection for the class it was defined 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 eb8cff9610..db99c3fbef 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -2,9 +2,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 @@ -13,7 +15,7 @@ module ActiveRecord # 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 @@ -33,7 +35,7 @@ module ActiveRecord # 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 @@ -84,19 +86,19 @@ module ActiveRecord # 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 diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb index 6ba64bb88f..17377bad96 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -57,7 +57,7 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index e1dad5b166..eec7efadc2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/blank' +require 'arel/visitors/bind_visitor' module ActiveRecord module ConnectionAdapters @@ -122,12 +123,21 @@ module ActiveRecord :boolean => { :name => "tinyint", :limit => 1 } } + class BindSubstitution < Arel::Visitors::MySQL # :nodoc: + include Arel::Visitors::BindVisitor + end + # FIXME: Make the first parameter more similar for the two adapters def initialize(connection, logger, connection_options, config) super(connection, logger) @connection_options, @config = connection_options, config @quoted_column_names, @quoted_table_names = {}, {} - @visitor = Arel::Visitors::MySQL.new self + + if config.fetch(:prepared_statements) { true } + @visitor = Arel::Visitors::MySQL.new self + else + @visitor = BindSubstitution.new self + end end def adapter_name #:nodoc: @@ -427,7 +437,7 @@ module ActiveRecord table, arguments = args.shift, args method = :"#{command}_sql" - if respond_to?(method) + if respond_to?(method, true) send(method, table, *arguments) else raise "Unknown method called : #{method}(#{arguments.inspect})" diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 5ab9c24999..3f45f23de8 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -32,6 +32,7 @@ module ActiveRecord def initialize(connection, logger, connection_options, config) super + @visitor = BindSubstitution.new self configure_connection end @@ -65,10 +66,6 @@ module ActiveRecord @connection.escape(string) end - def substitute_at(column, index) - Arel::Nodes::BindParam.new "\0" - end - # CONNECTION MANAGEMENT ==================================== def active? @@ -94,7 +91,7 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== def explain(arel, binds = []) - sql = "EXPLAIN #{to_sql(arel)}" + sql = "EXPLAIN #{to_sql(arel, binds.dup)}" start = Time.now result = exec_query(sql, 'EXPLAIN', binds) elapsed = Time.now - start @@ -220,8 +217,7 @@ 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 = []) - binds = binds.dup - exec_query(sql.gsub("\0") { quote(*binds.shift.reverse) }, name) + exec_query(sql, name) end def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) @@ -231,17 +227,11 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 3925a9634e..c675b64a26 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -2,6 +2,7 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_support/core_ext/object/blank' require 'active_record/connection_adapters/statement_pool' require 'active_record/connection_adapters/postgresql/oid' +require 'arel/visitors/bind_visitor' # Make sure we're using pg high enough for PGResult#values gem 'pg', '~> 0.11' @@ -373,11 +374,23 @@ module ActiveRecord 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) + + if config.fetch(:prepared_statements) { true } + @visitor = Arel::Visitors::PostgreSQL.new self + else + @visitor = BindSubstitution.new self + end + + connection_parameters.delete :prepared_statements + @connection_parameters, @config = connection_parameters, config - @visitor = Arel::Visitors::PostgreSQL.new self # @local_tz is initialized as nil to avoid warnings when connect tries to use it @local_tz = nil @@ -599,7 +612,7 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== def explain(arel, binds = []) - sql = "EXPLAIN #{to_sql(arel)}" + sql = "EXPLAIN #{to_sql(arel, binds)}" ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', binds)) end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index b73f7ae876..c85c4c6e51 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,5 +1,6 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_record/connection_adapters/statement_pool' +require 'arel/visitors/bind_visitor' module ActiveRecord module ConnectionAdapters #:nodoc: @@ -68,12 +69,21 @@ module ActiveRecord 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, config.fetch(:statement_limit) { 1000 }) @config = config - @visitor = Arel::Visitors::SQLite.new self + + if config.fetch(:prepared_statements) { true } + @visitor = Arel::Visitors::SQLite.new self + else + @visitor = BindSubstitution.new self + end end def adapter_name #:nodoc: @@ -201,7 +211,7 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== def explain(arel, binds = []) - sql = "EXPLAIN QUERY PLAN #{to_sql(arel)}" + sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}" ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', binds)) end diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index d7746826a9..7b218a5570 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -91,6 +91,6 @@ module ActiveRecord end delegate :clear_active_connections!, :clear_reloadable_connections!, - :clear_all_connections!, :verify_active_connections!, :to => :connection_handler + :clear_all_connections!, :to => :connection_handler end end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index ac70aeba67..3d1ca4f99b 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -78,6 +78,7 @@ module ActiveRecord end def initialize_copy(other) + @bind_values = @bind_values.dup reset end @@ -454,7 +455,7 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index f1ac421a50..26a5165abf 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -208,7 +208,7 @@ module ActiveRecord 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 [] diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 7131aa29b6..706b0cd1cc 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -24,7 +24,10 @@ module ActiveRecord (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method| value = r.send(:"#{method}_values") - merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present? + next if value.empty? + + value += merged_relation.send(:"#{method}_values") + merged_relation.send :"#{method}_values=", value end merged_relation.joins_values += r.joins_values diff --git a/activerecord/lib/rails/generators/active_record.rb b/activerecord/lib/rails/generators/active_record.rb index 4b3d1db216..297cd094c2 100644 --- a/activerecord/lib/rails/generators/active_record.rb +++ b/activerecord/lib/rails/generators/active_record.rb @@ -1,14 +1,12 @@ require 'rails/generators/named_base' require 'rails/generators/migration' require 'rails/generators/active_model' -require 'rails/generators/active_record/migration' require 'active_record' module ActiveRecord module Generators class Base < Rails::Generators::NamedBase #:nodoc: include Rails::Generators::Migration - extend ActiveRecord::Generators::Migration # Set the current directory as base for the inherited generators. def self.base_root diff --git a/activerecord/lib/rails/generators/active_record/migration.rb b/activerecord/lib/rails/generators/active_record/migration.rb deleted file mode 100644 index 7f2f2e06a5..0000000000 --- a/activerecord/lib/rails/generators/active_record/migration.rb +++ /dev/null @@ -1,15 +0,0 @@ -module ActiveRecord - module Generators - module Migration - # Implement the required interface for Rails::Generators::Migration. - def next_migration_number(dirname) #:nodoc: - next_migration_number = current_migration_number(dirname) + 1 - if ActiveRecord::Base.timestamped_migrations - [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max - else - "%.3d" % next_migration_number - end - end - end - end -end |