diff --git a/Rakefile b/Rakefile index 1a50839..ff42901 100644 --- a/Rakefile +++ b/Rakefile @@ -36,7 +36,7 @@ namespace :display do end task :default => ["display:notice"] -ADAPTERS = %w(mysql mysql2 jdbcmysql postgresql sqlite3 seamless_database_pool mysqlspatial mysql2spatial spatialite postgis) +ADAPTERS = %w(mysql mysql2 jdbcmysql postgresql sqlite3 seamless_database_pool) ADAPTERS.each do |adapter| namespace :test do desc "Runs #{adapter} database tests." diff --git a/lib/activerecord-import/active_record/adapters/mysql2_adapter.rb b/lib/activerecord-import/active_record/adapters/mysql2_adapter.rb index 74828b7..7f34e2f 100644 --- a/lib/activerecord-import/active_record/adapters/mysql2_adapter.rb +++ b/lib/activerecord-import/active_record/adapters/mysql2_adapter.rb @@ -1,6 +1,6 @@ require "active_record/connection_adapters/mysql2_adapter" -require "activerecord-import/adapters/mysql2_adapter" +require "activerecord-import/adapters/mysql_adapter" class ActiveRecord::ConnectionAdapters::Mysql2Adapter - include ActiveRecord::Import::Mysql2Adapter + include ActiveRecord::Import::MysqlAdapter end diff --git a/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb b/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb index c50b8ca..f0940c8 100644 --- a/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +++ b/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb @@ -1,7 +1,7 @@ require "active_record/connection_adapters/sqlite3_adapter" require "activerecord-import/adapters/sqlite3_adapter" -class ActiveRecord::ConnectionAdapters::SQLite3Adapter - include ActiveRecord::Import::SQLite3Adapter +class ActiveRecord::ConnectionAdapters::Sqlite3Adapter + include ActiveRecord::Import::Sqlite3Adapter end diff --git a/lib/activerecord-import/adapters/abstract_adapter.rb b/lib/activerecord-import/adapters/abstract_adapter.rb index 3fcc353..5f38001 100644 --- a/lib/activerecord-import/adapters/abstract_adapter.rb +++ b/lib/activerecord-import/adapters/abstract_adapter.rb @@ -34,7 +34,7 @@ module ActiveRecord::Import::AbstractAdapter # elements that are in position >= 1 will be appended to the final SQL. def insert_many( sql, values, *args ) # :nodoc: # the number of inserts default - number_of_inserts, last_inserted_id = 0, nil + number_of_inserts = 0 base_sql,post_sql = if sql.is_a?( String ) [ sql, '' ] @@ -59,17 +59,17 @@ module ActiveRecord::Import::AbstractAdapter if NO_MAX_PACKET == max or total_bytes < max number_of_inserts += 1 sql2insert = base_sql + values.join( ',' ) + post_sql - last_inserted_id = insert( sql2insert, *args ) + insert( sql2insert, *args ) else value_sets = self.class.get_insert_value_sets( values, sql_size, max ) value_sets.each do |values| number_of_inserts += 1 sql2insert = base_sql + values.join( ',' ) + post_sql - last_inserted_id = insert( sql2insert, *args ) + insert( sql2insert, *args ) end end - [number_of_inserts, last_inserted_id] + number_of_inserts end def pre_sql_statements(options) diff --git a/lib/activerecord-import/adapters/mysql2_adapter.rb b/lib/activerecord-import/adapters/mysql2_adapter.rb deleted file mode 100644 index 71e6a64..0000000 --- a/lib/activerecord-import/adapters/mysql2_adapter.rb +++ /dev/null @@ -1,5 +0,0 @@ -require File.dirname(__FILE__) + "/mysql_adapter" - -module ActiveRecord::Import::Mysql2Adapter - include ActiveRecord::Import::MysqlAdapter -end \ No newline at end of file diff --git a/lib/activerecord-import/adapters/sqlite3_adapter.rb b/lib/activerecord-import/adapters/sqlite3_adapter.rb index 2fb673d..0d298a4 100644 --- a/lib/activerecord-import/adapters/sqlite3_adapter.rb +++ b/lib/activerecord-import/adapters/sqlite3_adapter.rb @@ -1,4 +1,4 @@ -module ActiveRecord::Import::SQLite3Adapter +module ActiveRecord::Import::Sqlite3Adapter def next_value_for_sequence(sequence_name) %{nextval('#{sequence_name}')} end diff --git a/lib/activerecord-import/base.rb b/lib/activerecord-import/base.rb index 8498357..8aeb27c 100644 --- a/lib/activerecord-import/base.rb +++ b/lib/activerecord-import/base.rb @@ -5,20 +5,10 @@ require "active_record/version" module ActiveRecord::Import AdapterPath = File.join File.expand_path(File.dirname(__FILE__)), "/active_record/adapters" - def self.base_adapter(adapter) - case adapter - when 'mysqlspatial' then 'mysql' - when 'mysql2spatial' then 'mysql2' - when 'spatialite' then 'sqlite3' - when 'postgis' then 'postgresql' - else adapter - end - end - # Loads the import functionality for a specific database adapter def self.require_adapter(adapter) require File.join(AdapterPath,"/abstract_adapter") - require File.join(AdapterPath,"/#{base_adapter(adapter)}_adapter") + require File.join(AdapterPath,"/#{adapter}_adapter") end # Loads the import functionality for the passed in ActiveRecord connection diff --git a/lib/activerecord-import/import.rb b/lib/activerecord-import/import.rb index ecb634a..a596a4c 100644 --- a/lib/activerecord-import/import.rb +++ b/lib/activerecord-import/import.rb @@ -3,7 +3,7 @@ require "ostruct" module ActiveRecord::Import::ConnectionAdapters ; end module ActiveRecord::Import #:nodoc: - class Result < Struct.new(:failed_instances, :num_inserts, :last_inserted_id) + class Result < Struct.new(:failed_instances, :num_inserts) end module ImportSupport #:nodoc: @@ -137,8 +137,8 @@ class ActiveRecord::Base # # # Example synchronizing unsaved/new instances in memory by using a uniqued imported field # posts = [BlogPost.new(:title => "Foo"), BlogPost.new(:title => "Bar")] - # BlogPost.import posts, :synchronize => posts, :synchronize_keys => [:title] - # puts posts.first.persisted? # => true + # BlogPost.import posts, :synchronize => posts + # puts posts.first.new_record? # => false # # == On Duplicate Key Update (MySQL only) # @@ -162,10 +162,9 @@ class ActiveRecord::Base # BlogPost.import columns, attributes, :on_duplicate_key_update=>{ :title => :title } # # = Returns - # This returns an object which responds to +failed_instances+, +num_inserts+, +last_inserted_id+. + # This returns an object which responds to +failed_instances+ and +num_inserts+. # * failed_instances - an array of objects that fails validation and were not committed to the database. An empty array if no validation is performed. - # * num_inserts - the number of insert statements it took to import the data. - # * last_inserted_id - the last inserted id. Should be the id of the latest inserted row. + # * num_inserts - the number of insert statements it took to import the data def import( *args ) options = { :validate=>true, :timestamps=>true } options.merge!( args.pop ) if args.last.is_a? Hash @@ -192,7 +191,7 @@ class ActiveRecord::Base end # supports empty array elsif args.last.is_a?( Array ) and args.last.empty? - return ActiveRecord::Import::Result.new([], 0, nil) if args.last.empty? + return ActiveRecord::Import::Result.new([], 0) if args.last.empty? # supports 2-element array and array elsif args.size == 2 and args.first.is_a?( Array ) and args.last.is_a?( Array ) column_names, array_of_attributes = args @@ -219,8 +218,8 @@ class ActiveRecord::Base return_obj = if is_validating import_with_validations( column_names, array_of_attributes, options ) else - [num_inserts, last_inserted_id] = import_without_validations_or_callbacks( column_names, array_of_attributes, options ) - ActiveRecord::Import::Result.new([], num_inserts, last_inserted_id) + num_inserts = import_without_validations_or_callbacks( column_names, array_of_attributes, options ) + ActiveRecord::Import::Result.new([], num_inserts) end if options[:synchronize] @@ -262,12 +261,12 @@ class ActiveRecord::Base end array_of_attributes.compact! - num_inserts, last_inserted_id = if array_of_attributes.empty? || options[:all_or_none] && failed_instances.any? - [0, nil] + num_inserts = if array_of_attributes.empty? || options[:all_or_none] && failed_instances.any? + 0 else import_without_validations_or_callbacks( column_names, array_of_attributes, options ) end - ActiveRecord::Import::Result.new(failed_instances, num_inserts, last_inserted_id) + ActiveRecord::Import::Result.new(failed_instances, num_inserts) end # Imports the passed in +column_names+ and +array_of_attributes+ @@ -277,14 +276,6 @@ class ActiveRecord::Base # information on +column_names+, +array_of_attributes_ and # +options+. def import_without_validations_or_callbacks( column_names, array_of_attributes, options={} ) - number_inserted, last_inserted_id = 0, nil - scope_columns, scope_values = scope_attributes.to_a.transpose - - unless scope_columns.blank? - column_names.concat scope_columns - array_of_attributes.each { |a| a.concat scope_values } - end - columns = column_names.each_with_index.map do |name, i| column = columns_hash[name.to_s] @@ -307,11 +298,11 @@ class ActiveRecord::Base post_sql_statements = connection.post_sql_statements( quoted_table_name, options ) # perform the inserts - number_inserted, last_inserted_id = connection.insert_many( [ insert_sql, post_sql_statements ].flatten, + number_inserted = connection.insert_many( [ insert_sql, post_sql_statements ].flatten, values_sql, "#{self.class.name} Create Many Without Validations Or Callbacks" ) end - [number_inserted, last_inserted_id] + number_inserted end private @@ -319,22 +310,14 @@ class ActiveRecord::Base # Returns SQL the VALUES for an INSERT statement given the passed in +columns+ # and +array_of_attributes+. def values_sql_for_columns_and_attributes(columns, array_of_attributes) # :nodoc: - # connection gets called a *lot* in this high intensity loop. - # Reuse the same one w/in the loop, otherwise it would keep being re-retreived (= lots of time for large imports) - connection_memo = connection array_of_attributes.map do |arr| my_values = arr.each_with_index.map do |val,j| column = columns[j] - # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly - if val.nil? && column.name == primary_key && !sequence_name.blank? - connection_memo.next_value_for_sequence(sequence_name) + if val.nil? && !sequence_name.blank? && column.name == primary_key + connection.next_value_for_sequence(sequence_name) else - if serialized_attributes.include?(column.name) - connection_memo.quote(serialized_attributes[column.name].dump(val), column) - else - connection_memo.quote(val, column) - end + connection.quote(column.type_cast(val), column) end end "(#{my_values.join(',')})" diff --git a/lib/activerecord-import/synchronize.rb b/lib/activerecord-import/synchronize.rb index a5286d7..60408e5 100644 --- a/lib/activerecord-import/synchronize.rb +++ b/lib/activerecord-import/synchronize.rb @@ -43,10 +43,6 @@ module ActiveRecord # :nodoc: instance.clear_aggregation_cache instance.clear_association_cache instance.instance_variable_set '@attributes', matched_instance.attributes - # Since the instance now accurately reflects the record in - # the database, ensure that instance.persisted? is true. - instance.instance_variable_set '@new_record', false - instance.instance_variable_set '@destroyed', false end end end @@ -56,4 +52,4 @@ module ActiveRecord # :nodoc: self.class.synchronize(instances, key) end end -end +end \ No newline at end of file diff --git a/test/active_record/connection_adapter_test.rb b/test/active_record/connection_adapter_test.rb index 5b81e7d..ad3234c 100644 --- a/test/active_record/connection_adapter_test.rb +++ b/test/active_record/connection_adapter_test.rb @@ -50,13 +50,3 @@ describe "ActiveRecord::ConnectionAdapter::AbstractAdapter" do end end - -describe "ActiveRecord::Import DB-specific adapter class" do - context "when ActiveRecord::Import is in use" do - it "should appear in the AR connection adapter class's ancestors" do - connection = ActiveRecord::Base.connection - import_class_name = 'ActiveRecord::Import::' + connection.class.name.demodulize - assert_includes connection.class.ancestors, import_class_name.constantize - end - end -end \ No newline at end of file diff --git a/test/adapters/mysql2spatial.rb b/test/adapters/mysql2spatial.rb deleted file mode 100644 index 3bc9f6c..0000000 --- a/test/adapters/mysql2spatial.rb +++ /dev/null @@ -1 +0,0 @@ -ENV["ARE_DB"] = "mysql2spatial" \ No newline at end of file diff --git a/test/adapters/mysqlspatial.rb b/test/adapters/mysqlspatial.rb deleted file mode 100644 index 03316d1..0000000 --- a/test/adapters/mysqlspatial.rb +++ /dev/null @@ -1 +0,0 @@ -ENV["ARE_DB"] = "mysqlspatial" \ No newline at end of file diff --git a/test/adapters/postgis.rb b/test/adapters/postgis.rb deleted file mode 100644 index 0902039..0000000 --- a/test/adapters/postgis.rb +++ /dev/null @@ -1 +0,0 @@ -ENV["ARE_DB"] = "postgis" \ No newline at end of file diff --git a/test/adapters/spatialite.rb b/test/adapters/spatialite.rb deleted file mode 100644 index 1ff27f2..0000000 --- a/test/adapters/spatialite.rb +++ /dev/null @@ -1 +0,0 @@ -ENV["ARE_DB"] = "spatialite" \ No newline at end of file diff --git a/test/database.yml.sample b/test/database.yml.sample index 9bd8221..6a9a364 100644 --- a/test/database.yml.sample +++ b/test/database.yml.sample @@ -13,12 +13,6 @@ mysql2: <<: *common adapter: mysql2 -mysqlspatial: - <<: *mysql - -mysqlspatial2: - <<: *mysql2 - seamless_database_pool: <<: *common adapter: seamless_database_pool @@ -32,9 +26,6 @@ postgresql: adapter: postgresql min_messages: warning -postgis: - <<: *postgresql - oracle: <<: *common adapter: oracle @@ -47,6 +38,3 @@ sqlite: sqlite3: adapter: sqlite3 database: test.db - -spatialite: - <<: *sqlite3 diff --git a/test/import_test.rb b/test/import_test.rb index cc06891..982154e 100644 --- a/test/import_test.rb +++ b/test/import_test.rb @@ -134,18 +134,8 @@ describe "#import" do let(:new_topics) { Build(3, :topics) } it "reloads data for existing in-memory instances" do - Topic.import(new_topics, :synchronize => new_topics, :synchronize_keys => [:title] ) - assert new_topics.all?(&:persisted?), "Records should have been reloaded" - end - end - - context "synchronizing on destroyed records with explicit conditions" do - let(:new_topics) { Generate(3, :topics) } - - it "reloads data for existing in-memory instances" do - new_topics.each &:destroy - Topic.import(new_topics, :synchronize => new_topics, :synchronize_keys => [:title] ) - assert new_topics.all?(&:persisted?), "Records should have been reloaded" + Topic.import(new_topics, :synchronize => new_topics, :synchronize_key => [:title] ) + assert new_topics.all?(&:new_record?), "Records should have been reloaded" end end end @@ -303,18 +293,4 @@ describe "#import" do assert_equal "2010/05/14".to_date, Topic.last.last_read.to_date end end - - context "importing through an association scope" do - [ true, false ].each do |b| - context "when validation is " + (b ? "enabled" : "disabled") do - it "should automatically set the foreign key column" do - books = [[ "David Chelimsky", "The RSpec Book" ], [ "Chad Fowler", "Rails Recipes" ]] - topic = Factory.create :topic - topic.books.import [ :author_name, :title ], books, :validate => b - assert_equal 2, topic.books.count - assert topic.books.all? { |b| b.topic_id == topic.id } - end - end - end - end -end +end \ No newline at end of file diff --git a/test/mysqlspatial/import_test.rb b/test/mysqlspatial/import_test.rb deleted file mode 100644 index feaff67..0000000 --- a/test/mysqlspatial/import_test.rb +++ /dev/null @@ -1,6 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') - -require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions') -require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples') - -should_support_mysql_import_functionality \ No newline at end of file diff --git a/test/mysqlspatial2/import_test.rb b/test/mysqlspatial2/import_test.rb deleted file mode 100644 index feaff67..0000000 --- a/test/mysqlspatial2/import_test.rb +++ /dev/null @@ -1,6 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') - -require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions') -require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples') - -should_support_mysql_import_functionality \ No newline at end of file diff --git a/test/postgis/import_test.rb b/test/postgis/import_test.rb deleted file mode 100644 index 436fc83..0000000 --- a/test/postgis/import_test.rb +++ /dev/null @@ -1,4 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples') - -should_support_postgresql_import_functionality \ No newline at end of file diff --git a/test/postgresql/import_test.rb b/test/postgresql/import_test.rb index 436fc83..45e97ef 100644 --- a/test/postgresql/import_test.rb +++ b/test/postgresql/import_test.rb @@ -1,4 +1,20 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples') +require File.expand_path('../../test_helper', __FILE__) -should_support_postgresql_import_functionality \ No newline at end of file +describe "#supports_imports?" do + it "should support import" do + assert ActiveRecord::Base.supports_import? + end +end + +describe "#import" do + it "should import with a single insert" do + # see ActiveRecord::ConnectionAdapters::AbstractAdapter test for more specifics + assert_difference "Topic.count", +10 do + result = Topic.import Build(3, :topics) + assert_equal 1, result.num_inserts + + result = Topic.import Build(7, :topics) + assert_equal 1, result.num_inserts + end + end +end diff --git a/test/support/postgresql/import_examples.rb b/test/support/postgresql/import_examples.rb deleted file mode 100644 index fe7b61f..0000000 --- a/test/support/postgresql/import_examples.rb +++ /dev/null @@ -1,21 +0,0 @@ -# encoding: UTF-8 -def should_support_postgresql_import_functionality - describe "#supports_imports?" do - it "should support import" do - assert ActiveRecord::Base.supports_import? - end - end - - describe "#import" do - it "should import with a single insert" do - # see ActiveRecord::ConnectionAdapters::AbstractAdapter test for more specifics - assert_difference "Topic.count", +10 do - result = Topic.import Build(3, :topics) - assert_equal 1, result.num_inserts - - result = Topic.import Build(7, :topics) - assert_equal 1, result.num_inserts - end - end - end -end diff --git a/test/test_helper.rb b/test/test_helper.rb index a28e5b4..73f2802 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -44,8 +44,3 @@ adapter_schema = test_dir.join("schema/#{adapter}_schema.rb") require adapter_schema if File.exists?(adapter_schema) Dir[File.dirname(__FILE__) + "/models/*.rb"].each{ |file| require file } - -# Prevent this deprecation warning from breaking the tests. -module Rake::DeprecatedObjectDSL - remove_method :import -end