mass_insert 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|