mass_insert 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.travis.yml +10 -0
- data/Gemfile +0 -2
- data/README.md +15 -23
- data/Rakefile +22 -33
- data/lib/mass_insert.rb +11 -7
- data/lib/mass_insert/base.rb +22 -58
- data/lib/mass_insert/builder/adapters.rb +16 -0
- data/lib/mass_insert/builder/adapters/adapter.rb +65 -0
- data/lib/mass_insert/builder/adapters/helpers/abstract_query.rb +52 -0
- data/lib/mass_insert/builder/adapters/helpers/column_value.rb +90 -0
- data/lib/mass_insert/builder/adapters/mysql2_adapter.rb +15 -0
- data/lib/mass_insert/builder/adapters/postgresql_adapter.rb +7 -0
- data/lib/mass_insert/builder/adapters/sqlite3_adapter.rb +27 -0
- data/lib/mass_insert/builder/adapters/sqlserver_adapter.rb +26 -0
- data/lib/mass_insert/builder/base.rb +28 -0
- data/lib/mass_insert/builder/utilities.rb +13 -0
- data/lib/mass_insert/executer.rb +13 -0
- data/lib/mass_insert/process.rb +24 -0
- data/lib/mass_insert/result.rb +33 -0
- data/lib/mass_insert/version.rb +1 -1
- data/mass_insert.gemspec +2 -2
- data/spec/adapters/column_types/binary_spec.rb +64 -0
- data/spec/adapters/column_types/boolean_spec.rb +48 -0
- data/spec/adapters/column_types/decimal_spec.rb +59 -0
- data/spec/adapters/column_types/integer_spec.rb +59 -0
- data/spec/adapters/column_types/string_spec.rb +46 -0
- data/spec/{active_record_models → adapters}/model_spec.rb +1 -21
- data/spec/{active_record_dummy → dummy}/.gitignore +0 -0
- data/spec/{active_record_dummy → dummy}/Gemfile +1 -1
- data/spec/{active_record_dummy → dummy}/README.rdoc +0 -0
- data/spec/{active_record_dummy → dummy}/Rakefile +0 -0
- data/spec/{active_record_dummy → dummy}/app/assets/images/rails.png +0 -0
- data/spec/{active_record_dummy → dummy}/app/assets/javascripts/application.js +0 -0
- data/spec/{active_record_dummy → dummy}/app/assets/stylesheets/application.css +0 -0
- data/spec/{active_record_dummy → dummy}/app/controllers/application_controller.rb +0 -0
- data/spec/{active_record_dummy → dummy}/app/helpers/application_helper.rb +0 -0
- data/spec/{active_record_dummy → dummy}/app/mailers/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/app/models/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/app/models/user.rb +0 -0
- data/spec/{active_record_dummy → dummy}/app/views/layouts/application.html.erb +0 -0
- data/spec/{active_record_dummy → dummy}/config.ru +0 -0
- data/spec/{active_record_dummy → dummy}/config/application.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/boot.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/database.yml +3 -8
- data/spec/{active_record_dummy → dummy}/config/environment.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/environments/development.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/environments/mysql2.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/environments/postgresql.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/environments/production.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/environments/sqlite3.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/environments/test.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/initializers/backtrace_silencers.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/initializers/inflections.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/initializers/mime_types.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/initializers/secret_token.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/initializers/session_store.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/initializers/wrap_parameters.rb +0 -0
- data/spec/{active_record_dummy → dummy}/config/locales/en.yml +0 -0
- data/spec/{active_record_dummy → dummy}/config/routes.rb +0 -0
- data/spec/{active_record_dummy → dummy}/db/migrate/20130412154541_create_users.rb +0 -0
- data/spec/{active_record_dummy → dummy}/db/schema.rb +0 -0
- data/spec/{active_record_dummy → dummy}/db/seeds.rb +0 -0
- data/spec/{active_record_dummy → dummy}/lib/assets/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/lib/tasks/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/log/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/public/404.html +0 -0
- data/spec/{active_record_dummy → dummy}/public/422.html +0 -0
- data/spec/{active_record_dummy → dummy}/public/500.html +0 -0
- data/spec/{active_record_dummy → dummy}/public/favicon.ico +0 -0
- data/spec/{active_record_dummy → dummy}/public/index.html +0 -0
- data/spec/{active_record_dummy → dummy}/public/robots.txt +0 -0
- data/spec/{active_record_dummy → dummy}/script/rails +0 -0
- data/spec/{active_record_dummy → dummy}/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/{active_record_dummy → dummy}/vendor/plugins/.gitkeep +0 -0
- data/spec/lib/mass_insert/base_spec.rb +40 -0
- data/spec/lib/mass_insert/builder/adapters/adapter_spec.rb +129 -0
- data/spec/lib/mass_insert/builder/adapters/helpers/abstract_query_spec.rb +130 -0
- data/spec/{mass_insert/adapters/adapter_helpers → lib/mass_insert/builder/adapters/helpers}/column_value_spec.rb +42 -94
- data/spec/lib/mass_insert/builder/adapters/mysql_adapter_spec.rb +15 -0
- data/spec/lib/mass_insert/builder/adapters/postgresql_adapter_spec.rb +9 -0
- data/spec/lib/mass_insert/builder/adapters/sqlite3_adapter_spec.rb +52 -0
- data/spec/lib/mass_insert/builder/adapters/sqlserver_adapter_spec.rb +38 -0
- data/spec/lib/mass_insert/builder/adapters_spec.rb +31 -0
- data/spec/lib/mass_insert/builder/base_spec.rb +28 -0
- data/spec/lib/mass_insert/builder/utilities_spec.rb +11 -0
- data/spec/lib/mass_insert/executer_spec.rb +33 -0
- data/spec/lib/mass_insert/process_spec.rb +44 -0
- data/spec/lib/mass_insert/result_spec.rb +45 -0
- data/spec/lib/mass_insert_spec.rb +35 -0
- data/spec/spec_helper.rb +7 -2
- data/spec/support/mass_insert_support.rb +12 -0
- metadata +160 -163
- data/lib/mass_insert/adapters.rb +0 -10
- data/lib/mass_insert/adapters/adapter.rb +0 -26
- data/lib/mass_insert/adapters/adapter_helpers.rb +0 -11
- data/lib/mass_insert/adapters/adapter_helpers/abstract_query.rb +0 -56
- data/lib/mass_insert/adapters/adapter_helpers/column_value.rb +0 -110
- data/lib/mass_insert/adapters/adapter_helpers/sanitizer.rb +0 -21
- data/lib/mass_insert/adapters/adapter_helpers/timestamp.rb +0 -33
- data/lib/mass_insert/adapters/mysql2_adapter.rb +0 -13
- data/lib/mass_insert/adapters/postgresql_adapter.rb +0 -5
- data/lib/mass_insert/adapters/sqlite3_adapter.rb +0 -37
- data/lib/mass_insert/adapters/sqlserver_adapter.rb +0 -29
- data/lib/mass_insert/process_control.rb +0 -46
- data/lib/mass_insert/query_builder.rb +0 -39
- data/lib/mass_insert/query_execution.rb +0 -29
- data/spec/active_record_models/column_types/binary_spec.rb +0 -60
- data/spec/active_record_models/column_types/boolean_spec.rb +0 -52
- data/spec/active_record_models/column_types/decimal_spec.rb +0 -49
- data/spec/active_record_models/column_types/integer_spec.rb +0 -49
- data/spec/active_record_models/column_types/string_spec.rb +0 -50
- data/spec/dummy_models/test.rb +0 -5
- data/spec/mass_insert/adapters/adapter_helpers/abstract_query_spec.rb +0 -119
- data/spec/mass_insert/adapters/adapter_helpers/sanitizer_spec.rb +0 -46
- data/spec/mass_insert/adapters/adapter_helpers/timestamp_spec.rb +0 -75
- data/spec/mass_insert/adapters/adapter_helpers_spec.rb +0 -24
- data/spec/mass_insert/adapters/adapter_spec.rb +0 -79
- data/spec/mass_insert/adapters/mysql_adapter_spec.rb +0 -22
- data/spec/mass_insert/adapters/postgresql_adapter_spec.rb +0 -11
- data/spec/mass_insert/adapters/sqlite3_adapter_spec.rb +0 -84
- data/spec/mass_insert/adapters/sqlserver_adapter_spec.rb +0 -61
- data/spec/mass_insert/adapters_spec.rb +0 -32
- data/spec/mass_insert/base_spec.rb +0 -114
- data/spec/mass_insert/process_control_spec.rb +0 -125
- data/spec/mass_insert/query_builder_spec.rb +0 -84
- data/spec/mass_insert/query_execution_spec.rb +0 -50
- data/spec/mass_insert_spec.rb +0 -28
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,3 +2,13 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- "1.9.2"
|
4
4
|
- "1.9.3"
|
5
|
+
- "2.0.0"
|
6
|
+
|
7
|
+
before_script:
|
8
|
+
- mysql -e 'create database mysql2_test;'
|
9
|
+
- psql -c 'create database postgresql_test;' -U postgres
|
10
|
+
- cd spec/dummy
|
11
|
+
- rake db:migrate RAILS_ENV=mysql2
|
12
|
+
- rake db:migrate RAILS_ENV=postgresql
|
13
|
+
- rake db:migrate RAILS_ENV=sqlite3
|
14
|
+
- cd ../..
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# MassInsert [![Build Status](https://travis-ci.org/alejandrogutierrez/mass_insert.png?branch=master)](https://travis-ci.org/alejandrogutierrez/mass_insert)
|
2
2
|
|
3
3
|
This gem aims to provide an easy and faster way to do single database insertions in Rails.
|
4
|
-
Support Mysql, PostgreSQL
|
4
|
+
Support Mysql, PostgreSQL and SQLite3 adapters.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
@@ -21,7 +21,7 @@ Or install it yourself with:
|
|
21
21
|
|
22
22
|
Faster. It's depending of the computer but these are some results...
|
23
23
|
|
24
|
-
* PostgreSQL - Saving 10,000 records in 0.
|
24
|
+
* PostgreSQL - Saving 10,000 records in 0.49s
|
25
25
|
|
26
26
|
## Attention
|
27
27
|
|
@@ -43,11 +43,6 @@ The array of values:
|
|
43
43
|
:name => "Beverly",
|
44
44
|
:email => "nippy_programmer@gmail.com",
|
45
45
|
:age => 24
|
46
|
-
},
|
47
|
-
{
|
48
|
-
:name => "Scottie",
|
49
|
-
:email => "angry_programmer@gmail.com",
|
50
|
-
:age => 32
|
51
46
|
}
|
52
47
|
]
|
53
48
|
|
@@ -58,7 +53,7 @@ And call mass_insert method from your model:
|
|
58
53
|
|
59
54
|
## Results
|
60
55
|
|
61
|
-
Sometimes after MassInsert process you need to see some necessary information about the process. MassInsert gem provides a simple way to do it.
|
56
|
+
Sometimes after MassInsert process you need to see some necessary information about the process. MassInsert gem provides a simple way to do it. Just call the next methods from your model after MassInsert execution.
|
62
57
|
|
63
58
|
User.mass_insert_results.records # => 120000
|
64
59
|
|
@@ -66,8 +61,8 @@ Some result options are...
|
|
66
61
|
|
67
62
|
1. `records` : Returns the amount of records that were persisted.
|
68
63
|
2. `time` : Returns the time that took to do all the MassInsert process.
|
69
|
-
3. `
|
70
|
-
4. `
|
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.
|
71
66
|
|
72
67
|
|
73
68
|
## Options
|
@@ -75,32 +70,29 @@ Some result options are...
|
|
75
70
|
MassInsert accepts options hash by second param when you call `mass_insert` from your model. This options allow you to configure the way that the records will be created. Example...
|
76
71
|
|
77
72
|
options = {
|
78
|
-
:
|
79
|
-
:
|
73
|
+
:some_option => some_value,
|
74
|
+
:some_option => some_value
|
80
75
|
}
|
81
76
|
|
82
77
|
User.mass_insert(values, options)
|
83
78
|
|
84
79
|
OR directly
|
85
80
|
|
86
|
-
User.mass_insert(values, :
|
81
|
+
User.mass_insert(values, :option => value)
|
87
82
|
|
88
|
-
Some options
|
83
|
+
Some options you can include are...
|
89
84
|
|
90
|
-
**
|
91
|
-
- Default value is the table name to your model. This options rarely needs to change but you can do it if you pass a string with the table name. Example...
|
85
|
+
**Primary key**
|
92
86
|
|
93
|
-
|
87
|
+
By default primary key is ignored. If you wish primary key doesn't be ignored you need to pass the `primary_key` option on true. Example...
|
94
88
|
|
95
|
-
|
96
|
-
- Default value is `:id`. You can change the name of primary key column send it a symbol with the column name.
|
89
|
+
User.mass_insert(values, :primary_key => true)
|
97
90
|
|
98
|
-
|
91
|
+
**Each slice**
|
99
92
|
|
100
|
-
|
101
|
-
- Default value is `:auto`. When is `:auto` MassInsert knows that the database will generate the value of the primary key column automatically. If you pass `:manual` as primary key mode you need to create your value hashes with the key and value of the primary key column.
|
93
|
+
Due you can get a database timeout error you can specify that the insertion will be in batches. You need to pass the `each_slice` option with the records per batch. Example...
|
102
94
|
|
103
|
-
|
95
|
+
User.mass_insert(values, :each_slice => 10000)
|
104
96
|
|
105
97
|
## Contributing
|
106
98
|
|
data/Rakefile
CHANGED
@@ -1,44 +1,33 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
|
3
3
|
namespace :spec do
|
4
|
-
desc "
|
5
|
-
task :
|
6
|
-
system("
|
7
|
-
|
8
|
-
cd spec/active_record_dummy
|
9
|
-
rake db:drop db:create db:migrate RAILS_ENV=mysql2
|
10
|
-
rake db:drop db:create db:migrate RAILS_ENV=postgresql
|
11
|
-
rake db:drop db:create db:migrate RAILS_ENV=sqlite3
|
12
|
-
")
|
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")
|
13
8
|
end
|
14
9
|
|
15
|
-
|
16
|
-
task :all do
|
17
|
-
system("echo '\e[00;32m\033[1mRunning all unit tests...\e[00m'")
|
18
|
-
system("bundle exec rspec spec/mass_insert_spec.rb spec/mass_insert")
|
19
|
-
end
|
20
|
-
|
21
|
-
desc "Runs all the mysql2 specs"
|
22
|
-
task :mysql2 do
|
23
|
-
ENV["RAILS_ENV"] = "mysql2"
|
24
|
-
system("echo '\e[00;32m\033[1mRunning the Mysql2 adapter tests...\e[00m'")
|
25
|
-
system("bundle exec rspec spec/active_record_models")
|
26
|
-
end
|
10
|
+
adapters = [:mysql2, :postgresql, :sqlite3]
|
27
11
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
12
|
+
adapters.each do |adapter|
|
13
|
+
desc "Runs test suite to #{adapter}"
|
14
|
+
task adapter do
|
15
|
+
ENV["RAILS_ENV"] = adapter.to_s
|
16
|
+
system("echo '\e[00;32m\033[1mRunning test suite to #{adapter}...\e[00m'")
|
17
|
+
system("bundle exec rspec spec/adapters")
|
18
|
+
end
|
33
19
|
end
|
34
20
|
|
35
|
-
desc "Runs all
|
36
|
-
task :
|
37
|
-
|
38
|
-
|
39
|
-
|
21
|
+
desc "Runs all specs"
|
22
|
+
task :all do
|
23
|
+
Rake.application['spec:unit'].invoke
|
24
|
+
raise "Unit test failed!" unless $?.exitstatus == 0
|
25
|
+
|
26
|
+
adapters.each do |adapter|
|
27
|
+
Rake.application["spec:#{adapter}"].invoke
|
28
|
+
raise "Test suite to #{adapter} failed!" unless $?.exitstatus == 0
|
29
|
+
end
|
40
30
|
end
|
41
31
|
end
|
42
32
|
|
43
|
-
|
44
|
-
task default: ['spec:mysql2', 'spec:postgresql', 'spec:sqlite3', 'spec:all']
|
33
|
+
task default: 'spec:all'
|
data/lib/mass_insert.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
require "mass_insert/version"
|
2
|
-
|
3
1
|
module MassInsert
|
4
|
-
autoload :
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
2
|
+
autoload :Base, 'mass_insert/base.rb'
|
3
|
+
autoload :Result, 'mass_insert/result.rb'
|
4
|
+
autoload :Process, 'mass_insert/process.rb'
|
5
|
+
autoload :Executer, 'mass_insert/executer.rb'
|
6
|
+
autoload :VERSION, 'mass_insert/version.rb'
|
7
|
+
|
8
|
+
module Builder
|
9
|
+
autoload :Base, 'mass_insert/builder/base.rb'
|
10
|
+
autoload :Adapters, 'mass_insert/builder/adapters.rb'
|
11
|
+
autoload :Utilities, 'mass_insert/builder/utilities.rb'
|
12
|
+
end
|
9
13
|
end
|
10
14
|
|
11
15
|
if defined?(ActiveRecord::Base)
|
data/lib/mass_insert/base.rb
CHANGED
@@ -3,93 +3,57 @@ module MassInsert
|
|
3
3
|
|
4
4
|
# = MassInsert
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# ActiveRecord model. Example...
|
6
|
+
# Invoke mass insert just calling this from your ActiveRecord model...
|
8
7
|
#
|
9
8
|
# User.mass_insert(values)
|
10
9
|
#
|
11
|
-
# The values should be an array
|
12
|
-
# Example...
|
10
|
+
# The values should be an array of hashes. Include attributes and values
|
11
|
+
# in every hash. Example...
|
13
12
|
#
|
14
13
|
# values = [
|
15
14
|
# {:name => "user name", :email => "user email"},
|
16
|
-
# {:name => "user name", :email => "user email"},
|
17
15
|
# {:name => "user name", :email => "user email"}
|
18
16
|
# ]
|
19
17
|
#
|
20
18
|
# == Options
|
21
19
|
#
|
22
|
-
#
|
23
|
-
# Example...
|
20
|
+
# MassInset gem allow you to send it options as second param. Example...
|
24
21
|
#
|
25
22
|
# User.mass_insert(values, options)
|
26
23
|
#
|
27
|
-
# ===
|
28
|
-
#
|
29
|
-
# Default value is the table name to your model. This options rarely
|
30
|
-
# needs to change but you can do it if you pass a string with the table
|
31
|
-
# name. Example...
|
32
|
-
#
|
33
|
-
# options = {:table_name => "users"}
|
34
|
-
#
|
35
|
-
# === primary_key
|
36
|
-
#
|
37
|
-
# Default value is :id. You can change the name of primary key column
|
38
|
-
# send it a symbol with the column name.
|
24
|
+
# === Primary key
|
39
25
|
#
|
40
|
-
#
|
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.
|
41
28
|
#
|
42
|
-
#
|
29
|
+
# options = {:primary_key => true}
|
43
30
|
#
|
44
|
-
#
|
45
|
-
# will generate the value of the primary key column automatically. If
|
46
|
-
# you pass :manual as primary key mode you need to create your value
|
47
|
-
# hashes with the key and value of the primary key column.
|
31
|
+
# === Each slice
|
48
32
|
#
|
49
|
-
#
|
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...
|
50
36
|
#
|
51
|
-
#
|
52
|
-
# is going to extend the methods in ClassMethods module. This module
|
53
|
-
# contains some methods that provides some necessary functionality.
|
37
|
+
# User.mass_insert(values, :each_slice => 10000)
|
54
38
|
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
extend ClassMethods
|
62
|
-
end
|
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
|
63
45
|
|
64
|
-
|
65
|
-
@mass_insert_process = ProcessControl.new(values, options)
|
46
|
+
@mass_insert_process = Process.new(values, options)
|
66
47
|
@mass_insert_process.start
|
67
48
|
end
|
68
49
|
|
69
50
|
|
70
51
|
module ClassMethods
|
71
|
-
|
72
|
-
# results of MassInsert process. This method calls results method
|
73
|
-
# in ProcessControl class. Returns nil if there is not a instance
|
74
|
-
# variable with the MassInset process.
|
52
|
+
|
75
53
|
def mass_insert_results
|
76
|
-
|
54
|
+
Result.new(@mass_insert_process)
|
77
55
|
end
|
78
56
|
|
79
|
-
private
|
80
|
-
# Sanitizes the MassInset options that were passed by params.
|
81
|
-
# Prepares default options that come in the class that invokes the
|
82
|
-
# mass_insert function and attributes options that were configured
|
83
|
-
# and if the options weren't passed, they would be initialized with
|
84
|
-
# the default values.
|
85
|
-
def mass_insert_options options = {}
|
86
|
-
options[:class_name] ||= self
|
87
|
-
options[:table_name] ||= self.table_name
|
88
|
-
options[:primary_key] ||= :id
|
89
|
-
options[:primary_key_mode] ||= :auto
|
90
|
-
options
|
91
|
-
end
|
92
|
-
|
93
57
|
end
|
94
58
|
end
|
95
59
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module MassInsert
|
2
|
+
module Builder
|
3
|
+
module Adapters
|
4
|
+
autoload :Adapter, 'mass_insert/builder/adapters/adapter.rb'
|
5
|
+
autoload :Mysql2Adapter, 'mass_insert/builder/adapters/mysql2_adapter.rb'
|
6
|
+
autoload :PostgreSQLAdapter, 'mass_insert/builder/adapters/postgresql_adapter.rb'
|
7
|
+
autoload :SQLite3Adapter, 'mass_insert/builder/adapters/sqlite3_adapter.rb'
|
8
|
+
autoload :SQLServerAdapter, 'mass_insert/builder/adapters/sqlserver_adapter.rb'
|
9
|
+
|
10
|
+
module Helpers
|
11
|
+
autoload :AbstractQuery, 'mass_insert/builder/adapters/helpers/abstract_query.rb'
|
12
|
+
autoload :ColumnValue, 'mass_insert/builder/adapters/helpers/column_value.rb'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module MassInsert
|
2
|
+
module Builder
|
3
|
+
module Adapters
|
4
|
+
class Adapter
|
5
|
+
include Helpers::AbstractQuery
|
6
|
+
|
7
|
+
attr_accessor :values, :options
|
8
|
+
|
9
|
+
def initialize values, options
|
10
|
+
@values = values
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the options according to the method that wasn't found.
|
15
|
+
def method_missing method, *args
|
16
|
+
@options.has_key?(method) ? @options[method] : super
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an array according to the options with the column names
|
20
|
+
# that will be included in the queries.
|
21
|
+
def columns
|
22
|
+
@columns ||= sanitized_columns
|
23
|
+
end
|
24
|
+
|
25
|
+
# Prepare array with the column names according to the options.
|
26
|
+
def sanitized_columns
|
27
|
+
columns = class_name.column_names
|
28
|
+
columns.delete(class_name.primary_key) unless primary_key
|
29
|
+
columns.map(&:to_sym)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns true o false if the database table has timestamp columns.
|
33
|
+
def timestamp?
|
34
|
+
columns.include?(:created_at) && columns.include?(:updated_at)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns timestamp format according to the database adapter. This
|
38
|
+
# function can be overwrite in database adapters classes.
|
39
|
+
def timestamp_format
|
40
|
+
"%Y-%m-%d %H:%M:%S.%6N"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the timestamp value according to the correct timestamp
|
44
|
+
# format to that database engine.
|
45
|
+
def timestamp
|
46
|
+
Time.now.strftime(timestamp_format)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the timestamp hash to be merge into row values that will
|
50
|
+
# be saved in the database.
|
51
|
+
def timestamp_hash
|
52
|
+
timestamp_value = timestamp
|
53
|
+
{:created_at => timestamp_value, :updated_at => timestamp_value}
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the amount of records to each query. Tries to take the
|
57
|
+
# each_slice option value or the length of values.
|
58
|
+
def values_per_insertion
|
59
|
+
each_slice || @values.count
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module MassInsert
|
2
|
+
module Builder
|
3
|
+
module Adapters
|
4
|
+
module Helpers
|
5
|
+
module AbstractQuery
|
6
|
+
|
7
|
+
# Returns a basic beginning of the query.
|
8
|
+
def begin_string
|
9
|
+
"INSERT INTO #{class_name.table_name} "
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a basic part of the query with the columns definition.
|
13
|
+
def string_columns
|
14
|
+
"(#{columns.join(", ")}) "
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a basic part of the query with all the records values.
|
18
|
+
def string_values
|
19
|
+
"VALUES (#{string_rows_values});"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns all the column values to all the records
|
23
|
+
def string_rows_values
|
24
|
+
values.map{ |row| string_single_row_values(row) }.join("), (")
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns all the column values to a single record.
|
28
|
+
def string_single_row_values row
|
29
|
+
row.merge!(timestamp_hash) if timestamp?
|
30
|
+
columns.map{ |col| string_single_value(row, col) }.join(", ")
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a single column value. According to the database
|
34
|
+
# configuration, column type and presence.
|
35
|
+
def string_single_value row, column
|
36
|
+
ColumnValue.new(row, column, class_name).build
|
37
|
+
end
|
38
|
+
|
39
|
+
# Values will be treated in batches according to the values per
|
40
|
+
# insertion value. It'll generate an array with queries.
|
41
|
+
def execute
|
42
|
+
@values.each_slice(values_per_insertion).map do |slice|
|
43
|
+
@values = slice;
|
44
|
+
"#{begin_string}#{string_columns}#{string_values}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|