Providing support for the Mysql2 adapter.
This commit is contained in:
parent
f61eabda19
commit
b6c72f8456
1
Gemfile
1
Gemfile
|
@ -5,6 +5,7 @@ gem "rails", ">= 3.0.0.rc"
|
||||||
group :test do
|
group :test do
|
||||||
# Database Adapters
|
# Database Adapters
|
||||||
gem "mysql", ">= 2.8.1"
|
gem "mysql", ">= 2.8.1"
|
||||||
|
gem "mysql2", ">= 0.2.4"
|
||||||
gem "pg", ">= 0.9.0"
|
gem "pg", ">= 0.9.0"
|
||||||
gem "sqlite3-ruby", ">= 1.3.1"
|
gem "sqlite3-ruby", ">= 1.3.1"
|
||||||
|
|
||||||
|
|
5
Rakefile
5
Rakefile
|
@ -31,7 +31,7 @@ namespace :display do
|
||||||
end
|
end
|
||||||
task :default => ["display:notice"]
|
task :default => ["display:notice"]
|
||||||
|
|
||||||
ADAPTERS = %w(mysql postgresql sqlite3)
|
ADAPTERS = %w(mysql mysql2 postgresql sqlite3)
|
||||||
ADAPTERS.each do |adapter|
|
ADAPTERS.each do |adapter|
|
||||||
namespace :test do
|
namespace :test do
|
||||||
desc "Runs #{adapter} database tests."
|
desc "Runs #{adapter} database tests."
|
||||||
|
@ -44,9 +44,10 @@ end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
require 'rcov/rcovtask'
|
require 'rcov/rcovtask'
|
||||||
|
adapter = ENV['ARE_DB']
|
||||||
Rcov::RcovTask.new do |test|
|
Rcov::RcovTask.new do |test|
|
||||||
test.libs << 'test'
|
test.libs << 'test'
|
||||||
test.pattern = "test/*_test.rb"
|
test.pattern = ["test/adapters/#{adapter}.rb", "test/*_test.rb", "test/#{adapter}/**/*_test.rb"]
|
||||||
test.verbose = true
|
test.verbose = true
|
||||||
end
|
end
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
require "active_record/connection_adapters/mysql2_adapter"
|
||||||
|
require "activerecord-import/active_record/adapters/mysql_base"
|
||||||
|
|
||||||
|
class ActiveRecord::ConnectionAdapters::Mysql2Adapter
|
||||||
|
include ActiveRecord::ConnectionAdapters::MysqlBase
|
||||||
|
end
|
|
@ -1,47 +1,6 @@
|
||||||
require "active_record/connection_adapters/mysql_adapter"
|
require "active_record/connection_adapters/mysql_adapter"
|
||||||
|
require "activerecord-import/active_record/adapters/mysql_base"
|
||||||
|
|
||||||
class ActiveRecord::ConnectionAdapters::MysqlAdapter
|
class ActiveRecord::ConnectionAdapters::MysqlAdapter
|
||||||
include ActiveRecord::Extensions::Import::ImportSupport
|
include ActiveRecord::ConnectionAdapters::MysqlBase
|
||||||
include ActiveRecord::Extensions::Import::OnDuplicateKeyUpdateSupport
|
|
||||||
|
|
||||||
# Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
|
|
||||||
# in +args+.
|
|
||||||
def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
|
|
||||||
sql = ' ON DUPLICATE KEY UPDATE '
|
|
||||||
arg = args.first
|
|
||||||
if arg.is_a?( Array )
|
|
||||||
sql << sql_for_on_duplicate_key_update_as_array( table_name, arg )
|
|
||||||
elsif arg.is_a?( Hash )
|
|
||||||
sql << sql_for_on_duplicate_key_update_as_hash( table_name, arg )
|
|
||||||
elsif arg.is_a?( String )
|
|
||||||
sql << arg
|
|
||||||
else
|
|
||||||
raise ArgumentError.new( "Expected Array or Hash" )
|
|
||||||
end
|
|
||||||
sql
|
|
||||||
end
|
|
||||||
|
|
||||||
def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
|
|
||||||
results = arr.map do |column|
|
|
||||||
qc = quote_column_name( column )
|
|
||||||
"#{table_name}.#{qc}=VALUES(#{qc})"
|
|
||||||
end
|
|
||||||
results.join( ',' )
|
|
||||||
end
|
|
||||||
|
|
||||||
def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
|
|
||||||
sql = ' ON DUPLICATE KEY UPDATE '
|
|
||||||
results = hsh.map do |column1, column2|
|
|
||||||
qc1 = quote_column_name( column1 )
|
|
||||||
qc2 = quote_column_name( column2 )
|
|
||||||
"#{table_name}.#{qc1}=VALUES( #{qc2} )"
|
|
||||||
end
|
|
||||||
results.join( ',')
|
|
||||||
end
|
|
||||||
|
|
||||||
#return true if the statement is a duplicate key record error
|
|
||||||
def duplicate_key_update_error?(exception)# :nodoc:
|
|
||||||
exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry')
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
48
lib/activerecord-import/active_record/adapters/mysql_base.rb
Normal file
48
lib/activerecord-import/active_record/adapters/mysql_base.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
module ActiveRecord::ConnectionAdapters::MysqlBase
|
||||||
|
def self.included(klass)
|
||||||
|
klass.instance_eval do
|
||||||
|
include ActiveRecord::Extensions::Import::ImportSupport
|
||||||
|
include ActiveRecord::Extensions::Import::OnDuplicateKeyUpdateSupport
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
|
||||||
|
# in +args+.
|
||||||
|
def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
|
||||||
|
sql = ' ON DUPLICATE KEY UPDATE '
|
||||||
|
arg = args.first
|
||||||
|
if arg.is_a?( Array )
|
||||||
|
sql << sql_for_on_duplicate_key_update_as_array( table_name, arg )
|
||||||
|
elsif arg.is_a?( Hash )
|
||||||
|
sql << sql_for_on_duplicate_key_update_as_hash( table_name, arg )
|
||||||
|
elsif arg.is_a?( String )
|
||||||
|
sql << arg
|
||||||
|
else
|
||||||
|
raise ArgumentError.new( "Expected Array or Hash" )
|
||||||
|
end
|
||||||
|
sql
|
||||||
|
end
|
||||||
|
|
||||||
|
def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
|
||||||
|
results = arr.map do |column|
|
||||||
|
qc = quote_column_name( column )
|
||||||
|
"#{table_name}.#{qc}=VALUES(#{qc})"
|
||||||
|
end
|
||||||
|
results.join( ',' )
|
||||||
|
end
|
||||||
|
|
||||||
|
def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
|
||||||
|
sql = ' ON DUPLICATE KEY UPDATE '
|
||||||
|
results = hsh.map do |column1, column2|
|
||||||
|
qc1 = quote_column_name( column1 )
|
||||||
|
qc2 = quote_column_name( column2 )
|
||||||
|
"#{table_name}.#{qc1}=VALUES( #{qc2} )"
|
||||||
|
end
|
||||||
|
results.join( ',')
|
||||||
|
end
|
||||||
|
|
||||||
|
#return true if the statement is a duplicate key record error
|
||||||
|
def duplicate_key_update_error?(exception)# :nodoc:
|
||||||
|
exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry')
|
||||||
|
end
|
||||||
|
end
|
2
lib/activerecord-import/mysql2.rb
Normal file
2
lib/activerecord-import/mysql2.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
require File.join File.dirname(__FILE__), "base"
|
||||||
|
ActiveRecord::Extensions.require_adapter "mysql2"
|
1
test/adapters/mysql2.rb
Normal file
1
test/adapters/mysql2.rb
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ENV["ARE_DB"] = "mysql2"
|
|
@ -9,6 +9,10 @@ mysql:
|
||||||
<<: *common
|
<<: *common
|
||||||
adapter: mysql
|
adapter: mysql
|
||||||
|
|
||||||
|
mysql2:
|
||||||
|
<<: *common
|
||||||
|
adapter: mysql2
|
||||||
|
|
||||||
postgresql:
|
postgresql:
|
||||||
<<: *common
|
<<: *common
|
||||||
username: zdennis
|
username: zdennis
|
||||||
|
|
|
@ -1,118 +1,4 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
require "activerecord-import/mysql"
|
require "activerecord-import/mysql"
|
||||||
|
|
||||||
describe "#import with :on_duplicate_key_update option (mysql specific functionality)" do
|
should_support_mysql_import_functionality
|
||||||
extend ActiveSupport::TestCase::MySQLAssertions
|
|
||||||
|
|
||||||
asssertion_group(:should_support_on_duplicate_key_update) do
|
|
||||||
should_not_update_fields_not_mentioned
|
|
||||||
should_update_foreign_keys
|
|
||||||
should_not_update_created_at_on_timestamp_columns
|
|
||||||
should_update_updated_at_on_timestamp_columns
|
|
||||||
end
|
|
||||||
|
|
||||||
macro(:perform_import){ raise "supply your own #perform_import in a context below" }
|
|
||||||
macro(:updated_topic){ Topic.find(@topic) }
|
|
||||||
|
|
||||||
context "given columns and values with :validation checks turned off" do
|
|
||||||
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
|
||||||
let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
|
||||||
let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
|
||||||
|
|
||||||
macro(:perform_import) do |*opts|
|
|
||||||
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
|
||||||
end
|
|
||||||
|
|
||||||
setup do
|
|
||||||
Topic.import columns, values, :validate => false
|
|
||||||
@topic = Topic.find 99
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using string column names" do
|
|
||||||
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using symbol column names" do
|
|
||||||
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using string hash map" do
|
|
||||||
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using string hash map, but specifying column mismatches" do
|
|
||||||
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned_with_hash_mappings
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using symbol hash map" do
|
|
||||||
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using symbol hash map, but specifying column mismatches" do
|
|
||||||
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned_with_hash_mappings
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "given array of model instances with :validation checks turned off" do
|
|
||||||
macro(:perform_import) do |*opts|
|
|
||||||
@topic.title = "Book - 2nd Edition"
|
|
||||||
@topic.author_name = "Author Should Not Change"
|
|
||||||
@topic.author_email_address = "johndoe@example.com"
|
|
||||||
@topic.parent_id = 57
|
|
||||||
Topic.import [@topic], opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
|
||||||
end
|
|
||||||
|
|
||||||
setup do
|
|
||||||
@topic = Generate(:topic, :id => 99, :author_name => "John Doe", :parent_id => 17)
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using string column names" do
|
|
||||||
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using symbol column names" do
|
|
||||||
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using string hash map" do
|
|
||||||
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using string hash map, but specifying column mismatches" do
|
|
||||||
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned_with_hash_mappings
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using symbol hash map" do
|
|
||||||
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned
|
|
||||||
end
|
|
||||||
|
|
||||||
context "using symbol hash map, but specifying column mismatches" do
|
|
||||||
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
|
||||||
should_support_on_duplicate_key_update
|
|
||||||
should_update_fields_mentioned_with_hash_mappings
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
7
test/mysql2/import_test.rb
Normal file
7
test/mysql2/import_test.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
|
require "activerecord-import/mysql2"
|
||||||
|
|
||||||
|
require "test/support/mysql/assertions"
|
||||||
|
require "test/support/mysql/import_examples"
|
||||||
|
|
||||||
|
should_support_mysql_import_functionality
|
117
test/support/mysql/import_examples.rb
Normal file
117
test/support/mysql/import_examples.rb
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
def should_support_mysql_import_functionality
|
||||||
|
describe "#import with :on_duplicate_key_update option (mysql specific functionality)" do
|
||||||
|
extend ActiveSupport::TestCase::MySQLAssertions
|
||||||
|
|
||||||
|
asssertion_group(:should_support_on_duplicate_key_update) do
|
||||||
|
should_not_update_fields_not_mentioned
|
||||||
|
should_update_foreign_keys
|
||||||
|
should_not_update_created_at_on_timestamp_columns
|
||||||
|
should_update_updated_at_on_timestamp_columns
|
||||||
|
end
|
||||||
|
|
||||||
|
macro(:perform_import){ raise "supply your own #perform_import in a context below" }
|
||||||
|
macro(:updated_topic){ Topic.find(@topic) }
|
||||||
|
|
||||||
|
context "given columns and values with :validation checks turned off" do
|
||||||
|
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
||||||
|
let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
||||||
|
let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
||||||
|
|
||||||
|
macro(:perform_import) do |*opts|
|
||||||
|
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
||||||
|
end
|
||||||
|
|
||||||
|
setup do
|
||||||
|
Topic.import columns, values, :validate => false
|
||||||
|
@topic = Topic.find 99
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using string column names" do
|
||||||
|
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using symbol column names" do
|
||||||
|
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using string hash map" do
|
||||||
|
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using string hash map, but specifying column mismatches" do
|
||||||
|
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned_with_hash_mappings
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using symbol hash map" do
|
||||||
|
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using symbol hash map, but specifying column mismatches" do
|
||||||
|
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned_with_hash_mappings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "given array of model instances with :validation checks turned off" do
|
||||||
|
macro(:perform_import) do |*opts|
|
||||||
|
@topic.title = "Book - 2nd Edition"
|
||||||
|
@topic.author_name = "Author Should Not Change"
|
||||||
|
@topic.author_email_address = "johndoe@example.com"
|
||||||
|
@topic.parent_id = 57
|
||||||
|
Topic.import [@topic], opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
||||||
|
end
|
||||||
|
|
||||||
|
setup do
|
||||||
|
@topic = Generate(:topic, :id => 99, :author_name => "John Doe", :parent_id => 17)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using string column names" do
|
||||||
|
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using symbol column names" do
|
||||||
|
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using string hash map" do
|
||||||
|
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using string hash map, but specifying column mismatches" do
|
||||||
|
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned_with_hash_mappings
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using symbol hash map" do
|
||||||
|
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using symbol hash map, but specifying column mismatches" do
|
||||||
|
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
||||||
|
should_support_on_duplicate_key_update
|
||||||
|
should_update_fields_mentioned_with_hash_mappings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue