activerecord-import 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +49 -0
  3. data/.rubocop_todo.yml +36 -0
  4. data/.travis.yml +31 -7
  5. data/CHANGELOG.md +19 -0
  6. data/Gemfile +5 -2
  7. data/README.markdown +6 -1
  8. data/Rakefile +5 -2
  9. data/activerecord-import.gemspec +1 -1
  10. data/benchmarks/benchmark.rb +67 -68
  11. data/benchmarks/lib/base.rb +136 -137
  12. data/benchmarks/lib/cli_parser.rb +106 -107
  13. data/benchmarks/lib/mysql2_benchmark.rb +19 -21
  14. data/benchmarks/lib/output_to_csv.rb +2 -1
  15. data/benchmarks/lib/output_to_html.rb +8 -13
  16. data/benchmarks/schema/mysql_schema.rb +8 -8
  17. data/gemfiles/4.0.gemfile +1 -1
  18. data/gemfiles/4.1.gemfile +1 -1
  19. data/gemfiles/4.2.gemfile +1 -1
  20. data/gemfiles/5.0.gemfile +1 -1
  21. data/lib/activerecord-import.rb +2 -0
  22. data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +0 -1
  23. data/lib/activerecord-import/adapters/abstract_adapter.rb +9 -9
  24. data/lib/activerecord-import/adapters/mysql_adapter.rb +17 -17
  25. data/lib/activerecord-import/adapters/postgresql_adapter.rb +20 -22
  26. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +9 -9
  27. data/lib/activerecord-import/base.rb +3 -3
  28. data/lib/activerecord-import/import.rb +152 -131
  29. data/lib/activerecord-import/synchronize.rb +20 -20
  30. data/lib/activerecord-import/value_sets_parser.rb +7 -6
  31. data/lib/activerecord-import/version.rb +1 -1
  32. data/test/adapters/mysql2spatial.rb +1 -1
  33. data/test/adapters/postgis.rb +1 -1
  34. data/test/adapters/postgresql.rb +1 -1
  35. data/test/adapters/spatialite.rb +1 -1
  36. data/test/adapters/sqlite3.rb +1 -1
  37. data/test/import_test.rb +121 -70
  38. data/test/models/book.rb +5 -6
  39. data/test/models/chapter.rb +2 -2
  40. data/test/models/discount.rb +3 -0
  41. data/test/models/end_note.rb +2 -2
  42. data/test/models/promotion.rb +1 -1
  43. data/test/models/question.rb +1 -1
  44. data/test/models/rule.rb +2 -2
  45. data/test/models/topic.rb +3 -3
  46. data/test/models/widget.rb +1 -1
  47. data/test/postgis/import_test.rb +1 -1
  48. data/test/schema/generic_schema.rb +100 -96
  49. data/test/schema/mysql_schema.rb +5 -7
  50. data/test/sqlite3/import_test.rb +0 -2
  51. data/test/support/active_support/test_case_extensions.rb +12 -15
  52. data/test/support/assertions.rb +1 -1
  53. data/test/support/factories.rb +15 -16
  54. data/test/support/generate.rb +4 -4
  55. data/test/support/mysql/import_examples.rb +21 -21
  56. data/test/support/postgresql/import_examples.rb +83 -55
  57. data/test/support/shared_examples/on_duplicate_key_update.rb +23 -23
  58. data/test/synchronize_test.rb +2 -2
  59. data/test/test_helper.rb +6 -8
  60. data/test/value_sets_bytes_parser_test.rb +14 -17
  61. data/test/value_sets_records_parser_test.rb +6 -6
  62. metadata +7 -4
  63. data/test/travis/build.sh +0 -34
@@ -1,107 +1,106 @@
1
- require 'optparse'
2
- require 'ostruct'
3
-
4
- #
5
- # == PARAMETERS
6
- # * a - database adapter. ie: mysql, postgresql, oracle, etc.
7
- # * n - number of objects to test with. ie: 1, 100, 1000, etc.
8
- # * t - the table types to test. ie: myisam, innodb, memory, temporary, etc.
9
- #
10
- module BenchmarkOptionParser
11
- BANNER = "Usage: ruby #{$0} [options]\nSee ruby #{$0} -h for more options."
12
-
13
- def self.print_banner
14
- puts BANNER
15
- end
16
-
17
- def self.print_banner!
18
- print_banner
19
- exit
20
- end
21
-
22
- def self.print_options( options )
23
- puts "Benchmarking the following options:"
24
- puts " Database adapter: #{options.adapter}"
25
- puts " Number of objects: #{options.number_of_objects}"
26
- puts " Table types:"
27
- print_valid_table_types( options, :prefix=>" " )
28
- end
29
-
30
- # TODO IMPLEMENT THIS
31
- def self.print_valid_table_types( options, hsh={:prefix=>''} )
32
- if options.table_types.keys.size > 0
33
- options.table_types.keys.sort.each{ |type| puts hsh[:prefix].to_s + type.to_s }
34
- else
35
- puts 'No table types defined.'
36
- end
37
- end
38
-
39
- def self.parse( args )
40
- options = OpenStruct.new(
41
- :adapter => 'mysql2',
42
- :table_types => {},
43
- :delete_on_finish => true,
44
- :number_of_objects => [],
45
- :outputs => [] )
46
-
47
- opts = OptionParser.new do |opts|
48
- opts.banner = BANNER
49
-
50
- # parse the database adapter
51
- opts.on( "a", "--adapter [String]",
52
- "The database adapter to use. IE: mysql, postgresql, oracle" ) do |arg|
53
- options.adapter = arg
54
- end
55
-
56
- # parse do_not_delete flag
57
- opts.on( "d", "--do-not-delete",
58
- "By default all records in the benchmark tables will be deleted at the end of the benchmark. " +
59
- "This flag indicates not to delete the benchmark data." ) do |arg|
60
- options.delete_on_finish = false
61
- end
62
-
63
- # parse the number of row objects to test
64
- opts.on( "n", "--num [Integer]",
65
- "The number of objects to benchmark." ) do |arg|
66
- options.number_of_objects << arg.to_i
67
- end
68
-
69
- # parse the table types to test
70
- opts.on( "t", "--table-type [String]",
71
- "The table type to test. This can be used multiple times." ) do |arg|
72
- if arg =~ /^all$/
73
- options.table_types['all'] = options.benchmark_all_types = true
74
- else
75
- options.table_types[arg] = true
76
- end
77
- end
78
-
79
- # print results in CSV format
80
- opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
81
- options.outputs << OpenStruct.new( :format=>'csv', :filename=>filename)
82
- end
83
-
84
- # print results in HTML format
85
- opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
86
- options.outputs << OpenStruct.new( :format=>'html', :filename=>filename )
87
- end
88
- end #end opt.parse!
89
-
90
- begin
91
- opts.parse!( args )
92
- if options.table_types.size == 0
93
- options.table_types['all'] = options.benchmark_all_types = true
94
- end
95
- rescue Exception => ex
96
- print_banner!
97
- end
98
-
99
- options.number_of_objects = [1000] if options.number_of_objects.empty?
100
- options.outputs = [ OpenStruct.new( :format => 'html', :filename => 'benchmark.html')] if options.outputs.empty?
101
-
102
- print_options( options )
103
-
104
- options
105
- end
106
-
107
- end
1
+ require 'optparse'
2
+ require 'ostruct'
3
+
4
+ #
5
+ # == PARAMETERS
6
+ # * a - database adapter. ie: mysql, postgresql, oracle, etc.
7
+ # * n - number of objects to test with. ie: 1, 100, 1000, etc.
8
+ # * t - the table types to test. ie: myisam, innodb, memory, temporary, etc.
9
+ #
10
+ module BenchmarkOptionParser
11
+ BANNER = "Usage: ruby #{$0} [options]\nSee ruby #{$0} -h for more options.".freeze
12
+
13
+ def self.print_banner
14
+ puts BANNER
15
+ end
16
+
17
+ def self.print_banner!
18
+ print_banner
19
+ exit
20
+ end
21
+
22
+ def self.print_options( options )
23
+ puts "Benchmarking the following options:"
24
+ puts " Database adapter: #{options.adapter}"
25
+ puts " Number of objects: #{options.number_of_objects}"
26
+ puts " Table types:"
27
+ print_valid_table_types( options, prefix: " " )
28
+ end
29
+
30
+ # TODO IMPLEMENT THIS
31
+ def self.print_valid_table_types( options, hsh = { prefix: '' } )
32
+ if !options.table_types.keys.empty?
33
+ options.table_types.keys.sort.each { |type| puts hsh[:prefix].to_s + type.to_s }
34
+ else
35
+ puts 'No table types defined.'
36
+ end
37
+ end
38
+
39
+ def self.parse( args )
40
+ options = OpenStruct.new(
41
+ adapter: 'mysql2',
42
+ table_types: {},
43
+ delete_on_finish: true,
44
+ number_of_objects: [],
45
+ outputs: [] )
46
+
47
+ opt_parser = OptionParser.new do |opts|
48
+ opts.banner = BANNER
49
+
50
+ # parse the database adapter
51
+ opts.on( "a", "--adapter [String]",
52
+ "The database adapter to use. IE: mysql, postgresql, oracle" ) do |arg|
53
+ options.adapter = arg
54
+ end
55
+
56
+ # parse do_not_delete flag
57
+ opts.on( "d", "--do-not-delete",
58
+ "By default all records in the benchmark tables will be deleted at the end of the benchmark. " \
59
+ "This flag indicates not to delete the benchmark data." ) do |_|
60
+ options.delete_on_finish = false
61
+ end
62
+
63
+ # parse the number of row objects to test
64
+ opts.on( "n", "--num [Integer]",
65
+ "The number of objects to benchmark." ) do |arg|
66
+ options.number_of_objects << arg.to_i
67
+ end
68
+
69
+ # parse the table types to test
70
+ opts.on( "t", "--table-type [String]",
71
+ "The table type to test. This can be used multiple times." ) do |arg|
72
+ if arg =~ /^all$/
73
+ options.table_types['all'] = options.benchmark_all_types = true
74
+ else
75
+ options.table_types[arg] = true
76
+ end
77
+ end
78
+
79
+ # print results in CSV format
80
+ opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
81
+ options.outputs << OpenStruct.new( format: 'csv', filename: filename)
82
+ end
83
+
84
+ # print results in HTML format
85
+ opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
86
+ options.outputs << OpenStruct.new( format: 'html', filename: filename )
87
+ end
88
+ end # end opt.parse!
89
+
90
+ begin
91
+ opt_parser.parse!( args )
92
+ if options.table_types.empty?
93
+ options.table_types['all'] = options.benchmark_all_types = true
94
+ end
95
+ rescue Exception
96
+ print_banner!
97
+ end
98
+
99
+ options.number_of_objects = [1000] if options.number_of_objects.empty?
100
+ options.outputs = [OpenStruct.new( format: 'html', filename: 'benchmark.html')] if options.outputs.empty?
101
+
102
+ print_options( options )
103
+
104
+ options
105
+ end
106
+ end
@@ -1,21 +1,19 @@
1
- class Mysql2Benchmark < BenchmarkBase
2
-
3
- def benchmark_all( array_of_cols_and_vals )
4
- methods = self.methods.find_all { |m| m =~ /benchmark_/ }
5
- methods.delete_if{ |m| m =~ /benchmark_(all|model)/ }
6
- methods.each { |method| self.send( method, array_of_cols_and_vals ) }
7
- end
8
-
9
- def benchmark_myisam( array_of_cols_and_vals )
10
- bm_model( TestMyISAM, array_of_cols_and_vals )
11
- end
12
-
13
- def benchmark_innodb( array_of_cols_and_vals )
14
- bm_model( TestInnoDb, array_of_cols_and_vals )
15
- end
16
-
17
- def benchmark_memory( array_of_cols_and_vals )
18
- bm_model( TestMemory, array_of_cols_and_vals )
19
- end
20
-
21
- end
1
+ class Mysql2Benchmark < BenchmarkBase
2
+ def benchmark_all( array_of_cols_and_vals )
3
+ methods = self.methods.find_all { |m| m =~ /benchmark_/ }
4
+ methods.delete_if { |m| m =~ /benchmark_(all|model)/ }
5
+ methods.each { |method| send( method, array_of_cols_and_vals ) }
6
+ end
7
+
8
+ def benchmark_myisam( array_of_cols_and_vals )
9
+ bm_model( TestMyISAM, array_of_cols_and_vals )
10
+ end
11
+
12
+ def benchmark_innodb( array_of_cols_and_vals )
13
+ bm_model( TestInnoDb, array_of_cols_and_vals )
14
+ end
15
+
16
+ def benchmark_memory( array_of_cols_and_vals )
17
+ bm_model( TestMemory, array_of_cols_and_vals )
18
+ end
19
+ end
@@ -5,7 +5,8 @@ module OutputToCSV
5
5
  CSV.open( filename, 'w' ) do |csv|
6
6
  # Iterate over each result set, which contains many results
7
7
  results.each do |result_set|
8
- columns, times = [], []
8
+ columns = []
9
+ times = []
9
10
  result_set.each do |result|
10
11
  columns << result.description
11
12
  times << result.tms.real
@@ -1,8 +1,7 @@
1
1
  require 'erb'
2
2
 
3
3
  module OutputToHTML
4
-
5
- TEMPLATE_HEADER =<<"EOT"
4
+ TEMPLATE_HEADER = <<"EOT".freeze
6
5
  <div>
7
6
  All times are rounded to the nearest thousandth for display purposes. Speedups next to each time are computed
8
7
  before any rounding occurs. Also, all speedup calculations are computed by comparing a given time against
@@ -10,7 +9,7 @@ TEMPLATE_HEADER =<<"EOT"
10
9
  </div>
11
10
  EOT
12
11
 
13
- TEMPLATE =<<"EOT"
12
+ TEMPLATE = <<"EOT".freeze
14
13
  <style>
15
14
  td#benchmarkTitle {
16
15
  border: 1px solid black;
@@ -43,27 +42,23 @@ EOT
43
42
  def self.output_results( filename, results )
44
43
  html = ''
45
44
  results.each do |result_set|
46
- columns, times = [], []
45
+ columns = []
46
+ times = []
47
47
  result_set.each do |result|
48
48
  columns << result.description
49
49
  if result.failed
50
50
  times << "failed"
51
51
  else
52
52
  time = result.tms.real.round_to( 3 )
53
- speedup = ( result_set.first.tms.real / result.tms.real ).round
54
-
55
- if result == result_set.first
56
- times << "#{time}"
57
- else
58
- times << "#{time} (#{speedup}x speedup)"
59
- end
53
+ speedup = ( result_set.first.tms.real / result.tms.real ).round
54
+ times << result == result_set.first ? time.to_s : "#{time} (#{speedup}x speedup)"
60
55
  end
61
56
  end
62
57
 
63
58
  template = ERB.new( TEMPLATE, 0, "%<>")
64
59
  html << template.result( binding )
65
60
  end
66
-
67
- File.open( filename, 'w' ){ |file| file.write( TEMPLATE_HEADER + html ) }
61
+
62
+ File.open( filename, 'w' ) { |file| file.write( TEMPLATE_HEADER + html ) }
68
63
  end
69
64
  end
@@ -1,16 +1,16 @@
1
1
  ActiveRecord::Schema.define do
2
- create_table :test_myisam, :options=>'ENGINE=MyISAM', :force=>true do |t|
3
- t.column :my_name, :string, :null=>false
2
+ create_table :test_myisam, options: 'ENGINE=MyISAM', force: true do |t|
3
+ t.column :my_name, :string, null: false
4
4
  t.column :description, :string
5
5
  end
6
-
7
- create_table :test_innodb, :options=>'ENGINE=InnoDb', :force=>true do |t|
8
- t.column :my_name, :string, :null=>false
6
+
7
+ create_table :test_innodb, options: 'ENGINE=InnoDb', force: true do |t|
8
+ t.column :my_name, :string, null: false
9
9
  t.column :description, :string
10
10
  end
11
11
 
12
- create_table :test_memory, :options=>'ENGINE=Memory', :force=>true do |t|
13
- t.column :my_name, :string, :null=>false
12
+ create_table :test_memory, options: 'ENGINE=Memory', force: true do |t|
13
+ t.column :my_name, :string, null: false
14
14
  t.column :description, :string
15
15
  end
16
- end
16
+ end
@@ -1,3 +1,3 @@
1
1
  platforms :ruby do
2
- gem 'activerecord', '~> 4.0'
2
+ gem 'activerecord', '~> 4.0.0'
3
3
  end
@@ -1,3 +1,3 @@
1
1
  platforms :ruby do
2
- gem 'activerecord', '~> 4.1'
2
+ gem 'activerecord', '~> 4.1.0'
3
3
  end
@@ -1,3 +1,3 @@
1
1
  platforms :ruby do
2
- gem 'activerecord', '~> 4.2'
2
+ gem 'activerecord', '~> 4.2.0'
3
3
  end
@@ -1,3 +1,3 @@
1
1
  platforms :ruby do
2
- gem 'activerecord', '~> 5.0.0.beta1'
2
+ gem 'activerecord', '~> 5.0.0.beta3'
3
3
  end
@@ -1,3 +1,5 @@
1
+ # rubocop:disable Style/FileName
2
+
1
3
  ActiveSupport.on_load(:active_record) do
2
4
  class ActiveRecord::Base
3
5
  class << self
@@ -4,4 +4,3 @@ require "activerecord-import/adapters/sqlite3_adapter"
4
4
  class ActiveRecord::ConnectionAdapters::SQLite3Adapter
5
5
  include ActiveRecord::Import::SQLite3Adapter
6
6
  end
7
-
@@ -1,22 +1,22 @@
1
1
  module ActiveRecord::Import::AbstractAdapter
2
2
  module InstanceMethods
3
3
  def next_value_for_sequence(sequence_name)
4
- %{#{sequence_name}.nextval}
4
+ %(#{sequence_name}.nextval)
5
5
  end
6
6
 
7
7
  def insert_many( sql, values, *args ) # :nodoc:
8
8
  number_of_inserts = 1
9
9
 
10
- base_sql,post_sql = if sql.is_a?( String )
11
- [ sql, '' ]
10
+ base_sql, post_sql = if sql.is_a?( String )
11
+ [sql, '']
12
12
  elsif sql.is_a?( Array )
13
- [ sql.shift, sql.join( ' ' ) ]
13
+ [sql.shift, sql.join( ' ' )]
14
14
  end
15
15
 
16
16
  sql2insert = base_sql + values.join( ',' ) + post_sql
17
17
  insert( sql2insert, *args )
18
18
 
19
- [number_of_inserts,[]]
19
+ [number_of_inserts, []]
20
20
  end
21
21
 
22
22
  def pre_sql_statements(options)
@@ -25,7 +25,7 @@ module ActiveRecord::Import::AbstractAdapter
25
25
  sql << options[:command] if options[:command]
26
26
  sql << "IGNORE" if options[:ignore]
27
27
 
28
- #add keywords like IGNORE or DELAYED
28
+ # add keywords like IGNORE or DELAYED
29
29
  if options[:keywords].is_a?(Array)
30
30
  sql.concat(options[:keywords])
31
31
  elsif options[:keywords]
@@ -38,7 +38,7 @@ module ActiveRecord::Import::AbstractAdapter
38
38
  # Synchronizes the passed in ActiveRecord instances with the records in
39
39
  # the database by calling +reload+ on each instance.
40
40
  def after_import_synchronize( instances )
41
- instances.each { |e| e.reload }
41
+ instances.each(&:reload)
42
42
  end
43
43
 
44
44
  # Returns an array of post SQL statements given the passed in options.
@@ -53,10 +53,10 @@ module ActiveRecord::Import::AbstractAdapter
53
53
  end
54
54
  end
55
55
 
56
- #custom user post_sql
56
+ # custom user post_sql
57
57
  post_sql_statements << options[:post_sql] if options[:post_sql]
58
58
 
59
- #with rollup
59
+ # with rollup
60
60
  post_sql_statements << rollup_sql if options[:rollup]
61
61
 
62
62
  post_sql_statements
@@ -3,7 +3,7 @@ module ActiveRecord::Import::MysqlAdapter
3
3
  include ActiveRecord::Import::OnDuplicateKeyUpdateSupport
4
4
 
5
5
  NO_MAX_PACKET = 0
6
- QUERY_OVERHEAD = 8 #This was shown to be true for MySQL, but it's not clear where the overhead is from.
6
+ QUERY_OVERHEAD = 8 # This was shown to be true for MySQL, but it's not clear where the overhead is from.
7
7
 
8
8
  # +sql+ can be a single string or an array. If it is an array all
9
9
  # elements that are in position >= 1 will be appended to the final SQL.
@@ -11,19 +11,19 @@ module ActiveRecord::Import::MysqlAdapter
11
11
  # the number of inserts default
12
12
  number_of_inserts = 0
13
13
 
14
- base_sql,post_sql = if sql.is_a?( String )
15
- [ sql, '' ]
14
+ base_sql, post_sql = if sql.is_a?( String )
15
+ [sql, '']
16
16
  elsif sql.is_a?( Array )
17
- [ sql.shift, sql.join( ' ' ) ]
17
+ [sql.shift, sql.join( ' ' )]
18
18
  end
19
19
 
20
20
  sql_size = QUERY_OVERHEAD + base_sql.size + post_sql.size
21
21
 
22
22
  # the number of bytes the requested insert statement values will take up
23
- values_in_bytes = values.sum {|value| value.bytesize }
23
+ values_in_bytes = values.sum(&:bytesize)
24
24
 
25
25
  # the number of bytes (commas) it will take to comma separate our values
26
- comma_separated_bytes = values.size-1
26
+ comma_separated_bytes = values.size - 1
27
27
 
28
28
  # the total number of bytes required if this statement is one statement
29
29
  total_bytes = sql_size + values_in_bytes + comma_separated_bytes
@@ -31,22 +31,22 @@ module ActiveRecord::Import::MysqlAdapter
31
31
  max = max_allowed_packet
32
32
 
33
33
  # if we can insert it all as one statement
34
- if NO_MAX_PACKET == max or total_bytes < max
34
+ if NO_MAX_PACKET == max || total_bytes < max
35
35
  number_of_inserts += 1
36
36
  sql2insert = base_sql + values.join( ',' ) + post_sql
37
37
  insert( sql2insert, *args )
38
38
  else
39
39
  value_sets = ::ActiveRecord::Import::ValueSetsBytesParser.parse(values,
40
- :reserved_bytes => sql_size,
41
- :max_bytes => max)
42
- value_sets.each do |values|
40
+ reserved_bytes: sql_size,
41
+ max_bytes: max)
42
+ value_sets.each do |value_set|
43
43
  number_of_inserts += 1
44
- sql2insert = base_sql + values.join( ',' ) + post_sql
44
+ sql2insert = base_sql + value_set.join( ',' ) + post_sql
45
45
  insert( sql2insert, *args )
46
46
  end
47
47
  end
48
48
 
49
- [number_of_inserts,[]]
49
+ [number_of_inserts, []]
50
50
  end
51
51
 
52
52
  # Returns the maximum number of bytes that the server will allow
@@ -61,7 +61,7 @@ module ActiveRecord::Import::MysqlAdapter
61
61
  end
62
62
 
63
63
  # Add a column to be updated on duplicate key update
64
- def add_column_for_on_duplicate_key_update( column, options={} ) # :nodoc:
64
+ def add_column_for_on_duplicate_key_update( column, options = {} ) # :nodoc:
65
65
  if options.include?(:on_duplicate_key_update)
66
66
  columns = options[:on_duplicate_key_update]
67
67
  case columns
@@ -69,7 +69,7 @@ module ActiveRecord::Import::MysqlAdapter
69
69
  when Hash then columns[column.to_sym] = column.to_sym
70
70
  end
71
71
  else
72
- options[:on_duplicate_key_update] = [ column.to_sym ]
72
+ options[:on_duplicate_key_update] = [column.to_sym]
73
73
  end
74
74
  end
75
75
 
@@ -85,12 +85,12 @@ module ActiveRecord::Import::MysqlAdapter
85
85
  elsif arg.is_a?( String )
86
86
  sql << arg
87
87
  else
88
- raise ArgumentError.new( "Expected Array or Hash" )
88
+ raise ArgumentError, "Expected Array or Hash"
89
89
  end
90
90
  sql
91
91
  end
92
92
 
93
- def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
93
+ def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
94
94
  results = arr.map do |column|
95
95
  qc = quote_column_name( column )
96
96
  "#{table_name}.#{qc}=VALUES(#{qc})"
@@ -108,7 +108,7 @@ module ActiveRecord::Import::MysqlAdapter
108
108
  end
109
109
 
110
110
  # Return true if the statement is a duplicate key record error
111
- def duplicate_key_update_error?(exception)# :nodoc:
111
+ def duplicate_key_update_error?(exception) # :nodoc:
112
112
  exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry')
113
113
  end
114
114
  end