aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2010-10-14 10:25:43 +0100
committerJon Leighton <j@jonathanleighton.com>2010-10-14 10:25:43 +0100
commit3fb493c2b037ffbdda5c91d66334ec6f79faa2d1 (patch)
treee49b072103bbfe6fb6159954c786a31f44099325 /activerecord/lib/active_record
parent212fdd8ba9624f61421a7a950283537a3d39ac18 (diff)
parent01ab6f961bff150d50c99f03fa3946f48ac29b17 (diff)
downloadrails-3fb493c2b037ffbdda5c91d66334ec6f79faa2d1.tar.gz
rails-3fb493c2b037ffbdda5c91d66334ec6f79faa2d1.tar.bz2
rails-3fb493c2b037ffbdda5c91d66334ec6f79faa2d1.zip
Merge branch 'master' into nested_has_many_through
Conflicts: activerecord/lib/active_record/associations.rb activerecord/test/cases/associations/cascaded_eager_loading_test.rb
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/base.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb16
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb45
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb4
-rw-r--r--activerecord/lib/active_record/migration.rb41
-rw-r--r--activerecord/lib/active_record/railties/databases.rake50
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb14
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb4
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb11
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb11
-rw-r--r--activerecord/lib/active_record/serialization.rb2
-rw-r--r--activerecord/lib/active_record/test_case.rb15
14 files changed, 111 insertions, 119 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index ff6be4ff19..78b3507dd9 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -423,7 +423,7 @@ module ActiveRecord #:nodoc:
class << self # Class methods
delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
delegate :find_each, :find_in_batches, :to => :scoped
- delegate :select, :group, :order, :reorder, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
+ delegate :select, :group, :order, :except, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped
# Executes a custom SQL query against your database and returns all the results. The results will
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 37e584a629..ca9314ec99 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -73,12 +73,7 @@ module ActiveRecord
# The mutex used to synchronize pool access
@connection_mutex = Monitor.new
@queue = @connection_mutex.new_cond
-
- # default 5 second timeout unless on ruby 1.9
- @timeout =
- if RUBY_VERSION < '1.9'
- spec.config[:wait_timeout] || 5
- end
+ @timeout = spec.config[:wait_timeout] || 5
# default max pool size to 5
@size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
@@ -161,7 +156,6 @@ module ActiveRecord
keys = @reserved_connections.keys - Thread.list.find_all { |t|
t.alive?
}.map { |thread| thread.object_id }
-
keys.each do |key|
checkin @reserved_connections[key]
@reserved_connections.delete(key)
@@ -194,16 +188,18 @@ module ActiveRecord
checkout_new_connection
end
return conn if conn
- # No connections available; wait for one
- if @queue.wait(@timeout)
+
+ @queue.wait(@timeout)
+
+ if(@checked_out.size < @connections.size)
next
else
- # try looting dead threads
clear_stale_cached_connections!
if @size == @checked_out.size
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
end
end
+
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index e2b3773a99..a7a12faac2 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -10,28 +10,31 @@ module ActiveRecord
return value.quoted_id if value.respond_to?(:quoted_id)
case value
- when String, ActiveSupport::Multibyte::Chars
- value = value.to_s
- if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
- "'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode)
- elsif column && [:integer, :float].include?(column.type)
- value = column.type == :integer ? value.to_i : value.to_f
- value.to_s
- else
- "'#{quote_string(value)}'" # ' (for ruby-mode)
- end
- when NilClass then "NULL"
- when TrueClass then (column && column.type == :integer ? '1' : quoted_true)
- when FalseClass then (column && column.type == :integer ? '0' : quoted_false)
- when Float, Fixnum, Bignum then value.to_s
- # BigDecimals need to be output in a non-normalized form and quoted.
- when BigDecimal then value.to_s('F')
+ when String, ActiveSupport::Multibyte::Chars
+ value = value.to_s
+ return "'#{quote_string(value)}'" unless column
+
+ case column.type
+ when :binary then "'#{quote_string(column.string_to_binary(value))}'"
+ when :integer then value.to_i.to_s
+ when :float then value.to_f.to_s
+ else
+ "'#{quote_string(value)}'"
+ end
+
+ when true, false
+ if column && column.type == :integer
+ value ? '1' : '0'
else
- if value.acts_like?(:date) || value.acts_like?(:time)
- "'#{quoted_date(value)}'"
- else
- "'#{quote_string(value.to_s)}'"
- end
+ value ? quoted_true : quoted_false
+ end
+ # BigDecimals need to be put in a non-normalized form and quoted.
+ when nil then "NULL"
+ when BigDecimal then value.to_s('F')
+ when Numeric then value.to_s
+ when Date, Time then "'#{quoted_date(value)}'"
+ else
+ "'#{quote_string(value.to_s)}'"
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 6480aeb171..60ccf9edf3 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -114,6 +114,11 @@ module ActiveRecord
type_cast(default)
end
+ # Used to convert from Strings to BLOBs
+ def string_to_binary(value)
+ self.class.string_to_binary(value)
+ end
+
class << self
# Used to convert from Strings to BLOBs
def string_to_binary(value)
@@ -268,6 +273,10 @@ module ActiveRecord
# for generating a number of table creation or table changing SQL statements.
class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
+ def string_to_binary(value)
+ value
+ end
+
def sql_type
base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index e7f7b37b27..a4b336dfaf 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -132,7 +132,7 @@ module ActiveRecord
cattr_accessor :emulate_booleans
self.emulate_booleans = true
- ADAPTER_NAME = 'MySQL'.freeze
+ ADAPTER_NAME = 'MySQL'
LOST_CONNECTION_ERROR_MESSAGES = [
"Server shutdown in progress",
@@ -140,10 +140,10 @@ module ActiveRecord
"Lost connection to MySQL server during query",
"MySQL server has gone away" ]
- QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
+ QUOTED_TRUE, QUOTED_FALSE = '1', '0'
NATIVE_DATABASE_TYPES = {
- :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY".freeze,
+ :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY",
:string => { :name => "varchar", :limit => 255 },
:text => { :name => "text" },
:integer => { :name => "int", :limit => 4 },
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 5f14284615..dce9e99d27 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -180,8 +180,6 @@ module ActiveRecord
# <encoding></tt> call on the connection.
# * <tt>:min_messages</tt> - An optional client min messages that is used in a
# <tt>SET client_min_messages TO <min_messages></tt> call on the connection.
- # * <tt>:allow_concurrency</tt> - If true, use async query methods so Ruby threads don't deadlock;
- # otherwise, use blocking query methods.
class PostgreSQLAdapter < AbstractAdapter
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
def xml(*args)
@@ -930,7 +928,7 @@ module ActiveRecord
PGconn.translate_results = false if PGconn.respond_to?(:translate_results=)
# Ignore async_exec and async_query when using postgres-pr.
- @async = @config[:allow_concurrency] && @connection.respond_to?(:async_exec)
+ @async = @connection.respond_to?(:async_exec)
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 9ac18f9939..a4c09b654a 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -384,23 +384,32 @@ module ActiveRecord
end
end
- def copy(destination, sources)
+ def copy(destination, sources, options = {})
copied = []
- sources.each do |scope, path|
- destination_migrations = ActiveRecord::Migrator.migrations(destination)
+ destination_migrations = ActiveRecord::Migrator.migrations(destination)
+ last = destination_migrations.last
+ sources.each do |name, path|
source_migrations = ActiveRecord::Migrator.migrations(path)
- last = destination_migrations.last
source_migrations.each do |migration|
- next if destination_migrations.any? { |m| m.name == migration.name && m.scope == scope.to_s }
+ source = File.read(migration.filename)
+ source = "# This migration comes from #{name} (originally #{migration.version})\n#{source}"
+
+ if duplicate = destination_migrations.detect { |m| m.name == migration.name }
+ options[:on_skip].call(name, migration) if File.read(duplicate.filename) != source && options[:on_skip]
+ next
+ end
migration.version = next_migration_number(last ? last.version + 1 : 0).to_i
+ new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb")
+ old_path, migration.filename = migration.filename, new_path
last = migration
- new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.#{scope}.rb")
- FileUtils.cp(migration.filename, new_path)
- copied << new_path
+ FileUtils.cp(old_path, migration.filename)
+ copied << migration
+ options[:on_copy].call(name, migration, old_path) if options[:on_copy]
+ destination_migrations << migration
end
end
@@ -419,13 +428,17 @@ module ActiveRecord
# MigrationProxy is used to defer loading of the actual migration classes
# until they are needed
- class MigrationProxy < Struct.new(:name, :version, :filename, :scope)
+ class MigrationProxy < Struct.new(:name, :version, :filename)
- def initialize(name, version, filename, scope)
+ def initialize(name, version, filename)
super
@migration = nil
end
+ def basename
+ File.basename(filename)
+ end
+
delegate :migrate, :announce, :write, :to=>:migration
private
@@ -510,18 +523,18 @@ module ActiveRecord
seen = Hash.new false
migrations = files.map do |file|
- version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first
+ version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first
raise IllegalMigrationNameError.new(file) unless version
version = version.to_i
name = name.camelize
raise DuplicateMigrationVersionError.new(version) if seen[version]
- raise DuplicateMigrationNameError.new(name) if seen[[name, scope]]
+ raise DuplicateMigrationNameError.new(name) if seen[name]
- seen[version] = seen[[name, scope]] = true
+ seen[version] = seen[name] = true
- MigrationProxy.new(name, version, file, scope)
+ MigrationProxy.new(name, version, file)
end
migrations.sort_by(&:version)
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 58c705c8b2..1fbc8a1d32 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -2,28 +2,7 @@ namespace :db do
task :load_config => :rails_env do
require 'active_record'
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
- ActiveRecord::Migrator.migrations_path = Rails.application.config.paths.db.migrate.to_a.first
- end
-
- task :copy_migrations => :load_config do
- to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map {|n| n.strip }
- railties = {}
- Rails.application.railties.all do |railtie|
- next unless to_load == :all || to_load.include?(railtie.railtie_name)
-
- if railtie.config.respond_to?(:paths) && railtie.config.paths.db
- railties[railtie.railtie_name] = railtie.config.paths.db.migrate.to_a.first
- end
- end
-
- copied = ActiveRecord::Migration.copy(ActiveRecord::Migrator.migrations_path, railties)
-
- if copied.blank?
- puts "No migrations were copied, project is up to date."
- else
- puts "The following migrations were copied:"
- puts copied.map{ |path| File.basename(path) }.join("\n")
- end
+ ActiveRecord::Migrator.migrations_path = Rails.application.paths["db/migrate"].first
end
namespace :create do
@@ -501,8 +480,31 @@ namespace :db do
end
namespace :railties do
- desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
- task :copy_migrations => 'db:copy_migrations'
+ namespace :install do
+ # desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
+ task :migrations => :"db:load_config" do
+ to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map {|n| n.strip }
+ railties = {}
+ Rails.application.railties.all do |railtie|
+ next unless to_load == :all || to_load.include?(railtie.railtie_name)
+
+ if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first)
+ railties[railtie.railtie_name] = path
+ end
+ end
+
+ on_skip = Proc.new do |name, migration|
+ puts "NOTE: Migration #{migration.basename} from #{name} has been skipped. Migration with the same name already exists."
+ end
+
+ on_copy = Proc.new do |name, migration, old_path|
+ puts "Copied migration #{migration.basename} from #{name}"
+ end
+
+ ActiveRecord::Migration.copy( ActiveRecord::Migrator.migrations_path, railties,
+ :on_skip => on_skip, :on_copy => on_copy)
+ end
+ end
end
task 'test:prepare' => 'db:test:prepare'
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index d79ef78b4d..6bf698fe97 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -177,7 +177,7 @@ module ActiveRecord
distinct = options[:distinct] || distinct
if @group_values.any?
- execute_grouped_calculation(operation, column_name)
+ execute_grouped_calculation(operation, column_name, distinct)
else
execute_simple_calculation(operation, column_name, distinct)
end
@@ -191,19 +191,23 @@ module ActiveRecord
end
end
+ def operation_over_aggregate_column(column, operation, distinct)
+ operation == 'count' ? column.count(distinct) : column.send(operation)
+ end
+
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
column = aggregate_column(column_name)
# Postgresql doesn't like ORDER BY when there are no GROUP BY
relation = except(:order)
- select_value = operation == 'count' ? column.count(distinct) : column.send(operation)
+ select_value = operation_over_aggregate_column(column, operation, distinct)
relation.select_values = [select_value]
type_cast_calculated_value(@klass.connection.select_value(relation.to_sql), column_for(column_name), operation)
end
- def execute_grouped_calculation(operation, column_name) #:nodoc:
+ def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
group_attr = @group_values.first
association = @klass.reflect_on_association(group_attr.to_sym)
associated = association && association.macro == :belongs_to # only count belongs_to associations
@@ -221,7 +225,7 @@ module ActiveRecord
relation = except(:group).group(group)
relation.select_values = [
- aggregate_column(column_name).send(operation).as(aggregate_alias),
+ operation_over_aggregate_column(aggregate_column(column_name), operation, distinct).as(aggregate_alias),
"#{group_field} AS #{group_alias}"
]
@@ -273,7 +277,7 @@ module ActiveRecord
else type_cast_using_column(value, column)
end
else
- value
+ type_cast_using_column(value, column)
end
end
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 5034caf084..b763e22ec6 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -291,8 +291,8 @@ module ActiveRecord
record = where(primary_key.eq(id)).first
unless record
- conditions = arel.wheres.map { |x| x.value }.join(', ')
- conditions = " [WHERE #{conditions}]" if conditions.present?
+ conditions = arel.where_sql
+ conditions = " [#{conditions}]" if conditions
raise RecordNotFound, "Couldn't find #{@klass.name} with ID=#{id}#{conditions}"
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index f314ff861f..59ce76ea42 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -6,7 +6,7 @@ module ActiveRecord
extend ActiveSupport::Concern
attr_accessor :includes_values, :eager_load_values, :preload_values,
- :select_values, :group_values, :order_values, :reorder_flag, :joins_values, :where_values, :having_values,
+ :select_values, :group_values, :order_values, :joins_values, :where_values, :having_values,
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value
def includes(*args)
@@ -53,15 +53,6 @@ module ActiveRecord
relation
end
- def reorder(*args)
- relation = clone
- unless args.blank?
- relation.order_values = args
- relation.reorder_flag = true
- end
- relation
- end
-
def joins(*args)
relation = clone
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 9ecdb99bee..dcddc3dac4 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -19,20 +19,11 @@ module ActiveRecord
end
end
- (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
+ (Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method|
value = r.send(:"#{method}_values")
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
end
- order_value = r.order_values
- if order_value.present?
- if r.reorder_flag
- merged_relation.order_values = order_value
- else
- merged_relation.order_values = merged_relation.order_values + order_value
- end
- end
-
merged_relation = merged_relation.joins(r.joins_values)
merged_wheres = @where_values
diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb
index 398eb1534a..2bde06f562 100644
--- a/activerecord/lib/active_record/serialization.rb
+++ b/activerecord/lib/active_record/serialization.rb
@@ -22,7 +22,7 @@ module ActiveRecord #:nodoc:
end
private
- # Add associations specified via the <tt>:includes</tt> option.
+ # Add associations specified via the <tt>:include</tt> option.
#
# Expects a block that takes as arguments:
# +association+ - name of the association
diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb
index 31b5a8651b..014a900c71 100644
--- a/activerecord/lib/active_record/test_case.rb
+++ b/activerecord/lib/active_record/test_case.rb
@@ -36,21 +36,6 @@ module ActiveRecord
assert_queries(0, &block)
end
- def self.use_concurrent_connections
- setup :connection_allow_concurrency_setup
- teardown :connection_allow_concurrency_teardown
- end
-
- def connection_allow_concurrency_setup
- @connection = ActiveRecord::Base.remove_connection
- ActiveRecord::Base.establish_connection(@connection.merge({:allow_concurrency => true}))
- end
-
- def connection_allow_concurrency_teardown
- ActiveRecord::Base.clear_all_connections!
- ActiveRecord::Base.establish_connection(@connection)
- end
-
def with_kcode(kcode)
if RUBY_VERSION < '1.9'
orig_kcode, $KCODE = $KCODE, kcode