activerecord-import 0.10.0 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +49 -0
  4. data/.rubocop_todo.yml +36 -0
  5. data/.travis.yml +64 -8
  6. data/CHANGELOG.md +475 -0
  7. data/Gemfile +32 -15
  8. data/LICENSE +21 -56
  9. data/README.markdown +564 -35
  10. data/Rakefile +20 -3
  11. data/activerecord-import.gemspec +7 -7
  12. data/benchmarks/README +2 -2
  13. data/benchmarks/benchmark.rb +68 -64
  14. data/benchmarks/lib/base.rb +138 -137
  15. data/benchmarks/lib/cli_parser.rb +107 -103
  16. data/benchmarks/lib/{mysql_benchmark.rb → mysql2_benchmark.rb} +19 -22
  17. data/benchmarks/lib/output_to_csv.rb +5 -4
  18. data/benchmarks/lib/output_to_html.rb +8 -13
  19. data/benchmarks/models/test_innodb.rb +1 -1
  20. data/benchmarks/models/test_memory.rb +1 -1
  21. data/benchmarks/models/test_myisam.rb +1 -1
  22. data/benchmarks/schema/mysql2_schema.rb +16 -0
  23. data/gemfiles/3.2.gemfile +2 -4
  24. data/gemfiles/4.0.gemfile +2 -4
  25. data/gemfiles/4.1.gemfile +2 -4
  26. data/gemfiles/4.2.gemfile +2 -4
  27. data/gemfiles/5.0.gemfile +2 -0
  28. data/gemfiles/5.1.gemfile +2 -0
  29. data/gemfiles/5.2.gemfile +2 -0
  30. data/gemfiles/6.0.gemfile +2 -0
  31. data/gemfiles/6.1.gemfile +1 -0
  32. data/lib/activerecord-import/active_record/adapters/jdbcsqlite3_adapter.rb +6 -0
  33. data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +0 -1
  34. data/lib/activerecord-import/adapters/abstract_adapter.rb +23 -17
  35. data/lib/activerecord-import/adapters/mysql_adapter.rb +52 -25
  36. data/lib/activerecord-import/adapters/postgresql_adapter.rb +187 -10
  37. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +148 -17
  38. data/lib/activerecord-import/base.rb +15 -9
  39. data/lib/activerecord-import/import.rb +740 -191
  40. data/lib/activerecord-import/synchronize.rb +21 -21
  41. data/lib/activerecord-import/value_sets_parser.rb +33 -8
  42. data/lib/activerecord-import/version.rb +1 -1
  43. data/lib/activerecord-import.rb +4 -15
  44. data/test/adapters/jdbcsqlite3.rb +1 -0
  45. data/test/adapters/makara_postgis.rb +1 -0
  46. data/test/adapters/mysql2_makara.rb +1 -0
  47. data/test/adapters/mysql2spatial.rb +1 -1
  48. data/test/adapters/postgis.rb +1 -1
  49. data/test/adapters/postgresql.rb +1 -1
  50. data/test/adapters/postgresql_makara.rb +1 -0
  51. data/test/adapters/spatialite.rb +1 -1
  52. data/test/adapters/sqlite3.rb +1 -1
  53. data/test/database.yml.sample +13 -18
  54. data/test/import_test.rb +608 -89
  55. data/test/jdbcmysql/import_test.rb +2 -3
  56. data/test/jdbcpostgresql/import_test.rb +0 -2
  57. data/test/jdbcsqlite3/import_test.rb +4 -0
  58. data/test/makara_postgis/import_test.rb +8 -0
  59. data/test/models/account.rb +3 -0
  60. data/test/models/alarm.rb +2 -0
  61. data/test/models/animal.rb +6 -0
  62. data/test/models/bike_maker.rb +7 -0
  63. data/test/models/book.rb +7 -6
  64. data/test/models/car.rb +3 -0
  65. data/test/models/chapter.rb +2 -2
  66. data/test/models/dictionary.rb +4 -0
  67. data/test/models/discount.rb +3 -0
  68. data/test/models/end_note.rb +2 -2
  69. data/test/models/promotion.rb +3 -0
  70. data/test/models/question.rb +3 -0
  71. data/test/models/rule.rb +3 -0
  72. data/test/models/tag.rb +4 -0
  73. data/test/models/topic.rb +17 -3
  74. data/test/models/user.rb +3 -0
  75. data/test/models/user_token.rb +4 -0
  76. data/test/models/vendor.rb +7 -0
  77. data/test/models/widget.rb +19 -2
  78. data/test/mysql2/import_test.rb +2 -3
  79. data/test/{em_mysql2 → mysql2_makara}/import_test.rb +1 -1
  80. data/test/mysqlspatial2/import_test.rb +2 -2
  81. data/test/postgis/import_test.rb +5 -1
  82. data/test/schema/generic_schema.rb +159 -85
  83. data/test/schema/jdbcpostgresql_schema.rb +1 -0
  84. data/test/schema/mysql2_schema.rb +19 -0
  85. data/test/schema/postgis_schema.rb +1 -0
  86. data/test/schema/postgresql_schema.rb +61 -0
  87. data/test/schema/sqlite3_schema.rb +13 -0
  88. data/test/sqlite3/import_test.rb +2 -50
  89. data/test/support/active_support/test_case_extensions.rb +21 -13
  90. data/test/support/{mysql/assertions.rb → assertions.rb} +20 -2
  91. data/test/support/factories.rb +39 -14
  92. data/test/support/generate.rb +10 -10
  93. data/test/support/mysql/import_examples.rb +49 -98
  94. data/test/support/postgresql/import_examples.rb +535 -57
  95. data/test/support/shared_examples/on_duplicate_key_ignore.rb +43 -0
  96. data/test/support/shared_examples/on_duplicate_key_update.rb +378 -0
  97. data/test/support/shared_examples/recursive_import.rb +225 -0
  98. data/test/support/sqlite3/import_examples.rb +231 -0
  99. data/test/synchronize_test.rb +10 -2
  100. data/test/test_helper.rb +36 -8
  101. data/test/travis/database.yml +26 -17
  102. data/test/value_sets_bytes_parser_test.rb +25 -17
  103. data/test/value_sets_records_parser_test.rb +6 -6
  104. metadata +86 -42
  105. data/benchmarks/boot.rb +0 -18
  106. data/benchmarks/schema/mysql_schema.rb +0 -16
  107. data/gemfiles/3.1.gemfile +0 -4
  108. data/lib/activerecord-import/active_record/adapters/em_mysql2_adapter.rb +0 -8
  109. data/lib/activerecord-import/active_record/adapters/mysql_adapter.rb +0 -6
  110. data/lib/activerecord-import/em_mysql2.rb +0 -7
  111. data/lib/activerecord-import/mysql.rb +0 -7
  112. data/test/adapters/em_mysql2.rb +0 -1
  113. data/test/adapters/mysql.rb +0 -1
  114. data/test/adapters/mysqlspatial.rb +0 -1
  115. data/test/mysql/import_test.rb +0 -6
  116. data/test/mysqlspatial/import_test.rb +0 -6
  117. data/test/schema/mysql_schema.rb +0 -18
  118. data/test/travis/build.sh +0 -30
@@ -1,103 +1,107 @@
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
- :table_types => {},
42
- :delete_on_finish => true,
43
- :number_of_objects => [],
44
- :outputs => [] )
45
-
46
- opts = OptionParser.new do |opts|
47
- opts.banner = BANNER
48
-
49
- # parse the database adapter
50
- opts.on( "a", "--adapter [String]",
51
- "The database adapter to use. IE: mysql, postgresql, oracle" ) do |arg|
52
- options.adapter = arg
53
- end
54
-
55
- # parse do_not_delete flag
56
- opts.on( "d", "--do-not-delete",
57
- "By default all records in the benchmark tables will be deleted at the end of the benchmark. " +
58
- "This flag indicates not to delete the benchmark data." ) do |arg|
59
- options.delete_on_finish = false
60
- end
61
-
62
- # parse the number of row objects to test
63
- opts.on( "n", "--num [Integer]",
64
- "The number of objects to benchmark." ) do |arg|
65
- options.number_of_objects << arg.to_i
66
- end
67
-
68
- # parse the table types to test
69
- opts.on( "t", "--table-type [String]",
70
- "The table type to test. This can be used multiple times." ) do |arg|
71
- if arg =~ /^all$/
72
- options.table_types['all'] = options.benchmark_all_types = true
73
- else
74
- options.table_types[arg] = true
75
- end
76
- end
77
-
78
- # print results in CSV format
79
- opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
80
- options.outputs << OpenStruct.new( :format=>'csv', :filename=>filename)
81
- end
82
-
83
- # print results in HTML format
84
- opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
85
- options.outputs << OpenStruct.new( :format=>'html', :filename=>filename )
86
- end
87
- end #end opt.parse!
88
-
89
- begin
90
- opts.parse!( args )
91
- if options.table_types.size == 0
92
- options.table_types['all'] = options.benchmark_all_types = true
93
- end
94
- rescue Exception => ex
95
- print_banner!
96
- end
97
-
98
- print_options( options )
99
-
100
- options
101
- end
102
-
103
- 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
+
48
+ opt_parser = OptionParser.new do |opts|
49
+ opts.banner = BANNER
50
+
51
+ # parse the database adapter
52
+ opts.on( "a", "--adapter [String]",
53
+ "The database adapter to use. IE: mysql, postgresql, oracle" ) do |arg|
54
+ options.adapter = arg
55
+ end
56
+
57
+ # parse do_not_delete flag
58
+ opts.on( "d", "--do-not-delete",
59
+ "By default all records in the benchmark tables will be deleted at the end of the benchmark. " \
60
+ "This flag indicates not to delete the benchmark data." ) do |_|
61
+ options.delete_on_finish = false
62
+ end
63
+
64
+ # parse the number of row objects to test
65
+ opts.on( "n", "--num [Integer]",
66
+ "The number of objects to benchmark." ) do |arg|
67
+ options.number_of_objects << arg.to_i
68
+ end
69
+
70
+ # parse the table types to test
71
+ opts.on( "t", "--table-type [String]",
72
+ "The table type to test. This can be used multiple times." ) do |arg|
73
+ if arg =~ /^all$/
74
+ options.table_types['all'] = options.benchmark_all_types = true
75
+ else
76
+ options.table_types[arg] = true
77
+ end
78
+ end
79
+
80
+ # print results in CSV format
81
+ opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
82
+ options.outputs << OpenStruct.new( format: 'csv', filename: filename)
83
+ end
84
+
85
+ # print results in HTML format
86
+ opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
87
+ options.outputs << OpenStruct.new( format: 'html', filename: filename )
88
+ end
89
+ end # end opt.parse!
90
+
91
+ begin
92
+ opt_parser.parse!( args )
93
+ if options.table_types.empty?
94
+ options.table_types['all'] = options.benchmark_all_types = true
95
+ end
96
+ rescue Exception
97
+ print_banner!
98
+ end
99
+
100
+ options.number_of_objects = [1000] if options.number_of_objects.empty?
101
+ options.outputs = [OpenStruct.new( format: 'html', filename: 'benchmark.html')] if options.outputs.empty?
102
+
103
+ print_options( options )
104
+
105
+ options
106
+ end
107
+ end
@@ -1,22 +1,19 @@
1
- class MysqlBenchmark < 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
22
-
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
@@ -1,12 +1,13 @@
1
- require 'fastercsv'
1
+ require 'csv'
2
2
 
3
3
  module OutputToCSV
4
4
  def self.output_results( filename, results )
5
- FasterCSV.open( filename, 'w' ) do |csv|
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 = [], []
9
- result_set.each do |result|
8
+ columns = []
9
+ times = []
10
+ result_set.each do |result|
10
11
  columns << result.description
11
12
  times << result.tms.real
12
13
  end
@@ -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,3 +1,3 @@
1
1
  class TestInnoDb < ActiveRecord::Base
2
- set_table_name 'test_innodb'
2
+ self.table_name = 'test_innodb'
3
3
  end
@@ -1,3 +1,3 @@
1
1
  class TestMemory < ActiveRecord::Base
2
- set_table_name 'test_memory'
2
+ self.table_name = 'test_memory'
3
3
  end
@@ -1,3 +1,3 @@
1
1
  class TestMyISAM < ActiveRecord::Base
2
- set_table_name 'test_myisam'
2
+ self.table_name = 'test_myisam'
3
3
  end
@@ -0,0 +1,16 @@
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
4
+ t.column :description, :string
5
+ end
6
+
7
+ create_table :test_innodb, options: 'ENGINE=InnoDb', force: true do |t|
8
+ t.column :my_name, :string, null: false
9
+ t.column :description, :string
10
+ end
11
+
12
+ create_table :test_memory, options: 'ENGINE=Memory', force: true do |t|
13
+ t.column :my_name, :string, null: false
14
+ t.column :description, :string
15
+ end
16
+ end
data/gemfiles/3.2.gemfile CHANGED
@@ -1,4 +1,2 @@
1
- platforms :ruby do
2
- gem 'mysql', '>= 2.8.1'
3
- gem 'activerecord', '~> 3.2.0'
4
- end
1
+ gem 'activerecord', '~> 3.2.0'
2
+ gem 'composite_primary_keys', '~> 5.0'
data/gemfiles/4.0.gemfile CHANGED
@@ -1,4 +1,2 @@
1
- platforms :ruby do
2
- gem 'mysql', '~> 2.9'
3
- gem 'activerecord', '~> 4.0.0.rc2'
4
- end
1
+ gem 'activerecord', '~> 4.0.0'
2
+ gem 'composite_primary_keys', '~> 6.0'
data/gemfiles/4.1.gemfile CHANGED
@@ -1,4 +1,2 @@
1
- platforms :ruby do
2
- gem 'mysql', '~> 2.9'
3
- gem 'activerecord', '~> 4.1'
4
- end
1
+ gem 'activerecord', '~> 4.1.0'
2
+ gem 'composite_primary_keys', '~> 7.0'
data/gemfiles/4.2.gemfile CHANGED
@@ -1,4 +1,2 @@
1
- platforms :ruby do
2
- gem 'mysql', '~> 2.9'
3
- gem 'activerecord', '~> 4.2'
4
- end
1
+ gem 'activerecord', '~> 4.2.0'
2
+ gem 'composite_primary_keys', '~> 8.0'
@@ -0,0 +1,2 @@
1
+ gem 'activerecord', '~> 5.0.0'
2
+ gem 'composite_primary_keys', '~> 9.0'
@@ -0,0 +1,2 @@
1
+ gem 'activerecord', '~> 5.1.0'
2
+ gem 'composite_primary_keys', '~> 10.0'
@@ -0,0 +1,2 @@
1
+ gem 'activerecord', '~> 5.2.0'
2
+ gem 'composite_primary_keys', '~> 11.0'
@@ -0,0 +1,2 @@
1
+ gem 'activerecord', '~> 6.0.0'
2
+ gem 'composite_primary_keys', '~> 12.0'
@@ -0,0 +1 @@
1
+ gem 'activerecord', '~> 6.1.0'
@@ -0,0 +1,6 @@
1
+ require "active_record/connection_adapters/sqlite3_adapter"
2
+ require "activerecord-import/adapters/sqlite3_adapter"
3
+
4
+ class ActiveRecord::ConnectionAdapters::SQLite3Adapter
5
+ include ActiveRecord::Import::SQLite3Adapter
6
+ end
@@ -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,31 +1,30 @@
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
- def insert_many( sql, values, *args ) # :nodoc:
7
+ def insert_many( sql, values, _options = {}, *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
+ ActiveRecord::Import::Result.new([], number_of_inserts, [], [])
20
20
  end
21
21
 
22
22
  def pre_sql_statements(options)
23
23
  sql = []
24
24
  sql << options[:pre_sql] if options[:pre_sql]
25
25
  sql << options[:command] if options[:command]
26
- sql << "IGNORE" if options[:ignore]
27
26
 
28
- #add keywords like IGNORE or DELAYED
27
+ # add keywords like IGNORE or DELAYED
29
28
  if options[:keywords].is_a?(Array)
30
29
  sql.concat(options[:keywords])
31
30
  elsif options[:keywords]
@@ -38,29 +37,36 @@ module ActiveRecord::Import::AbstractAdapter
38
37
  # Synchronizes the passed in ActiveRecord instances with the records in
39
38
  # the database by calling +reload+ on each instance.
40
39
  def after_import_synchronize( instances )
41
- instances.each { |e| e.reload }
40
+ instances.each(&:reload)
42
41
  end
43
42
 
44
43
  # Returns an array of post SQL statements given the passed in options.
45
44
  def post_sql_statements( table_name, options ) # :nodoc:
46
45
  post_sql_statements = []
47
- if options[:on_duplicate_key_update]
48
- post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update] )
46
+
47
+ if supports_on_duplicate_key_update? && options[:on_duplicate_key_update]
48
+ post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update], options[:primary_key], options[:locking_column] )
49
+ elsif logger && options[:on_duplicate_key_update]
50
+ logger.warn "Ignoring on_duplicate_key_update because it is not supported by the database."
49
51
  end
50
52
 
51
- #custom user post_sql
53
+ # custom user post_sql
52
54
  post_sql_statements << options[:post_sql] if options[:post_sql]
53
55
 
54
- #with rollup
56
+ # with rollup
55
57
  post_sql_statements << rollup_sql if options[:rollup]
56
58
 
57
59
  post_sql_statements
58
60
  end
59
61
 
60
- # Returns the maximum number of bytes that the server will allow
61
- # in a single packet
62
- def max_allowed_packet
63
- NO_MAX_PACKET
62
+ def increment_locking_column!(table_name, results, locking_column)
63
+ if locking_column.present?
64
+ results << "\"#{locking_column}\"=#{table_name}.\"#{locking_column}\"+1"
65
+ end
66
+ end
67
+
68
+ def supports_on_duplicate_key_update?
69
+ false
64
70
  end
65
71
  end
66
72
  end