mass_insert 0.1.3 → 0.2.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.
- checksums.yaml +5 -13
- data/.gitignore +2 -0
- data/.travis.yml +12 -10
- data/Gemfile +9 -8
- data/LICENSE.txt +1 -1
- data/README.md +34 -78
- data/Rakefile +19 -24
- data/lib/mass_insert/adapters/abstract_adapter.rb +54 -0
- data/lib/mass_insert/adapters/mysql2_adapter.rb +5 -0
- data/lib/mass_insert/adapters/postgresql_adapter.rb +5 -0
- data/lib/mass_insert/adapters/sqlite3_adapter.rb +5 -0
- data/lib/mass_insert/base.rb +3 -84
- data/lib/mass_insert/builder.rb +8 -0
- data/lib/mass_insert/executer.rb +2 -6
- data/lib/mass_insert/process.rb +14 -14
- data/lib/mass_insert/utilities.rb +25 -0
- data/lib/mass_insert/version.rb +1 -1
- data/lib/mass_insert.rb +9 -5
- data/mass_insert.gemspec +10 -10
- data/test/adapters/mysql2/example_test.rb +3 -0
- data/test/adapters/postgresql/example_test.rb +3 -0
- data/test/adapters/sqlite3/example_test.rb +3 -0
- data/test/database.yml.example +18 -0
- data/test/models/user.rb +2 -0
- data/test/schema.rb +11 -0
- data/test/support/adapters/mysql2.rb +1 -0
- data/test/support/adapters/postgresql.rb +1 -0
- data/test/support/adapters/sqlite3.rb +1 -0
- data/test/support/shared_examples.rb +57 -0
- data/test/test_helper.rb +20 -0
- metadata +42 -188
- data/.rvmrc +0 -62
- data/lib/mass_insert/builder/adapters/adapter.rb +0 -52
- data/lib/mass_insert/builder/adapters/helpers/abstract_query.rb +0 -52
- data/lib/mass_insert/builder/adapters/helpers/column_value.rb +0 -90
- data/lib/mass_insert/builder/adapters/mysql2_adapter.rb +0 -7
- data/lib/mass_insert/builder/adapters/postgresql_adapter.rb +0 -7
- data/lib/mass_insert/builder/adapters/sqlite3_adapter.rb +0 -27
- data/lib/mass_insert/builder/adapters/sqlserver_adapter.rb +0 -20
- data/lib/mass_insert/builder/adapters.rb +0 -16
- data/lib/mass_insert/builder/base.rb +0 -28
- data/lib/mass_insert/builder/utilities.rb +0 -13
- data/lib/mass_insert/result.rb +0 -33
- data/spec/adapters/column_types/binary_spec.rb +0 -64
- data/spec/adapters/column_types/boolean_spec.rb +0 -48
- data/spec/adapters/column_types/date_spec.rb +0 -14
- data/spec/adapters/column_types/datetime_spec.rb +0 -14
- data/spec/adapters/column_types/decimal_spec.rb +0 -59
- data/spec/adapters/column_types/integer_spec.rb +0 -59
- data/spec/adapters/column_types/string_spec.rb +0 -46
- data/spec/adapters/column_types/time_spec.rb +0 -14
- data/spec/adapters/model_spec.rb +0 -83
- data/spec/dummy/.gitignore +0 -15
- data/spec/dummy/Gemfile +0 -40
- data/spec/dummy/README.rdoc +0 -261
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +0 -15
- data/spec/dummy/app/assets/stylesheets/application.css +0 -13
- data/spec/dummy/app/controllers/application_controller.rb +0 -3
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/user.rb +0 -3
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/application.rb +0 -68
- data/spec/dummy/config/boot.rb +0 -6
- data/spec/dummy/config/database.yml +0 -49
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -37
- data/spec/dummy/config/environments/mysql2.rb +0 -37
- data/spec/dummy/config/environments/postgresql.rb +0 -37
- data/spec/dummy/config/environments/production.rb +0 -67
- data/spec/dummy/config/environments/sqlite3.rb +0 -37
- data/spec/dummy/config/environments/test.rb +0 -37
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -15
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -58
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20130412154541_create_users.rb +0 -16
- data/spec/dummy/db/schema.rb +0 -29
- data/spec/dummy/db/seeds.rb +0 -7
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/tasks/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -25
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/index.html +0 -241
- data/spec/dummy/public/robots.txt +0 -5
- data/spec/dummy/script/rails +0 -6
- data/spec/dummy/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/dummy/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/dummy/vendor/plugins/.gitkeep +0 -0
- data/spec/lib/mass_insert/base_spec.rb +0 -40
- data/spec/lib/mass_insert/builder/adapters/adapter_spec.rb +0 -116
- data/spec/lib/mass_insert/builder/adapters/helpers/abstract_query_spec.rb +0 -130
- data/spec/lib/mass_insert/builder/adapters/helpers/column_value_spec.rb +0 -222
- data/spec/lib/mass_insert/builder/adapters/mysql_adapter_spec.rb +0 -9
- data/spec/lib/mass_insert/builder/adapters/postgresql_adapter_spec.rb +0 -9
- data/spec/lib/mass_insert/builder/adapters/sqlite3_adapter_spec.rb +0 -52
- data/spec/lib/mass_insert/builder/adapters/sqlserver_adapter_spec.rb +0 -32
- data/spec/lib/mass_insert/builder/adapters_spec.rb +0 -31
- data/spec/lib/mass_insert/builder/base_spec.rb +0 -28
- data/spec/lib/mass_insert/builder/utilities_spec.rb +0 -11
- data/spec/lib/mass_insert/executer_spec.rb +0 -33
- data/spec/lib/mass_insert/process_spec.rb +0 -58
- data/spec/lib/mass_insert/result_spec.rb +0 -45
- data/spec/lib/mass_insert_spec.rb +0 -35
- data/spec/spec_helper.rb +0 -15
- data/spec/support/mass_insert_support.rb +0 -12
checksums.yaml
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
ZTE4MGExN2IwY2NmOTBkYTUwNmVmYzNjZDZkM2IxZTNhMmY1MmYyNw==
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 048a8940b6950ce71e156538ee9e3e49fc4093e7
|
|
4
|
+
data.tar.gz: c06223f8ded6fb2f4596fdb1514a57c02c90038e
|
|
7
5
|
SHA512:
|
|
8
|
-
metadata.gz:
|
|
9
|
-
|
|
10
|
-
OTQxZDI4MTEyZGI2MTFjZWI5NzJiMWE2YzQxMTJiZTliZWYyMzIyOTEzNTkx
|
|
11
|
-
ZWE0MTZkYjIxODE2ZDMyYTJkMDE0Mzg4NTRhZDQ2MmVlNDNiZDM=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
M2Q1MjFlYmVhNzc2ZDRlNDY4MTM0MTk3NjA0ODg4NDNkYmMwZDU4YjJkNWZm
|
|
14
|
-
N2IxZTZhMTI3MGFiNjI3Y2RjZGM1ZWUyYzNlODlkOTEzMDliMzM3ZjA2NzAz
|
|
15
|
-
MTA0ZmVjMmExNjNmNWYwNDE3MTRiNmJkYzMxYTEzMjI1OGMzYmU=
|
|
6
|
+
metadata.gz: 8016065eb3fc0076411860b949f4e0499a0754f7b3c4e2469573dc3094eb3f40a81fe2d50f60d947318c9db2504d648ef2ad17750914c631dc008d4bf37c151b
|
|
7
|
+
data.tar.gz: fe0d19f977031e25ae993d9ccc8bb2534d442ca0cea307c63afc4bc3630cd4c4d036a41a7037e69b06fdcefe151e84adb7ac4b7c0399cb98d2e1b3c5d28a9f98
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
rvm:
|
|
3
|
-
-
|
|
4
|
-
-
|
|
5
|
-
-
|
|
3
|
+
- '1.9.3'
|
|
4
|
+
- '2.0.0'
|
|
5
|
+
- '2.1.0'
|
|
6
|
+
|
|
7
|
+
#env:
|
|
8
|
+
#- 'AR_VERSION=3.2.17'
|
|
9
|
+
#- 'AR_VERSION=4.0.3'
|
|
10
|
+
#- 'AR_VERSION=4.1.0'
|
|
11
|
+
#- 'AR_VERSION=master'
|
|
6
12
|
|
|
7
13
|
before_script:
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- rake db:migrate RAILS_ENV=mysql2
|
|
12
|
-
- rake db:migrate RAILS_ENV=postgresql
|
|
13
|
-
- rake db:migrate RAILS_ENV=sqlite3
|
|
14
|
-
- cd ../..
|
|
14
|
+
- cp test/database.yml.example test/database.yml
|
|
15
|
+
- mysql -e 'CREATE DATABASE mass_insert_test;'
|
|
16
|
+
- psql -c 'CREATE DATABASE mass_insert_test;' -U postgres
|
data/Gemfile
CHANGED
|
@@ -2,11 +2,12 @@ source 'https://rubygems.org'
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem
|
|
6
|
-
gem
|
|
7
|
-
gem
|
|
8
|
-
|
|
9
|
-
gem
|
|
10
|
-
gem
|
|
11
|
-
|
|
12
|
-
gem
|
|
5
|
+
gem 'mysql2'
|
|
6
|
+
gem 'sqlite3'
|
|
7
|
+
gem 'pg'
|
|
8
|
+
|
|
9
|
+
gem 'simplecov'
|
|
10
|
+
gem 'coveralls', require: false
|
|
11
|
+
|
|
12
|
+
gem 'rake'
|
|
13
|
+
gem 'activerecord', '>= 3.2'
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -3,99 +3,55 @@
|
|
|
3
3
|
This gem aims to provide an easy and faster way to do single database insertions in Rails.
|
|
4
4
|
Support Mysql, PostgreSQL and SQLite3 adapters. It depends on ActiveRecord.
|
|
5
5
|
|
|
6
|
-
## Installation
|
|
7
6
|
|
|
7
|
+
## Installation
|
|
8
8
|
Add this line to your application's Gemfile:
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'mass_insert'
|
|
11
|
+
```
|
|
12
|
+
Run the bundle command to install it.
|
|
9
13
|
|
|
10
|
-
gem 'mass_insert'
|
|
11
|
-
|
|
12
|
-
And then execute:
|
|
13
|
-
|
|
14
|
-
$ bundle install
|
|
15
|
-
|
|
16
|
-
Or install it yourself with:
|
|
17
|
-
|
|
18
|
-
$ gem install mass_insert
|
|
19
14
|
|
|
20
15
|
## Advantages
|
|
21
|
-
|
|
22
16
|
Faster. It's depending of the computer but these are some results...
|
|
23
|
-
|
|
24
17
|
* PostgreSQL - Saving 10,000 records in 0.49s
|
|
25
18
|
|
|
19
|
+
|
|
26
20
|
## Attention
|
|
21
|
+
Since this is a single database insertion your model validations will be ignored,
|
|
22
|
+
then if you use this gem you need to be sure that information is OK to be persisted.
|
|
27
23
|
|
|
28
|
-
Since this is a single database insertion your model validations will be ignored, then if you use this gem you need to be sure that information is OK to be persisted.
|
|
29
24
|
|
|
30
25
|
## Basic Usage
|
|
26
|
+
To use MassInsert gem you need to call `mass_insert` method from your ActiveRecord model
|
|
27
|
+
and pass it an array with the values that you want to persist into the database.
|
|
28
|
+
```ruby
|
|
29
|
+
values = [
|
|
30
|
+
{
|
|
31
|
+
name: 'Jay',
|
|
32
|
+
email: 'tremendous_gamer@gmail.com',
|
|
33
|
+
age: 15
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'Beverly',
|
|
37
|
+
email: 'nippy_programmer@gmail.com',
|
|
38
|
+
age: 24
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
User.mass_insert(values)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Insertion per batches
|
|
47
|
+
Due you can get a database timeout error you can specify that the insertion will be in batches.
|
|
48
|
+
Just pass the `per_batch` option with the records per batch. Example...
|
|
49
|
+
```ruby
|
|
50
|
+
User.mass_insert(values, per_batch: 1000)
|
|
51
|
+
```
|
|
31
52
|
|
|
32
|
-
To use MassInsert gem you need to call mass_insert method from your ActiveRecord model and pass it an array with the values that you want to persist into the database.
|
|
33
|
-
|
|
34
|
-
The array of values:
|
|
35
|
-
|
|
36
|
-
values = [
|
|
37
|
-
{
|
|
38
|
-
:name => "Jay",
|
|
39
|
-
:email => "tremendous_gamer@gmail.com",
|
|
40
|
-
:age => 15
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
:name => "Beverly",
|
|
44
|
-
:email => "nippy_programmer@gmail.com",
|
|
45
|
-
:age => 24
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
|
|
49
|
-
And call mass_insert method from your model:
|
|
50
|
-
|
|
51
|
-
User.mass_insert(values)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
## Results
|
|
55
|
-
|
|
56
|
-
Sometimes after MassInsert process you need to see information about the process. MassInsert provides a simple way to do it. Just call the next methods from your model after MassInsert execution.
|
|
57
|
-
|
|
58
|
-
User.mass_insert_results.records # => 120000
|
|
59
|
-
|
|
60
|
-
Some result options are...
|
|
61
|
-
|
|
62
|
-
1. `records` : Returns the amount of records that were persisted.
|
|
63
|
-
2. `time` : Returns the time that took to do all the MassInsert process.
|
|
64
|
-
3. `building_time` : Returns the time that took to create the query string that was persisted.
|
|
65
|
-
4. `execution_time` : Returns the time that took to execute the query string that was persisted.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
## Options
|
|
69
|
-
|
|
70
|
-
MassInsert accepts options hash by second param when you call `mass_insert` from your model. These options allow you to configure the way that records will be persisted. Example...
|
|
71
|
-
|
|
72
|
-
options = {
|
|
73
|
-
:some_option => some_value,
|
|
74
|
-
:some_option => some_value
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
User.mass_insert(values, options)
|
|
78
|
-
|
|
79
|
-
OR directly
|
|
80
|
-
|
|
81
|
-
User.mass_insert(values, :option => value)
|
|
82
|
-
|
|
83
|
-
Some options you can include are...
|
|
84
|
-
|
|
85
|
-
**Primary key**
|
|
86
|
-
|
|
87
|
-
By default primary key is generated automatically. If you wish to set primary key manually you need to pass the `primary_key` option on true. Example...
|
|
88
|
-
|
|
89
|
-
User.mass_insert(values, :primary_key => true)
|
|
90
|
-
|
|
91
|
-
**Each slice**
|
|
92
|
-
|
|
93
|
-
Due you can get a database timeout error you can specify that the insertion will be in batches. Just pass the `each_slice` option with the records per batch. Example...
|
|
94
|
-
|
|
95
|
-
User.mass_insert(values, :each_slice => 10000)
|
|
96
53
|
|
|
97
54
|
## Contributing
|
|
98
|
-
|
|
99
55
|
1. Fork it
|
|
100
56
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
101
57
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
data/Rakefile
CHANGED
|
@@ -1,33 +1,28 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
require 'rake/testtask'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
desc "Runs unit tests"
|
|
5
|
-
task :unit do
|
|
6
|
-
system("echo '\e[00;32m\033[1mRunning unit tests...\e[00m'")
|
|
7
|
-
system("bundle exec rspec spec/lib")
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
adapters = [:mysql2, :postgresql, :sqlite3]
|
|
4
|
+
ADAPTERS = %w(mysql2 postgresql sqlite3)
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
ADAPTERS.each do |adapter|
|
|
7
|
+
namespace :test do
|
|
8
|
+
desc "Runs #{adapter} tests."
|
|
9
|
+
Rake::TestTask.new(adapter) do |t|
|
|
10
|
+
t.libs << 'test'
|
|
11
|
+
t.test_files = FileList[
|
|
12
|
+
"test/support/adapters/#{adapter}.rb",
|
|
13
|
+
"test/adapters/#{adapter}/**/*_test.rb"]
|
|
18
14
|
end
|
|
19
15
|
end
|
|
16
|
+
end
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
adapters.each do |adapter|
|
|
27
|
-
Rake.application["spec:#{adapter}"].invoke
|
|
28
|
-
raise "Test suite to #{adapter} failed!" unless $?.exitstatus == 0
|
|
18
|
+
namespace :test do
|
|
19
|
+
desc 'Runs tests.'
|
|
20
|
+
task :all do |t|
|
|
21
|
+
ADAPTERS.each do |adapter|
|
|
22
|
+
Rake.application["test:#{adapter}"].invoke
|
|
29
23
|
end
|
|
30
24
|
end
|
|
31
25
|
end
|
|
32
26
|
|
|
33
|
-
|
|
27
|
+
|
|
28
|
+
task default: 'test:postgresql'
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module MassInsert
|
|
2
|
+
module Adapters
|
|
3
|
+
class AbstractAdapter < SimpleDelegator
|
|
4
|
+
attr_accessor :values, :options
|
|
5
|
+
|
|
6
|
+
def initialize(class_name, values, options)
|
|
7
|
+
@values = values
|
|
8
|
+
@options = options
|
|
9
|
+
super(class_name)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_sql
|
|
13
|
+
"#{insert_sql} #{values_sql}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def columns
|
|
19
|
+
@columns ||= begin
|
|
20
|
+
columns = column_names
|
|
21
|
+
columns.delete(primary_key)
|
|
22
|
+
columns.map(&:to_sym)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def quoted_columns
|
|
27
|
+
columns.map do |name|
|
|
28
|
+
connection.quote_column_name(name)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def insert_sql
|
|
33
|
+
"INSERT INTO #{quoted_table_name} #{columns_sql} VALUES"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def columns_sql
|
|
37
|
+
"(#{quoted_columns.join(',')})"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def values_sql
|
|
41
|
+
"(#{array_of_attributes_sql.join('),(')});"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def array_of_attributes_sql
|
|
45
|
+
values.map do |attrs|
|
|
46
|
+
columns.map do |name|
|
|
47
|
+
value = attrs[name.to_sym] || attrs[name.to_s]
|
|
48
|
+
connection.quote(value, columns_hash[name.to_s])
|
|
49
|
+
end.join(',')
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/mass_insert/base.rb
CHANGED
|
@@ -1,89 +1,8 @@
|
|
|
1
1
|
module MassInsert
|
|
2
2
|
module Base
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
# Invoke mass insert just calling this from your ActiveRecord model...
|
|
7
|
-
#
|
|
8
|
-
# User.mass_insert(values)
|
|
9
|
-
#
|
|
10
|
-
# The values should be an array of hashes. Include attributes and values
|
|
11
|
-
# in every hash. Example...
|
|
12
|
-
#
|
|
13
|
-
# values = [
|
|
14
|
-
# {:name => "user name", :email => "user email"},
|
|
15
|
-
# {:name => "user name", :email => "user email"}
|
|
16
|
-
# ]
|
|
17
|
-
#
|
|
18
|
-
# == Options
|
|
19
|
-
#
|
|
20
|
-
# MassInset gem allow you to send it options as second param. Example...
|
|
21
|
-
#
|
|
22
|
-
# User.mass_insert(values, options)
|
|
23
|
-
#
|
|
24
|
-
# === Primary key
|
|
25
|
-
#
|
|
26
|
-
# By default primary key is ignored. If you wish primary key doesn't
|
|
27
|
-
# be ignored you need to pass the primary_key option on true.
|
|
28
|
-
#
|
|
29
|
-
# User.mass_insert(values, :primary_key => true)
|
|
30
|
-
#
|
|
31
|
-
# === Each slice
|
|
32
|
-
#
|
|
33
|
-
# Due you can get a database timeout error you can specify that the
|
|
34
|
-
# insertion will be in batches. You need to pass the each_slice option
|
|
35
|
-
# with the records per batch. Example...
|
|
36
|
-
#
|
|
37
|
-
# User.mass_insert(values, :each_slice => 10000)
|
|
38
|
-
#
|
|
39
|
-
def mass_insert values, options = {}
|
|
40
|
-
extend ClassMethods
|
|
41
|
-
|
|
42
|
-
options[:class_name] ||= self
|
|
43
|
-
options[:each_slice] ||= false
|
|
44
|
-
options[:primary_key] ||= false
|
|
45
|
-
|
|
46
|
-
@mass_insert_process = Process.new(values, options)
|
|
47
|
-
@mass_insert_process.start
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
module ClassMethods
|
|
52
|
-
|
|
53
|
-
# == Results
|
|
54
|
-
#
|
|
55
|
-
# Sometimes after MassInsert process you need to see information about
|
|
56
|
-
# the process. MassInsert provides a simple way to do it. Just call the
|
|
57
|
-
# next methods from your model after MassInsert execution:
|
|
58
|
-
#
|
|
59
|
-
# === Records
|
|
60
|
-
#
|
|
61
|
-
# Returns the amount of records that were persisted.
|
|
62
|
-
#
|
|
63
|
-
# User.mass_insert_results.records # => 120000
|
|
64
|
-
#
|
|
65
|
-
# === Time
|
|
66
|
-
#
|
|
67
|
-
# Returns the time that took to do all the MassInsert process.
|
|
68
|
-
#
|
|
69
|
-
# User.mass_insert_results.time # => 0.67
|
|
70
|
-
#
|
|
71
|
-
# === Building time
|
|
72
|
-
#
|
|
73
|
-
# Returns the time that took to create the query string that was persisted.
|
|
74
|
-
#
|
|
75
|
-
# User.mass_insert_results.building_time # => 0.58
|
|
76
|
-
#
|
|
77
|
-
# === Execution time
|
|
78
|
-
#
|
|
79
|
-
# Returns the time that took to execute the query string that was persisted.
|
|
80
|
-
#
|
|
81
|
-
# User.mass_insert_results.execution_time # => 0.09
|
|
82
|
-
#
|
|
83
|
-
def mass_insert_results
|
|
84
|
-
Result.new(@mass_insert_process)
|
|
85
|
-
end
|
|
86
|
-
|
|
3
|
+
def mass_insert(values, options = {})
|
|
4
|
+
options[:class_name] ||= self
|
|
5
|
+
Process.new(values, options).start
|
|
87
6
|
end
|
|
88
7
|
end
|
|
89
8
|
end
|
data/lib/mass_insert/executer.rb
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
module MassInsert
|
|
2
|
-
# This class is responsible to execute the queries into the database.
|
|
3
|
-
# Uses the ActiveRecord::Base.connection.execute functionality.
|
|
4
2
|
class Executer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Array(queries).each do |query|
|
|
3
|
+
def execute(query)
|
|
4
|
+
ActiveRecord::Base.transaction do
|
|
8
5
|
ActiveRecord::Base.connection.execute(query)
|
|
9
6
|
end
|
|
10
7
|
end
|
|
11
|
-
|
|
12
8
|
end
|
|
13
9
|
end
|
data/lib/mass_insert/process.rb
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
require 'benchmark'
|
|
2
|
-
|
|
3
1
|
module MassInsert
|
|
4
2
|
class Process
|
|
3
|
+
attr_reader :values, :options
|
|
5
4
|
|
|
6
|
-
def initialize
|
|
5
|
+
def initialize(values, options)
|
|
7
6
|
@values = values
|
|
8
7
|
@options = options
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def start
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# The second one executes queries into the database using an
|
|
19
|
-
# ActiveRecord connection.
|
|
20
|
-
@execution_time = Benchmark.measure do
|
|
21
|
-
executer.execute(@queries)
|
|
11
|
+
ActiveRecord::Base.transaction do
|
|
12
|
+
values.each_slice(per_batch).each do |batch|
|
|
13
|
+
query = builder.build(batch, options)
|
|
14
|
+
executer.execute(query)
|
|
15
|
+
end
|
|
22
16
|
end
|
|
23
17
|
end
|
|
24
18
|
|
|
19
|
+
private
|
|
20
|
+
|
|
25
21
|
def builder
|
|
26
|
-
@builder ||= Builder
|
|
22
|
+
@builder ||= Builder.new
|
|
27
23
|
end
|
|
28
24
|
|
|
29
25
|
def executer
|
|
30
26
|
@executer ||= Executer.new
|
|
31
27
|
end
|
|
28
|
+
|
|
29
|
+
def per_batch
|
|
30
|
+
options[:per_batch] || Utilities.per_batch
|
|
31
|
+
end
|
|
32
32
|
end
|
|
33
33
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module MassInsert
|
|
2
|
+
class Utilities
|
|
3
|
+
ADAPTERS = {
|
|
4
|
+
mysql2: Adapters::Mysql2Adapter,
|
|
5
|
+
postgresql: Adapters::PostgreSQLAdapter,
|
|
6
|
+
sqlite3: Adapters::SQLite3Adapter,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
def self.adapter
|
|
10
|
+
database_config[:adapter].to_sym
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.database_config
|
|
14
|
+
ActiveRecord::Base.connection.instance_values['config']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.adapter_class
|
|
18
|
+
ADAPTERS[Utilities.adapter]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.per_batch
|
|
22
|
+
500
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/mass_insert/version.rb
CHANGED
data/lib/mass_insert.rb
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
require 'delegate'
|
|
2
|
+
|
|
1
3
|
module MassInsert
|
|
2
4
|
autoload :Base, 'mass_insert/base.rb'
|
|
3
|
-
autoload :
|
|
5
|
+
autoload :Builder, 'mass_insert/builder.rb'
|
|
4
6
|
autoload :Process, 'mass_insert/process.rb'
|
|
5
7
|
autoload :Executer, 'mass_insert/executer.rb'
|
|
8
|
+
autoload :Utilities, 'mass_insert/utilities.rb'
|
|
6
9
|
autoload :VERSION, 'mass_insert/version.rb'
|
|
7
10
|
|
|
8
|
-
module
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
11
|
+
module Adapters
|
|
12
|
+
autoload :AbstractAdapter, 'mass_insert/adapters/abstract_adapter.rb'
|
|
13
|
+
autoload :Mysql2Adapter, 'mass_insert/adapters/mysql2_adapter.rb'
|
|
14
|
+
autoload :PostgreSQLAdapter, 'mass_insert/adapters/postgresql_adapter.rb'
|
|
15
|
+
autoload :SQLite3Adapter, 'mass_insert/adapters/sqlite3_adapter.rb'
|
|
12
16
|
end
|
|
13
17
|
end
|
|
14
18
|
|
data/mass_insert.gemspec
CHANGED
|
@@ -4,20 +4,20 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require 'mass_insert/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
7
|
+
spec.name = 'mass_insert'
|
|
8
8
|
spec.version = MassInsert::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
11
|
-
spec.summary =
|
|
12
|
-
spec.description =
|
|
13
|
-
spec.homepage =
|
|
14
|
-
spec.license =
|
|
9
|
+
spec.authors = ['Alejandro Gutiérrez']
|
|
10
|
+
spec.email = ['alejandrodevs@gmail.com']
|
|
11
|
+
spec.summary = 'Mass database insertion in Rails'
|
|
12
|
+
spec.description = 'This gem aims to provide an easy and faster way to do single database insertions in Rails.'
|
|
13
|
+
spec.homepage = 'https://github.com/alejandrogutierrez/mass_insert'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
15
|
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
-
spec.require_paths = [
|
|
19
|
+
spec.require_paths = ['lib']
|
|
20
20
|
|
|
21
|
-
spec.
|
|
22
|
-
spec.
|
|
21
|
+
spec.required_ruby_version = '>= 1.9.3'
|
|
22
|
+
spec.add_dependency 'activerecord', '>= 3.2'
|
|
23
23
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
common: &common
|
|
2
|
+
username: root
|
|
3
|
+
password:
|
|
4
|
+
encoding: utf8
|
|
5
|
+
database: mass_insert_test
|
|
6
|
+
|
|
7
|
+
mysql2: &mysql2
|
|
8
|
+
<<: *common
|
|
9
|
+
adapter: mysql2
|
|
10
|
+
|
|
11
|
+
postgresql: &postgresql
|
|
12
|
+
<<: *common
|
|
13
|
+
username: postgres
|
|
14
|
+
adapter: postgresql
|
|
15
|
+
|
|
16
|
+
sqlite3: &sqlite3
|
|
17
|
+
adapter: sqlite3
|
|
18
|
+
database: tmp/test.db
|
data/test/models/user.rb
ADDED
data/test/schema.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ENV['DATABASE_ADAPTER'] = 'mysql2'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ENV['DATABASE_ADAPTER'] = 'postgresql'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ENV['DATABASE_ADAPTER'] = 'sqlite3'
|