mass_insert 0.1.1 → 0.1.2

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 (129) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +0 -2
  4. data/README.md +15 -23
  5. data/Rakefile +22 -33
  6. data/lib/mass_insert.rb +11 -7
  7. data/lib/mass_insert/base.rb +22 -58
  8. data/lib/mass_insert/builder/adapters.rb +16 -0
  9. data/lib/mass_insert/builder/adapters/adapter.rb +65 -0
  10. data/lib/mass_insert/builder/adapters/helpers/abstract_query.rb +52 -0
  11. data/lib/mass_insert/builder/adapters/helpers/column_value.rb +90 -0
  12. data/lib/mass_insert/builder/adapters/mysql2_adapter.rb +15 -0
  13. data/lib/mass_insert/builder/adapters/postgresql_adapter.rb +7 -0
  14. data/lib/mass_insert/builder/adapters/sqlite3_adapter.rb +27 -0
  15. data/lib/mass_insert/builder/adapters/sqlserver_adapter.rb +26 -0
  16. data/lib/mass_insert/builder/base.rb +28 -0
  17. data/lib/mass_insert/builder/utilities.rb +13 -0
  18. data/lib/mass_insert/executer.rb +13 -0
  19. data/lib/mass_insert/process.rb +24 -0
  20. data/lib/mass_insert/result.rb +33 -0
  21. data/lib/mass_insert/version.rb +1 -1
  22. data/mass_insert.gemspec +2 -2
  23. data/spec/adapters/column_types/binary_spec.rb +64 -0
  24. data/spec/adapters/column_types/boolean_spec.rb +48 -0
  25. data/spec/adapters/column_types/decimal_spec.rb +59 -0
  26. data/spec/adapters/column_types/integer_spec.rb +59 -0
  27. data/spec/adapters/column_types/string_spec.rb +46 -0
  28. data/spec/{active_record_models → adapters}/model_spec.rb +1 -21
  29. data/spec/{active_record_dummy → dummy}/.gitignore +0 -0
  30. data/spec/{active_record_dummy → dummy}/Gemfile +1 -1
  31. data/spec/{active_record_dummy → dummy}/README.rdoc +0 -0
  32. data/spec/{active_record_dummy → dummy}/Rakefile +0 -0
  33. data/spec/{active_record_dummy → dummy}/app/assets/images/rails.png +0 -0
  34. data/spec/{active_record_dummy → dummy}/app/assets/javascripts/application.js +0 -0
  35. data/spec/{active_record_dummy → dummy}/app/assets/stylesheets/application.css +0 -0
  36. data/spec/{active_record_dummy → dummy}/app/controllers/application_controller.rb +0 -0
  37. data/spec/{active_record_dummy → dummy}/app/helpers/application_helper.rb +0 -0
  38. data/spec/{active_record_dummy → dummy}/app/mailers/.gitkeep +0 -0
  39. data/spec/{active_record_dummy → dummy}/app/models/.gitkeep +0 -0
  40. data/spec/{active_record_dummy → dummy}/app/models/user.rb +0 -0
  41. data/spec/{active_record_dummy → dummy}/app/views/layouts/application.html.erb +0 -0
  42. data/spec/{active_record_dummy → dummy}/config.ru +0 -0
  43. data/spec/{active_record_dummy → dummy}/config/application.rb +0 -0
  44. data/spec/{active_record_dummy → dummy}/config/boot.rb +0 -0
  45. data/spec/{active_record_dummy → dummy}/config/database.yml +3 -8
  46. data/spec/{active_record_dummy → dummy}/config/environment.rb +0 -0
  47. data/spec/{active_record_dummy → dummy}/config/environments/development.rb +0 -0
  48. data/spec/{active_record_dummy → dummy}/config/environments/mysql2.rb +0 -0
  49. data/spec/{active_record_dummy → dummy}/config/environments/postgresql.rb +0 -0
  50. data/spec/{active_record_dummy → dummy}/config/environments/production.rb +0 -0
  51. data/spec/{active_record_dummy → dummy}/config/environments/sqlite3.rb +0 -0
  52. data/spec/{active_record_dummy → dummy}/config/environments/test.rb +0 -0
  53. data/spec/{active_record_dummy → dummy}/config/initializers/backtrace_silencers.rb +0 -0
  54. data/spec/{active_record_dummy → dummy}/config/initializers/inflections.rb +0 -0
  55. data/spec/{active_record_dummy → dummy}/config/initializers/mime_types.rb +0 -0
  56. data/spec/{active_record_dummy → dummy}/config/initializers/secret_token.rb +0 -0
  57. data/spec/{active_record_dummy → dummy}/config/initializers/session_store.rb +0 -0
  58. data/spec/{active_record_dummy → dummy}/config/initializers/wrap_parameters.rb +0 -0
  59. data/spec/{active_record_dummy → dummy}/config/locales/en.yml +0 -0
  60. data/spec/{active_record_dummy → dummy}/config/routes.rb +0 -0
  61. data/spec/{active_record_dummy → dummy}/db/migrate/20130412154541_create_users.rb +0 -0
  62. data/spec/{active_record_dummy → dummy}/db/schema.rb +0 -0
  63. data/spec/{active_record_dummy → dummy}/db/seeds.rb +0 -0
  64. data/spec/{active_record_dummy → dummy}/lib/assets/.gitkeep +0 -0
  65. data/spec/{active_record_dummy → dummy}/lib/tasks/.gitkeep +0 -0
  66. data/spec/{active_record_dummy → dummy}/log/.gitkeep +0 -0
  67. data/spec/{active_record_dummy → dummy}/public/404.html +0 -0
  68. data/spec/{active_record_dummy → dummy}/public/422.html +0 -0
  69. data/spec/{active_record_dummy → dummy}/public/500.html +0 -0
  70. data/spec/{active_record_dummy → dummy}/public/favicon.ico +0 -0
  71. data/spec/{active_record_dummy → dummy}/public/index.html +0 -0
  72. data/spec/{active_record_dummy → dummy}/public/robots.txt +0 -0
  73. data/spec/{active_record_dummy → dummy}/script/rails +0 -0
  74. data/spec/{active_record_dummy → dummy}/vendor/assets/javascripts/.gitkeep +0 -0
  75. data/spec/{active_record_dummy → dummy}/vendor/assets/stylesheets/.gitkeep +0 -0
  76. data/spec/{active_record_dummy → dummy}/vendor/plugins/.gitkeep +0 -0
  77. data/spec/lib/mass_insert/base_spec.rb +40 -0
  78. data/spec/lib/mass_insert/builder/adapters/adapter_spec.rb +129 -0
  79. data/spec/lib/mass_insert/builder/adapters/helpers/abstract_query_spec.rb +130 -0
  80. data/spec/{mass_insert/adapters/adapter_helpers → lib/mass_insert/builder/adapters/helpers}/column_value_spec.rb +42 -94
  81. data/spec/lib/mass_insert/builder/adapters/mysql_adapter_spec.rb +15 -0
  82. data/spec/lib/mass_insert/builder/adapters/postgresql_adapter_spec.rb +9 -0
  83. data/spec/lib/mass_insert/builder/adapters/sqlite3_adapter_spec.rb +52 -0
  84. data/spec/lib/mass_insert/builder/adapters/sqlserver_adapter_spec.rb +38 -0
  85. data/spec/lib/mass_insert/builder/adapters_spec.rb +31 -0
  86. data/spec/lib/mass_insert/builder/base_spec.rb +28 -0
  87. data/spec/lib/mass_insert/builder/utilities_spec.rb +11 -0
  88. data/spec/lib/mass_insert/executer_spec.rb +33 -0
  89. data/spec/lib/mass_insert/process_spec.rb +44 -0
  90. data/spec/lib/mass_insert/result_spec.rb +45 -0
  91. data/spec/lib/mass_insert_spec.rb +35 -0
  92. data/spec/spec_helper.rb +7 -2
  93. data/spec/support/mass_insert_support.rb +12 -0
  94. metadata +160 -163
  95. data/lib/mass_insert/adapters.rb +0 -10
  96. data/lib/mass_insert/adapters/adapter.rb +0 -26
  97. data/lib/mass_insert/adapters/adapter_helpers.rb +0 -11
  98. data/lib/mass_insert/adapters/adapter_helpers/abstract_query.rb +0 -56
  99. data/lib/mass_insert/adapters/adapter_helpers/column_value.rb +0 -110
  100. data/lib/mass_insert/adapters/adapter_helpers/sanitizer.rb +0 -21
  101. data/lib/mass_insert/adapters/adapter_helpers/timestamp.rb +0 -33
  102. data/lib/mass_insert/adapters/mysql2_adapter.rb +0 -13
  103. data/lib/mass_insert/adapters/postgresql_adapter.rb +0 -5
  104. data/lib/mass_insert/adapters/sqlite3_adapter.rb +0 -37
  105. data/lib/mass_insert/adapters/sqlserver_adapter.rb +0 -29
  106. data/lib/mass_insert/process_control.rb +0 -46
  107. data/lib/mass_insert/query_builder.rb +0 -39
  108. data/lib/mass_insert/query_execution.rb +0 -29
  109. data/spec/active_record_models/column_types/binary_spec.rb +0 -60
  110. data/spec/active_record_models/column_types/boolean_spec.rb +0 -52
  111. data/spec/active_record_models/column_types/decimal_spec.rb +0 -49
  112. data/spec/active_record_models/column_types/integer_spec.rb +0 -49
  113. data/spec/active_record_models/column_types/string_spec.rb +0 -50
  114. data/spec/dummy_models/test.rb +0 -5
  115. data/spec/mass_insert/adapters/adapter_helpers/abstract_query_spec.rb +0 -119
  116. data/spec/mass_insert/adapters/adapter_helpers/sanitizer_spec.rb +0 -46
  117. data/spec/mass_insert/adapters/adapter_helpers/timestamp_spec.rb +0 -75
  118. data/spec/mass_insert/adapters/adapter_helpers_spec.rb +0 -24
  119. data/spec/mass_insert/adapters/adapter_spec.rb +0 -79
  120. data/spec/mass_insert/adapters/mysql_adapter_spec.rb +0 -22
  121. data/spec/mass_insert/adapters/postgresql_adapter_spec.rb +0 -11
  122. data/spec/mass_insert/adapters/sqlite3_adapter_spec.rb +0 -84
  123. data/spec/mass_insert/adapters/sqlserver_adapter_spec.rb +0 -61
  124. data/spec/mass_insert/adapters_spec.rb +0 -32
  125. data/spec/mass_insert/base_spec.rb +0 -114
  126. data/spec/mass_insert/process_control_spec.rb +0 -125
  127. data/spec/mass_insert/query_builder_spec.rb +0 -84
  128. data/spec/mass_insert/query_execution_spec.rb +0 -50
  129. data/spec/mass_insert_spec.rb +0 -28
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .rvmrc
19
+ .rspec
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
@@ -1,13 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in mass_insert.gemspec
4
3
  gemspec
5
4
 
6
5
  gem "rails", "3.2.13"
7
6
  gem "mysql2"
8
7
  gem "sqlite3"
9
8
  gem "pg"
10
-
11
9
  gem "rspec"
12
10
  gem "simplecov"
13
11
  gem "rake"
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, SQLite3 and SQLServer adapters.
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.84s
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. Only call the next methods from your model after MassInsert execution.
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. `build_time` : Returns the time that took to create the query string that was persisted.
70
- 4. `execute_time` : Returns the time that took to execute the query string that was persisted.
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
- :primary_key => :user_id,
79
- :primary_key_mode => :manual
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, :primary_key => :user_id, :primary_key_mode => :manual)
81
+ User.mass_insert(values, :option => value)
87
82
 
88
- Some options that you can include are...
83
+ Some options you can include are...
89
84
 
90
- **table_name**
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
- options = {:table_name => "users"}
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
- **primary_key**
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
- options = {:primary_key => :post_id}
91
+ **Each slice**
99
92
 
100
- **primary_key_mode**
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
- options = {:primary_key_mode => :manual}
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 "Prepares the environment to use the gem"
5
- task :prepare do
6
- system("
7
- bundle install
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
- desc "Runs all unit tests"
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
- desc "Runs all the Postgresql specs"
29
- task :postgresql do
30
- ENV["RAILS_ENV"] = "postgresql"
31
- system("echo '\e[00;32m\033[1mRunning the Postgresql adapter tests...\e[00m'")
32
- system("bundle exec rspec spec/active_record_models")
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 the Sqlite3 specs"
36
- task :sqlite3 do
37
- ENV["RAILS_ENV"] = "sqlite3"
38
- system("echo '\e[00;32m\033[1mRunning the Sqlite3 adapter tests...\e[00m'")
39
- system("bundle exec rspec spec/active_record_models")
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 :Adapters, 'mass_insert/adapters.rb'
5
- autoload :Base, 'mass_insert/base.rb'
6
- autoload :ProcessControl, 'mass_insert/process_control.rb'
7
- autoload :QueryBuilder, 'mass_insert/query_builder.rb'
8
- autoload :QueryExecution, 'mass_insert/query_execution.rb'
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)
@@ -3,93 +3,57 @@ module MassInsert
3
3
 
4
4
  # = MassInsert
5
5
  #
6
- # This method does a mass database insertion just calling it from your
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 with the object values in a hash.
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
- # And MassInset gem allow you to send it some options as second param
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
- # === table_name
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
- # options = {:primary_key => :post_id}
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
- # === primary_key_mode
29
+ # options = {:primary_key => true}
43
30
  #
44
- # Default value is :auto. When is :auto MassInsert knows that database
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
- # options = {:primary_key_mode => :manual}
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
- # When a class that inherit from ActiveRecord::Base calls this method
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
- # After extends the class with methods in ClassMethods module. The
56
- # options that were passed by params are sanitized in the method
57
- # called mass_insert_options to be passed by params to ProcessControl
58
- # class. The record values are passed too.
59
- def mass_insert values, args = {}
60
- class_eval do
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
- options = mass_insert_options(args)
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
- # Returns an OpenStruc instance where is possible to see the
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
- @mass_insert_process.results if @mass_insert_process
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