From 3825f173d9f2ff3ecf1563e188a9ad638da9f82d Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Fri, 26 Dec 2008 22:53:07 +0000 Subject: Fix :include of has_many associations with :primary_key option --- activerecord/lib/active_record/association_preload.rb | 2 +- activerecord/lib/active_record/associations.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 9d0bf3a308..195d2fb4f8 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -229,7 +229,7 @@ module ActiveRecord options = reflection.options primary_key_name = reflection.through_reflection_primary_key_name - id_to_record_map, ids = construct_id_map(records, primary_key_name) + id_to_record_map, ids = construct_id_map(records, primary_key_name || reflection.options[:primary_key]) records.each {|record| record.send(reflection.name).loaded} if options[:through] diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index c154a5087c..dfa3ffab4b 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -2171,7 +2171,7 @@ module ActiveRecord aliased_table_name, foreign_key, parent.aliased_table_name, - parent.primary_key + reflection.options[:primary_key] || parent.primary_key ] end when :belongs_to -- cgit v1.2.3 From 27cfeb7cbcc725c36053833ca8e12cc26357a170 Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Fri, 26 Dec 2008 23:26:37 +0000 Subject: Fix :include of has_one with :primary_key option --- activerecord/lib/active_record/association_preload.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 195d2fb4f8..e4ab69aa1b 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -195,7 +195,7 @@ module ActiveRecord def preload_has_one_association(records, reflection, preload_options={}) return if records.first.send("loaded_#{reflection.name}?") - id_to_record_map, ids = construct_id_map(records) + id_to_record_map, ids = construct_id_map(records, reflection.options[:primary_key]) options = reflection.options records.each {|record| record.send("set_#{reflection.name}_target", nil)} if options[:through] -- cgit v1.2.3 From 7276128fb47d5997437eb5452b4e9a82ee54f4a8 Mon Sep 17 00:00:00 2001 From: Roman Shterenzon Date: Sat, 27 Dec 2008 01:10:29 +0000 Subject: Fix HasManyAssociation#create ignoring the :primary_key option [#1633 state:resolved] Signed-off-by: Frederick Cheung --- activerecord/lib/active_record/associations/association_proxy.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index 59f1d3b867..676c4ace61 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -180,7 +180,10 @@ module ActiveRecord record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record? record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s else - record[@reflection.primary_key_name] = @owner.id unless @owner.new_record? + unless @owner.new_record? + primary_key = @reflection.options[:primary_key] || :id + record[@reflection.primary_key_name] = @owner.send(primary_key) + end end end -- cgit v1.2.3 From 373e94a03f1b5d3a2f0551d95c64ebbaf416d47f Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Sat, 27 Dec 2008 14:16:17 +0000 Subject: Fix to_sentence being used with options removed by 273c77 --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index dfa3ffab4b..86616abf52 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -22,7 +22,7 @@ module ActiveRecord through_reflection = reflection.through_reflection source_reflection_names = reflection.source_reflection_names source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect } - super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :connector => 'or'} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => '. Is it one of #{source_associations.to_sentence :connector => 'or'}?") + super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :two_words_connector => ' or ', :last_word_connector => ', or '} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => '. Is it one of #{source_associations.to_sentence :two_words_connector => ' or ', :last_word_connector => ', or '}?") end end -- cgit v1.2.3 From abfa46e3a6ba0e91f377a073d208f31f99a7a008 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Mon, 29 Dec 2008 20:46:20 -0600 Subject: Add transaction check to SQLite2 adapter to fix test_sqlite_add_column_in_transaction_raises_statement_invalid [#1669 state:resolved] Signed-off-by: Pratik Naik --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 84f8c0284e..9387cf8827 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -402,6 +402,10 @@ module ActiveRecord end def add_column(table_name, column_name, type, options = {}) #:nodoc: + if @connection.respond_to?(:transaction_active?) && @connection.transaction_active? + raise StatementInvalid, 'Cannot add columns to a SQLite database while inside a transaction' + end + alter_table(table_name) do |definition| definition.column(column_name, type, options) end -- cgit v1.2.3 From 319ae4628f4e0058de3e40e4ca7791b17e45e70c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 27 Jan 2009 18:54:01 -0600 Subject: Move HTTP libs and middleware into ActionDispatch component --- activerecord/lib/active_record/session_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index 5e45cf65ab..74d91f129e 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -40,7 +40,7 @@ module ActiveRecord # # The example SqlBypass class is a generic SQL session store. You may # use it as a basis for high-performance database-specific stores. - class SessionStore < ActionController::Session::AbstractStore + class SessionStore < ActionDispatch::Session::AbstractStore # The default Active Record class. class Session < ActiveRecord::Base ## -- cgit v1.2.3 From f97832b1e4406a76d268a96b521d2297adec0ae3 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Tue, 24 Mar 2009 12:15:43 +0000 Subject: Merge docrails --- activerecord/lib/active_record/base.rb | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 2a5385119d..9943a7014a 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -810,25 +810,28 @@ module ActiveRecord #:nodoc: # Updates all records with details given if they match a set of conditions supplied, limits and order can # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the - # database. It does not instantiate the involved models and it does not trigger Active Record callbacks. + # database. It does not instantiate the involved models and it does not trigger Active Record callbacks + # or validations. # # ==== Parameters # - # * +updates+ - A string of column and value pairs that will be set on any records that match conditions. This creates the SET clause of the generated SQL. - # * +conditions+ - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro for more info. + # * +updates+ - A string, array, or hash representing the SET part of an SQL statement. + # * +conditions+ - A string, array, or hash representing the WHERE part of an SQL statement. See conditions in the intro. # * +options+ - Additional options are :limit and :order, see the examples for usage. # # ==== Examples # - # # Update all billing objects with the 3 different attributes given - # Billing.update_all( "category = 'authorized', approved = 1, author = 'David'" ) + # # Update all customers with the given attributes + # Customer.update_all :wants_email => true # - # # Update records that match our conditions - # Billing.update_all( "author = 'David'", "title LIKE '%Rails%'" ) + # # Update all books with 'Rails' in their title + # Book.update_all "author = 'David'", "title LIKE '%Rails%'" # - # # Update records that match our conditions but limit it to 5 ordered by date - # Billing.update_all( "author = 'David'", "title LIKE '%Rails%'", - # :order => 'created_at', :limit => 5 ) + # # Update all avatars migrated more than a week ago + # Avatar.update_all ['migrated_at = ?, Time.now.utc], ['migrated_at > ?', 1.week.ago] + # + # # Update all books that match our conditions, but limit it to 5 ordered by date + # Book.update_all "author = 'David'", "title LIKE '%Rails%'", :order => 'created_at', :limit => 5 def update_all(updates, conditions = nil, options = {}) sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} " -- cgit v1.2.3 From 42cdc7571d115c5eb4ece440001d221f24553100 Mon Sep 17 00:00:00 2001 From: Luca Guidi Date: Tue, 31 Mar 2009 16:39:13 +0200 Subject: Ensure SqlBypass use ActiveRecord::Base connection Signed-off-by: Michael Koziarski [#https://rails.lighthouseapp.com/attachments/106066/0001-Ensure-SqlBypass-use-ActiveRecord-Base-connection.patch state:committed] --- activerecord/lib/active_record/session_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index 3cc4640f42..8fc5c9e7a6 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -184,7 +184,7 @@ module ActiveRecord # Look up a session by id and unmarshal its data if found. def find_by_session_id(session_id) - if record = @@connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{@@connection.quote(session_id)}") + if record = connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{connection.quote(session_id)}") new(:session_id => session_id, :marshaled_data => record['data']) end end -- cgit v1.2.3 From 632bbbfe1cc49ab92c6de858865ffcdcfa67635f Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 4 Apr 2009 17:33:36 +0100 Subject: Merge docrails --- activerecord/lib/active_record/transactions.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 0b6e52c79b..b059eb7f6f 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -175,6 +175,8 @@ module ActiveRecord # end # RELEASE savepoint active_record_1 # # ^^^^ BOOM! database error! # end + # + # Note that "TRUNCATE" is also a MySQL DDL statement! module ClassMethods # See ActiveRecord::Transactions::ClassMethods for detailed documentation. def transaction(options = {}, &block) -- cgit v1.2.3 From 70de8e64e30092b2b1b77869e459b4868f5b9577 Mon Sep 17 00:00:00 2001 From: Max Lapshin Date: Sat, 4 Apr 2009 18:11:33 +0100 Subject: Support multiple schemas in table names for postgresql [#390 state:resolved] Signed-off-by: Pratik Naik --- .../connection_adapters/postgresql_adapter.rb | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 913bb521ca..ec204d0f03 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -392,9 +392,28 @@ module ActiveRecord quote_string(s) end + # Checks the following cases: + # + # - table_name + # - "table.name" + # - schema_name.table_name + # - schema_name."table.name" + # - "schema.name".table_name + # - "schema.name"."table.name" + def quote_table_name(name) + schema, name_part = extract_pg_identifier_from_name(name.to_s) + + unless name_part + quote_column_name(schema) + else + table_name, name_part = extract_pg_identifier_from_name(name_part) + "#{quote_column_name(schema)}.#{quote_column_name(table_name)}" + end + end + # Quotes column names for use in SQL queries. def quote_column_name(name) #:nodoc: - %("#{name}") + PGconn.quote_ident(name.to_s) end # Quote date/time values for use in SQL input. Includes microseconds @@ -1045,6 +1064,16 @@ module ActiveRecord ORDER BY a.attnum end_sql end + + def extract_pg_identifier_from_name(name) + match_data = name[0,1] == '"' ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/) + + if match_data + rest = name[match_data[0].length..-1] + rest = rest[1..-1] if rest[0,1] == "." + [match_data[1], (rest.length > 0 ? rest : nil)] + end + end end end end -- cgit v1.2.3 From fdb61f02c54bda0ad5ff6d0259209113202b9307 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 16 Apr 2009 16:48:07 -0500 Subject: Added ActiveRecord::Base#touch to update the updated_at/on attributes with the current time [DHH] --- activerecord/lib/active_record/timestamp.rb | 38 ++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 8dbe80a01a..648861f8d4 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -15,27 +15,47 @@ module ActiveRecord base.class_inheritable_accessor :record_timestamps, :instance_writer => false base.record_timestamps = true end + + # Saves the record with the updated_at/on attributes set to the current time. + # If the save fails because of validation errors, an ActiveRecord::RecordInvalid exception is raised. + def touch + current_time = current_time_from_proper_timezone + + write_attribute('updated_at', current_time) if respond_to?(:updated_at) + write_attribute('updated_on', current_time) if respond_to?(:updated_on) + + save! + end + private def create_with_timestamps #:nodoc: if record_timestamps - t = self.class.default_timezone == :utc ? Time.now.utc : Time.now - write_attribute('created_at', t) if respond_to?(:created_at) && created_at.nil? - write_attribute('created_on', t) if respond_to?(:created_on) && created_on.nil? + current_time = current_time_from_proper_timezone + + write_attribute('created_at', current_time) if respond_to?(:created_at) && created_at.nil? + write_attribute('created_on', current_time) if respond_to?(:created_on) && created_on.nil? - write_attribute('updated_at', t) if respond_to?(:updated_at) && updated_at.nil? - write_attribute('updated_on', t) if respond_to?(:updated_on) && updated_on.nil? + write_attribute('updated_at', current_time) if respond_to?(:updated_at) && updated_at.nil? + write_attribute('updated_on', current_time) if respond_to?(:updated_on) && updated_on.nil? end + create_without_timestamps end def update_with_timestamps(*args) #:nodoc: if record_timestamps && (!partial_updates? || changed?) - t = self.class.default_timezone == :utc ? Time.now.utc : Time.now - write_attribute('updated_at', t) if respond_to?(:updated_at) - write_attribute('updated_on', t) if respond_to?(:updated_on) + current_time = current_time_from_proper_timezone + + write_attribute('updated_at', current_time) if respond_to?(:updated_at) + write_attribute('updated_on', current_time) if respond_to?(:updated_on) end + update_without_timestamps(*args) end + + def current_time_from_proper_timezone + self.class.default_timezone == :utc ? Time.now.utc : Time.now + end end -end +end \ No newline at end of file -- cgit v1.2.3 From abb899c54e8777428b7a607774370ba29a5573bd Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 16 Apr 2009 17:25:55 -0500 Subject: Added :touch option to belongs_to associations that will touch the parent record when the current record is saved or destroyed [DHH] --- activerecord/lib/active_record/associations.rb | 68 +++++++++++++++++--------- activerecord/lib/active_record/timestamp.rb | 16 ++++-- 2 files changed, 58 insertions(+), 26 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 6d25b36aea..53a710537f 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -981,6 +981,9 @@ module ActiveRecord # If false, don't validate the associated objects when saving the parent object. +false+ by default. # [:autosave] # If true, always save the associated object or destroy it if marked for destruction, when saving the parent object. Off by default. + # [:touch] + # If true, the associated object will be touched (the updated_at/on attributes set to now) when this record is either saved or + # destroyed. If you specify a symbol, that attribute will be updated with the current time instead of the updated_at/on attribute. # # Option examples: # belongs_to :firm, :foreign_key => "client_of" @@ -990,6 +993,8 @@ module ActiveRecord # belongs_to :attachable, :polymorphic => true # belongs_to :project, :readonly => true # belongs_to :post, :counter_cache => true + # belongs_to :company, :touch => true + # belongs_to :company, :touch => :employees_last_updated_at def belongs_to(association_id, options = {}) reflection = create_belongs_to_reflection(association_id, options) @@ -1001,28 +1006,8 @@ module ActiveRecord association_constructor_method(:create, reflection, BelongsToAssociation) end - # Create the callbacks to update counter cache - if options[:counter_cache] - cache_column = reflection.counter_cache_column - - method_name = "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym - define_method(method_name) do - association = send(reflection.name) - association.class.increment_counter(cache_column, send(reflection.primary_key_name)) unless association.nil? - end - after_create method_name - - method_name = "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym - define_method(method_name) do - association = send(reflection.name) - association.class.decrement_counter(cache_column, send(reflection.primary_key_name)) unless association.nil? - end - before_destroy method_name - - module_eval( - "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)" - ) - end + add_counter_cache_callbacks(reflection) if options[:counter_cache] + add_touch_callbacks(reflection, options[:touch]) if options[:touch] configure_dependency_for_belongs_to(reflection) end @@ -1329,6 +1314,43 @@ module ActiveRecord end end + def add_counter_cache_callbacks(reflection) + cache_column = reflection.counter_cache_column + + method_name = "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym + define_method(method_name) do + association = send(reflection.name) + association.class.increment_counter(cache_column, send(reflection.primary_key_name)) unless association.nil? + end + after_create(method_name) + + method_name = "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym + define_method(method_name) do + association = send(reflection.name) + association.class.decrement_counter(cache_column, send(reflection.primary_key_name)) unless association.nil? + end + before_destroy(method_name) + + module_eval( + "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)" + ) + end + + def add_touch_callbacks(reflection, touch_attribute) + method_name = "belongs_to_touch_after_save_or_destroy_for_#{reflection.name}".to_sym + define_method(method_name) do + association = send(reflection.name) + + if touch_attribute == true + association.touch unless association.nil? + else + association.touch(touch_attribute) unless association.nil? + end + end + after_save(method_name) + after_destroy(method_name) + end + def find_with_associations(options = {}) catch :invalid_query do join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins]) @@ -1499,7 +1521,7 @@ module ActiveRecord @@valid_keys_for_belongs_to_association = [ :class_name, :foreign_key, :foreign_type, :remote, :select, :conditions, :include, :dependent, :counter_cache, :extend, :polymorphic, :readonly, - :validate + :validate, :touch ] def create_belongs_to_reflection(association_id, options) diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 648861f8d4..d9e1ef351f 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -18,11 +18,21 @@ module ActiveRecord # Saves the record with the updated_at/on attributes set to the current time. # If the save fails because of validation errors, an ActiveRecord::RecordInvalid exception is raised. - def touch + # If an attribute name is passed, that attribute is used for the touch instead of the updated_at/on attributes. + # + # Examples: + # + # product.touch # updates updated_at + # product.touch(:designed_at) # updates the designed_at attribute + def touch(attribute = nil) current_time = current_time_from_proper_timezone - write_attribute('updated_at', current_time) if respond_to?(:updated_at) - write_attribute('updated_on', current_time) if respond_to?(:updated_on) + if attribute + write_attribute(attribute, current_time) + else + write_attribute('updated_at', current_time) if respond_to?(:updated_at) + write_attribute('updated_on', current_time) if respond_to?(:updated_on) + end save! end -- cgit v1.2.3 From 489abfd3b23f3c4b3de86aeb3bde3970771c001b Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 20 Apr 2009 13:51:11 +0100 Subject: Ensure JoinAssociation uses aliased table name when multiple associations have hash conditions on the same table --- activerecord/lib/active_record/associations.rb | 2 +- activerecord/lib/active_record/associations/association_proxy.rb | 4 ++-- activerecord/lib/active_record/base.rb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 53a710537f..fa18822c24 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -2123,7 +2123,7 @@ module ActiveRecord klass.send(:type_condition, aliased_table_name)] unless klass.descends_from_active_record? [through_reflection, reflection].each do |ref| - join << "AND #{interpolate_sql(sanitize_sql(ref.options[:conditions]))} " if ref && ref.options[:conditions] + join << "AND #{interpolate_sql(sanitize_sql(ref.options[:conditions], aliased_table_name))} " if ref && ref.options[:conditions] end join diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index 676c4ace61..241b9bfee0 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -169,8 +169,8 @@ module ActiveRecord end # Forwards the call to the reflection class. - def sanitize_sql(sql) - @reflection.klass.send(:sanitize_sql, sql) + def sanitize_sql(sql, table_name = @reflection.klass.quoted_table_name) + @reflection.klass.send(:sanitize_sql, sql, table_name) end # Assigns the ID of the owner to the corresponding foreign key in +record+. diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 9943a7014a..251d5000f5 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -2231,12 +2231,12 @@ module ActiveRecord #:nodoc: # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'" # { :name => "foo'bar", :group_id => 4 } returns "name='foo''bar' and group_id='4'" # "name='foo''bar' and group_id='4'" returns "name='foo''bar' and group_id='4'" - def sanitize_sql_for_conditions(condition) + def sanitize_sql_for_conditions(condition, table_name = quoted_table_name) return nil if condition.blank? case condition when Array; sanitize_sql_array(condition) - when Hash; sanitize_sql_hash_for_conditions(condition) + when Hash; sanitize_sql_hash_for_conditions(condition, table_name) else condition end end -- cgit v1.2.3 From de0ea3866370ec61581f910cf393a3cc97eba32f Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 20 Apr 2009 18:12:40 +0100 Subject: Ensure :dependent => :delete_all works for association with hash conditions --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index fa18822c24..2115878e32 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1375,7 +1375,7 @@ module ActiveRecord dependent_conditions = [] dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}" dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as] - dependent_conditions << sanitize_sql(reflection.options[:conditions]) if reflection.options[:conditions] + dependent_conditions << sanitize_sql(reflection.options[:conditions], reflection.quoted_table_name) if reflection.options[:conditions] dependent_conditions << extra_conditions if extra_conditions dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ") dependent_conditions = dependent_conditions.gsub('@', '\@') -- cgit v1.2.3 From cdcd638c2f27ebf98ba7aa59512547f58a5e0c61 Mon Sep 17 00:00:00 2001 From: Max Lapshin Date: Mon, 20 Apr 2009 20:08:51 +0400 Subject: Fixed wrong quoting of index names in postgres [#2402 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tarmo Tänav --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ec204d0f03..15e155d025 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -858,7 +858,7 @@ module ActiveRecord # Drops an index from a table. def remove_index(table_name, options = {}) - execute "DROP INDEX #{index_name(table_name, options)}" + execute "DROP INDEX #{quote_table_name(index_name(table_name, options))}" end # Maps logical Rails types to PostgreSQL-specific data types. -- cgit v1.2.3 From 64b33b6cf9db508d2c12394cc1a3f36c91fb2eed Mon Sep 17 00:00:00 2001 From: Scott Woods Date: Mon, 20 Apr 2009 23:48:02 +0300 Subject: Quote table names when casting to regclass so that capitalized tables are supported. [#2418 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tarmo Tänav --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 15e155d025..74ee6a133f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -764,7 +764,7 @@ module ActiveRecord AND attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1] AND cons.contype = 'p' - AND dep.refobjid = '#{table}'::regclass + AND dep.refobjid = '#{quote_table_name(table)}'::regclass end_sql if result.nil? or result.empty? @@ -783,7 +783,7 @@ module ActiveRecord JOIN pg_attribute attr ON (t.oid = attrelid) JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum) JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1]) - WHERE t.oid = '#{table}'::regclass + WHERE t.oid = '#{quote_table_name(table)}'::regclass AND cons.contype = 'p' AND def.adsrc ~* 'nextval' end_sql @@ -1059,7 +1059,7 @@ module ActiveRecord SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum - WHERE a.attrelid = '#{table_name}'::regclass + WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum end_sql -- cgit v1.2.3 From f3ac4f387dd748db349ec217030d2b13260516f1 Mon Sep 17 00:00:00 2001 From: Max Lapshin Date: Mon, 20 Apr 2009 19:47:31 +0400 Subject: Fixed dumping from postgresql columns in index in wrong order. [#2515 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tarmo Tänav --- .../connection_adapters/postgresql_adapter.rb | 33 ++++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 74ee6a133f..4961793866 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -640,33 +640,36 @@ module ActiveRecord def indexes(table_name, name = nil) schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',') result = query(<<-SQL, name) - SELECT distinct i.relname, d.indisunique, a.attname - FROM pg_class t, pg_class i, pg_index d, pg_attribute a + SELECT distinct i.relname, d.indisunique, d.indkey, t.oid + FROM pg_class t, pg_class i, pg_index d WHERE i.relkind = 'i' AND d.indexrelid = i.oid AND d.indisprimary = 'f' AND t.oid = d.indrelid AND t.relname = '#{table_name}' AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) ) - AND a.attrelid = t.oid - AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum - OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum - OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum - OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum - OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum ) ORDER BY i.relname SQL - current_index = nil + indexes = [] - result.each do |row| - if current_index != row[0] - indexes << IndexDefinition.new(table_name, row[0], row[1] == "t", []) - current_index = row[0] - end + indexes = result.map do |row| + index_name = row[0] + unique = row[1] == 't' + indkey = row[2].split(" ") + oid = row[3] + + columns = query(<<-SQL, "Columns for index #{row[0]} on #{table_name}").inject({}) {|attlist, r| attlist[r[1]] = r[0]; attlist} + SELECT a.attname, a.attnum + FROM pg_attribute a + WHERE a.attrelid = #{oid} + AND a.attnum IN (#{indkey.join(",")}) + SQL + + column_names = indkey.map {|attnum| columns[attnum] } + IndexDefinition.new(table_name, index_name, unique, column_names) - indexes.last.columns << row[2] end indexes -- cgit v1.2.3 From 504d16ccdfcd689eac31c1646957b06cc0ce55d1 Mon Sep 17 00:00:00 2001 From: Alex Pooley Date: Mon, 16 Feb 2009 11:44:48 +0900 Subject: Add microsecond support for sqlite adapter [#1982 state:resolved] Signed-off-by: Pratik Naik --- .../lib/active_record/connection_adapters/sqlite_adapter.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index afd6472db8..05334a830a 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -150,6 +150,16 @@ module ActiveRecord %Q("#{name}") end + # Quote date/time values for use in SQL input. Includes microseconds + # if the value is a Time responding to usec. + def quoted_date(value) #:nodoc: + if value.acts_like?(:time) && value.respond_to?(:usec) + "#{super}.#{sprintf("%06d", value.usec)}" + else + super + end + end + # DATABASE STATEMENTS ====================================== -- cgit v1.2.3