activerecord-import 0.10.0 → 1.0.8

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 (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
@@ -0,0 +1,231 @@
1
+ # encoding: UTF-8
2
+ def should_support_sqlite3_import_functionality
3
+ if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
4
+ should_support_sqlite_upsert_functionality
5
+ end
6
+
7
+ describe "#supports_imports?" do
8
+ it "should support import" do
9
+ assert ActiveRecord::Base.supports_import?
10
+ end
11
+ end
12
+
13
+ describe "#import" do
14
+ it "imports with a single insert on SQLite 3.7.11 or higher" do
15
+ assert_difference "Topic.count", +507 do
16
+ result = Topic.import Build(7, :topics)
17
+ assert_equal 1, result.num_inserts, "Failed to issue a single INSERT statement. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
18
+ assert_equal 7, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
19
+
20
+ result = Topic.import Build(500, :topics)
21
+ assert_equal 1, result.num_inserts, "Failed to issue a single INSERT statement. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
22
+ assert_equal 507, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
23
+ end
24
+ end
25
+
26
+ it "imports with a two inserts on SQLite 3.7.11 or higher" do
27
+ assert_difference "Topic.count", +501 do
28
+ result = Topic.import Build(501, :topics)
29
+ assert_equal 2, result.num_inserts, "Failed to issue a two INSERT statements. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
30
+ assert_equal 501, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
31
+ end
32
+ end
33
+
34
+ it "imports with a five inserts on SQLite 3.7.11 or higher" do
35
+ assert_difference "Topic.count", +2500 do
36
+ result = Topic.import Build(2500, :topics)
37
+ assert_equal 5, result.num_inserts, "Failed to issue a two INSERT statements. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
38
+ assert_equal 2500, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def should_support_sqlite_upsert_functionality
45
+ should_support_basic_on_duplicate_key_update
46
+ should_support_on_duplicate_key_ignore
47
+
48
+ describe "#import" do
49
+ extend ActiveSupport::TestCase::ImportAssertions
50
+
51
+ macro(:perform_import) { raise "supply your own #perform_import in a context below" }
52
+ macro(:updated_topic) { Topic.find(@topic.id) }
53
+
54
+ context "with :on_duplicate_key_ignore and validation checks turned off" do
55
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
56
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
57
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
58
+
59
+ setup do
60
+ Topic.import columns, values, validate: false
61
+ end
62
+
63
+ it "should not update any records" do
64
+ result = Topic.import columns, updated_values, on_duplicate_key_ignore: true, validate: false
65
+ assert_equal [], result.ids
66
+ end
67
+ end
68
+
69
+ context "with :on_duplicate_key_update and validation checks turned off" do
70
+ asssertion_group(:should_support_on_duplicate_key_update) do
71
+ should_not_update_fields_not_mentioned
72
+ should_update_foreign_keys
73
+ should_not_update_created_at_on_timestamp_columns
74
+ should_update_updated_at_on_timestamp_columns
75
+ end
76
+
77
+ context "using a hash" do
78
+ context "with :columns a hash" do
79
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
80
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
81
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
82
+
83
+ macro(:perform_import) do |*opts|
84
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { conflict_target: :id, columns: update_columns }, validate: false)
85
+ end
86
+
87
+ setup do
88
+ Topic.import columns, values, validate: false
89
+ @topic = Topic.find 99
90
+ end
91
+
92
+ it "should not modify the passed in :on_duplicate_key_update columns array" do
93
+ assert_nothing_raised do
94
+ columns = %w(title author_name).freeze
95
+ Topic.import columns, [%w(foo, bar)], on_duplicate_key_update: { columns: columns }
96
+ end
97
+ end
98
+
99
+ context "using string hash map" do
100
+ let(:update_columns) { { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
101
+ should_support_on_duplicate_key_update
102
+ should_update_fields_mentioned
103
+ end
104
+
105
+ context "using string hash map, but specifying column mismatches" do
106
+ let(:update_columns) { { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
107
+ should_support_on_duplicate_key_update
108
+ should_update_fields_mentioned_with_hash_mappings
109
+ end
110
+
111
+ context "using symbol hash map" do
112
+ let(:update_columns) { { title: :title, author_email_address: :author_email_address, parent_id: :parent_id } }
113
+ should_support_on_duplicate_key_update
114
+ should_update_fields_mentioned
115
+ end
116
+
117
+ context "using symbol hash map, but specifying column mismatches" do
118
+ let(:update_columns) { { title: :author_email_address, author_email_address: :title, parent_id: :parent_id } }
119
+ should_support_on_duplicate_key_update
120
+ should_update_fields_mentioned_with_hash_mappings
121
+ end
122
+ end
123
+
124
+ context 'with :index_predicate' do
125
+ let(:columns) { %w( id device_id alarm_type status metadata ) }
126
+ let(:values) { [[99, 17, 1, 1, 'foo']] }
127
+ let(:updated_values) { [[99, 17, 1, 2, 'bar']] }
128
+
129
+ macro(:perform_import) do |*opts|
130
+ Alarm.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { conflict_target: [:device_id, :alarm_type], index_predicate: 'status <> 0', columns: [:status] }, validate: false)
131
+ end
132
+
133
+ macro(:updated_alarm) { Alarm.find(@alarm.id) }
134
+
135
+ setup do
136
+ Alarm.import columns, values, validate: false
137
+ @alarm = Alarm.find 99
138
+ end
139
+
140
+ context 'supports on duplicate key update for partial indexes' do
141
+ it 'should not update created_at timestamp columns' do
142
+ Timecop.freeze Chronic.parse("5 minutes from now") do
143
+ perform_import
144
+ assert_in_delta @alarm.created_at.to_i, updated_alarm.created_at.to_i, 1
145
+ end
146
+ end
147
+
148
+ it 'should update updated_at timestamp columns' do
149
+ time = Chronic.parse("5 minutes from now")
150
+ Timecop.freeze time do
151
+ perform_import
152
+ assert_in_delta time.to_i, updated_alarm.updated_at.to_i, 1
153
+ end
154
+ end
155
+
156
+ it 'should not update fields not mentioned' do
157
+ perform_import
158
+ assert_equal 'foo', updated_alarm.metadata
159
+ end
160
+
161
+ it 'should update fields mentioned with hash mappings' do
162
+ perform_import
163
+ assert_equal 2, updated_alarm.status
164
+ end
165
+ end
166
+ end
167
+
168
+ context 'with :condition' do
169
+ let(:columns) { %w( id device_id alarm_type status metadata) }
170
+ let(:values) { [[99, 17, 1, 1, 'foo']] }
171
+ let(:updated_values) { [[99, 17, 1, 1, 'bar']] }
172
+
173
+ macro(:perform_import) do |*opts|
174
+ Alarm.import(
175
+ columns,
176
+ updated_values,
177
+ opts.extract_options!.merge(
178
+ on_duplicate_key_update: {
179
+ conflict_target: [:id],
180
+ condition: "alarms.metadata NOT LIKE '%foo%'",
181
+ columns: [:metadata]
182
+ },
183
+ validate: false
184
+ )
185
+ )
186
+ end
187
+
188
+ macro(:updated_alarm) { Alarm.find(@alarm.id) }
189
+
190
+ setup do
191
+ Alarm.import columns, values, validate: false
192
+ @alarm = Alarm.find 99
193
+ end
194
+
195
+ it 'should not update fields not matched' do
196
+ perform_import
197
+ assert_equal 'foo', updated_alarm.metadata
198
+ end
199
+ end
200
+
201
+ context "with no :conflict_target" do
202
+ context "with no primary key" do
203
+ it "raises ArgumentError" do
204
+ error = assert_raises ArgumentError do
205
+ Rule.import Build(3, :rules), on_duplicate_key_update: [:condition_text], validate: false
206
+ end
207
+ assert_match(/Expected :conflict_target to be specified/, error.message)
208
+ end
209
+ end
210
+ end
211
+
212
+ context "with no :columns" do
213
+ let(:columns) { %w( id title author_name author_email_address ) }
214
+ let(:values) { [[100, "Book", "John Doe", "john@doe.com"]] }
215
+ let(:updated_values) { [[100, "Title Should Not Change", "Author Should Not Change", "john@nogo.com"]] }
216
+
217
+ macro(:perform_import) do |*opts|
218
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { conflict_target: :id }, validate: false)
219
+ end
220
+
221
+ setup do
222
+ Topic.import columns, values, validate: false
223
+ @topic = Topic.find 100
224
+ end
225
+
226
+ should_update_updated_at_on_timestamp_columns
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
@@ -1,8 +1,8 @@
1
1
  require File.expand_path('../test_helper', __FILE__)
2
2
 
3
3
  describe ".synchronize" do
4
- let(:topics){ Generate(3, :topics) }
5
- let(:titles){ %w(one two three) }
4
+ let(:topics) { Generate(3, :topics) }
5
+ let(:titles) { %w(one two three) }
6
6
 
7
7
  setup do
8
8
  # update records outside of ActiveRecord knowing about it
@@ -30,4 +30,12 @@ describe ".synchronize" do
30
30
  assert_equal false, topics[1].changed?, "the second record was dirty"
31
31
  assert_equal false, topics[2].changed?, "the third record was dirty"
32
32
  end
33
+
34
+ it "ignores default scope" do
35
+ # update records outside of ActiveRecord knowing about it
36
+ Topic.connection.execute( "UPDATE #{Topic.table_name} SET approved='0' WHERE id=#{topics[0].id}", "Updating record 1 without ActiveRecord" )
37
+
38
+ Topic.synchronize topics
39
+ assert_equal false, topics[0].approved
40
+ end
33
41
  end
data/test/test_helper.rb CHANGED
@@ -10,19 +10,37 @@ ENV["RAILS_ENV"] = "test"
10
10
  require "bundler"
11
11
  Bundler.setup
12
12
 
13
+ require 'pry' unless RbConfig::CONFIG["RUBY_INSTALL_NAME"] =~ /jruby/
14
+
13
15
  require "active_record"
14
16
  require "active_record/fixtures"
15
17
  require "active_support/test_case"
16
18
 
17
- if ActiveSupport::VERSION::STRING < "4.1"
19
+ if ActiveSupport::VERSION::STRING < "4.0"
18
20
  require 'test/unit'
21
+ require 'mocha/test_unit'
19
22
  else
20
23
  require 'active_support/testing/autorun'
24
+ require "mocha/mini_test"
21
25
  end
22
26
 
23
27
  require 'timecop'
24
28
  require 'chronic'
25
29
 
30
+ begin
31
+ require 'composite_primary_keys'
32
+ rescue LoadError
33
+ ENV["SKIP_COMPOSITE_PK"] = "true"
34
+ end
35
+
36
+ # Support MySQL 5.7
37
+ if ActiveSupport::VERSION::STRING < "4.1"
38
+ require "active_record/connection_adapters/mysql2_adapter"
39
+ class ActiveRecord::ConnectionAdapters::Mysql2Adapter
40
+ NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
41
+ end
42
+ end
43
+
26
44
  require "ruby-debug" if RUBY_VERSION.to_f < 1.9
27
45
 
28
46
  adapter = ENV["ARE_DB"] || "sqlite3"
@@ -30,26 +48,36 @@ adapter = ENV["ARE_DB"] || "sqlite3"
30
48
  FileUtils.mkdir_p 'log'
31
49
  ActiveRecord::Base.logger = Logger.new("log/test.log")
32
50
  ActiveRecord::Base.logger.level = Logger::DEBUG
33
- ActiveRecord::Base.configurations["test"] = YAML.load_file(test_dir.join("database.yml"))[adapter]
51
+
52
+ if ENV['AR_VERSION'].to_f >= 6.0
53
+ yaml_config = YAML.load_file(test_dir.join("database.yml"))[adapter]
54
+ config = ActiveRecord::DatabaseConfigurations::HashConfig.new("test", adapter, yaml_config)
55
+ ActiveRecord::Base.configurations.configurations << config
56
+ else
57
+ ActiveRecord::Base.configurations["test"] = YAML.load_file(test_dir.join("database.yml"))[adapter]
58
+ end
59
+
34
60
  ActiveRecord::Base.default_timezone = :utc
35
61
 
36
62
  require "activerecord-import"
37
- ActiveRecord::Base.establish_connection "test"
63
+ ActiveRecord::Base.establish_connection :test
38
64
 
39
- ActiveSupport::Notifications.subscribe(/active_record.sql/) do |event, _, _, _, hsh|
65
+ ActiveSupport::Notifications.subscribe(/active_record.sql/) do |_, _, _, _, hsh|
40
66
  ActiveRecord::Base.logger.info hsh[:sql]
41
67
  end
42
68
 
43
- require "factory_girl"
44
- Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each{ |file| require file }
69
+ require "factory_bot"
70
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |file| require file }
45
71
 
46
72
  # Load base/generic schema
47
73
  require test_dir.join("schema/version")
48
74
  require test_dir.join("schema/generic_schema")
49
75
  adapter_schema = test_dir.join("schema/#{adapter}_schema.rb")
50
- require adapter_schema if File.exists?(adapter_schema)
76
+ require adapter_schema if File.exist?(adapter_schema)
51
77
 
52
- Dir[File.dirname(__FILE__) + "/models/*.rb"].each{ |file| require file }
78
+ Dir[File.dirname(__FILE__) + "/models/*.rb"].each { |file| require file }
53
79
 
54
80
  # Prevent this deprecation warning from breaking the tests.
55
81
  Rake::FileList.send(:remove_method, :import)
82
+
83
+ ActiveSupport::TestCase.test_order = :random if ENV['AR_VERSION'].to_f >= 4.2
@@ -5,31 +5,34 @@ common: &common
5
5
  host: localhost
6
6
  database: activerecord_import_test
7
7
 
8
- mysql: &mysql
8
+ jdbcpostgresql: &postgresql
9
9
  <<: *common
10
- adapter: mysql
10
+ username: postgres
11
+ adapter: jdbcpostgresql
12
+ min_messages: warning
13
+
14
+ jdbcmysql: &mysql2
15
+ <<: *common
16
+ adapter: jdbcmysql
17
+
18
+ jdbcsqlite3: &sqlite3
19
+ <<: *common
20
+ adapter: jdbcsqlite3
11
21
 
12
22
  mysql2: &mysql2
13
23
  <<: *common
14
24
  adapter: mysql2
15
25
 
16
- mysqlspatial:
17
- <<: *mysql
18
-
19
26
  mysql2spatial:
20
27
  <<: *mysql2
21
28
 
22
- em_mysql2:
23
- <<: *common
24
- adapter: em_mysql2
25
- pool: 5
29
+ mysql2_makara:
30
+ <<: *mysql2
26
31
 
27
- seamless_database_pool:
32
+ oracle:
28
33
  <<: *common
29
- adapter: seamless_database_pool
30
- pool_adapter: mysql2
31
- master:
32
- host: localhost
34
+ adapter: oracle
35
+ min_messages: debug
33
36
 
34
37
  postgresql: &postgresql
35
38
  <<: *common
@@ -37,13 +40,19 @@ postgresql: &postgresql
37
40
  adapter: postgresql
38
41
  min_messages: warning
39
42
 
43
+ postresql_makara:
44
+ <<: *postgresql
45
+
40
46
  postgis:
41
47
  <<: *postgresql
42
48
 
43
- oracle:
49
+ seamless_database_pool:
44
50
  <<: *common
45
- adapter: oracle
46
- min_messages: debug
51
+ adapter: seamless_database_pool
52
+ pool_adapter: mysql2
53
+ prepared_statements: false
54
+ master:
55
+ host: localhost
47
56
 
48
57
  sqlite:
49
58
  adapter: sqlite
@@ -4,48 +4,57 @@ require 'activerecord-import/value_sets_parser'
4
4
 
5
5
  describe ActiveRecord::Import::ValueSetsBytesParser do
6
6
  context "#parse - computing insert value sets" do
7
- let(:parser){ ActiveRecord::Import::ValueSetsBytesParser }
8
- let(:base_sql){ "INSERT INTO atable (a,b,c)" }
9
- let(:values){ [ "(1,2,3)", "(2,3,4)", "(3,4,5)" ] }
7
+ let(:parser) { ActiveRecord::Import::ValueSetsBytesParser }
8
+ let(:base_sql) { "INSERT INTO atable (a,b,c)" }
9
+ let(:values) { ["(1,2,3)", "(2,3,4)", "(3,4,5)"] }
10
+
11
+ context "when the max allowed bytes is 30 and the base SQL is 26 bytes" do
12
+ it "should raise ActiveRecord::Import::ValueSetTooLargeError" do
13
+ error = assert_raises ActiveRecord::Import::ValueSetTooLargeError do
14
+ parser.parse values, reserved_bytes: base_sql.size, max_bytes: 30
15
+ end
16
+ assert_match(/33 bytes exceeds the max allowed for an insert \[30\]/, error.message)
17
+ end
18
+ end
10
19
 
11
20
  context "when the max allowed bytes is 33 and the base SQL is 26 bytes" do
12
21
  it "should return 3 value sets when given 3 value sets of 7 bytes a piece" do
13
- value_sets = parser.parse values, :reserved_bytes => base_sql.size, :max_bytes => 33
22
+ value_sets = parser.parse values, reserved_bytes: base_sql.size, max_bytes: 33
14
23
  assert_equal 3, value_sets.size
15
24
  end
16
25
  end
17
26
 
18
27
  context "when the max allowed bytes is 40 and the base SQL is 26 bytes" do
19
28
  it "should return 3 value sets when given 3 value sets of 7 bytes a piece" do
20
- value_sets = parser.parse values, :reserved_bytes => base_sql.size, :max_bytes => 40
29
+ value_sets = parser.parse values, reserved_bytes: base_sql.size, max_bytes: 40
21
30
  assert_equal 3, value_sets.size
22
31
  end
23
32
  end
24
33
 
25
34
  context "when the max allowed bytes is 41 and the base SQL is 26 bytes" do
26
35
  it "should return 2 value sets when given 2 value sets of 7 bytes a piece" do
27
- value_sets = parser.parse values, :reserved_bytes => base_sql.size, :max_bytes => 41
36
+ value_sets = parser.parse values, reserved_bytes: base_sql.size, max_bytes: 41
28
37
  assert_equal 2, value_sets.size
29
38
  end
30
39
  end
31
40
 
32
41
  context "when the max allowed bytes is 48 and the base SQL is 26 bytes" do
33
42
  it "should return 2 value sets when given 2 value sets of 7 bytes a piece" do
34
- value_sets = parser.parse values, :reserved_bytes => base_sql.size, :max_bytes => 48
43
+ value_sets = parser.parse values, reserved_bytes: base_sql.size, max_bytes: 48
35
44
  assert_equal 2, value_sets.size
36
45
  end
37
46
  end
38
47
 
39
48
  context "when the max allowed bytes is 49 and the base SQL is 26 bytes" do
40
49
  it "should return 1 value sets when given 1 value sets of 7 bytes a piece" do
41
- value_sets = parser.parse values, :reserved_bytes => base_sql.size, :max_bytes => 49
50
+ value_sets = parser.parse values, reserved_bytes: base_sql.size, max_bytes: 49
42
51
  assert_equal 1, value_sets.size
43
52
  end
44
53
  end
45
54
 
46
55
  context "when the max allowed bytes is 999999 and the base SQL is 26 bytes" do
47
56
  it "should return 1 value sets when given 1 value sets of 7 bytes a piece" do
48
- value_sets = parser.parse values, :reserved_bytes => base_sql.size, :max_bytes => 999999
57
+ value_sets = parser.parse values, reserved_bytes: base_sql.size, max_bytes: 999_999
49
58
  assert_equal 1, value_sets.size
50
59
  end
51
60
  end
@@ -54,9 +63,9 @@ describe ActiveRecord::Import::ValueSetsBytesParser do
54
63
  values = [
55
64
  "('1','2','3')",
56
65
  "('4','5','6')",
57
- "('7','8','9')" ]
66
+ "('7','8','9')"
67
+ ]
58
68
 
59
- values_size_in_bytes = values.sum {|value| value.bytesize }
60
69
  base_sql_size_in_bytes = 15
61
70
  max_bytes = 30
62
71
 
@@ -64,8 +73,9 @@ describe ActiveRecord::Import::ValueSetsBytesParser do
64
73
  assert_equal 3, value_sets.size, 'Three value sets were expected!'
65
74
 
66
75
  # Each element in the value_sets array must be an array
67
- value_sets.each_with_index { |e,i|
68
- assert_kind_of Array, e, "Element #{i} was expected to be an Array!" }
76
+ value_sets.each_with_index do |e, i|
77
+ assert_kind_of Array, e, "Element #{i} was expected to be an Array!"
78
+ end
69
79
 
70
80
  # Each element in the values array should have a 1:1 correlation to the elements
71
81
  # in the returned value_sets arrays
@@ -79,18 +89,16 @@ describe ActiveRecord::Import::ValueSetsBytesParser do
79
89
  # each accented e should be 2 bytes, so each entry is 6 bytes instead of 5
80
90
  values = [
81
91
  "('é')",
82
- "('é')" ]
92
+ "('é')"
93
+ ]
83
94
 
84
95
  base_sql_size_in_bytes = 15
85
96
  max_bytes = 26
86
97
 
87
- values_size_in_bytes = values.sum {|value| value.bytesize }
88
98
  value_sets = parser.parse values, reserved_bytes: base_sql_size_in_bytes, max_bytes: max_bytes
89
99
 
90
100
  assert_equal 2, value_sets.size, 'Two value sets were expected!'
91
101
  end
92
102
  end
93
103
  end
94
-
95
104
  end
96
-
@@ -4,27 +4,27 @@ require 'activerecord-import/value_sets_parser'
4
4
 
5
5
  describe "ActiveRecord::Import::ValueSetsRecordsParser" do
6
6
  context "#parse - computing insert value sets" do
7
- let(:parser){ ActiveRecord::Import::ValueSetsRecordsParser }
8
- let(:base_sql){ "INSERT INTO atable (a,b,c)" }
9
- let(:values){ [ "(1,2,3)", "(2,3,4)", "(3,4,5)" ] }
7
+ let(:parser) { ActiveRecord::Import::ValueSetsRecordsParser }
8
+ let(:base_sql) { "INSERT INTO atable (a,b,c)" }
9
+ let(:values) { ["(1,2,3)", "(2,3,4)", "(3,4,5)"] }
10
10
 
11
11
  context "when the max number of records is 1" do
12
12
  it "should return 3 value sets when given 3 values sets" do
13
- value_sets = parser.parse values, :max_records => 1
13
+ value_sets = parser.parse values, max_records: 1
14
14
  assert_equal 3, value_sets.size
15
15
  end
16
16
  end
17
17
 
18
18
  context "when the max number of records is 2" do
19
19
  it "should return 2 value sets when given 3 values sets" do
20
- value_sets = parser.parse values, :max_records => 2
20
+ value_sets = parser.parse values, max_records: 2
21
21
  assert_equal 2, value_sets.size
22
22
  end
23
23
  end
24
24
 
25
25
  context "when the max number of records is 3" do
26
26
  it "should return 1 value sets when given 3 values sets" do
27
- value_sets = parser.parse values, :max_records => 3
27
+ value_sets = parser.parse values, max_records: 3
28
28
  assert_equal 1, value_sets.size
29
29
  end
30
30
  end