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.
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