bulk-insert-active-record 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-gemset +1 -0
- data/Gemfile +3 -0
- data/README.md +39 -0
- data/Rakefile +1 -0
- data/bulk-insert-active-record.gemspec +22 -0
- data/lib/bulk-insert-active-record.rb +45 -0
- data/lib/inserters.rb +16 -0
- data/lib/inserters/base.rb +36 -0
- data/lib/inserters/oracle.rb +16 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 50a047ec99ae044e95e2ece35f7ed6a98f774369
|
4
|
+
data.tar.gz: c81b2276e7d97ba319cbfed840c28eff00b0db12
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6bf3fca5d20ee03cbc94ea6de6de28e7940074c17106ecc36eb8ebbb0a31e63d96debcb3a46456055591e768e3b5e024a84abd6a4f0f91dacedbd8cf7a39b14a
|
7
|
+
data.tar.gz: 72bad9ef5d4e3ca8f1990fd95ccaad3c4ea7bd2984fcc48c1a3e704a5c46b67e348426c333941a1b0c9c65ccb8cd3a00172d8d3363d193eae6dfed391a6dda2a
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bulk-insert-active-record
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Bulk Insert Active Record (for ActiveRecord 3 or higher)
|
2
|
+
|
3
|
+
This gem extends Active Record and allows you to insert multiple records in one SQL statement,
|
4
|
+
dramatically increasing performance.
|
5
|
+
|
6
|
+
## Current status
|
7
|
+
|
8
|
+
This gem is currently actively in development, but because it's already useful, I've decided to
|
9
|
+
publish it in its premature state. Right now it has been manually tested with MySQL and SQL Server
|
10
|
+
via JDBC.
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Installation is done by adding the gem your *Gemfile* and running Bundler. After loading Active
|
15
|
+
Record an extra class method is available for your models.
|
16
|
+
|
17
|
+
## Examples
|
18
|
+
|
19
|
+
Suppose you want to insert multiple Post records in the database. This can be done in different
|
20
|
+
ways:
|
21
|
+
|
22
|
+
# suppose it has 3 columns (`id`, `author` and `text`)
|
23
|
+
class Post < ActiveRecord::Base
|
24
|
+
end
|
25
|
+
|
26
|
+
# create an array of arrays
|
27
|
+
posts = [
|
28
|
+
# author, # text
|
29
|
+
['John Doe', 'An article about me'],
|
30
|
+
['John Smith', 'Something interesting']
|
31
|
+
]
|
32
|
+
|
33
|
+
# call class method bulk_insert with two arguments (the posts and the column names)
|
34
|
+
Post.bulk_insert(posts, ['author', 'name])
|
35
|
+
|
36
|
+
|
37
|
+
# Copyright
|
38
|
+
|
39
|
+
© 2014 Walter Horstman, [IT on Rails](http://itonrails.com)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'bulk-insert-active-record'
|
7
|
+
spec.summary = 'Lightweight bulk insert mechanism for ActiveRecord 3 or higher'
|
8
|
+
spec.description = 'This gem allows you to insert multiple rows as once, dramatically increasing performance.'
|
9
|
+
spec.version = '0.0.1'
|
10
|
+
spec.required_ruby_version = '>= 1.9.2'
|
11
|
+
|
12
|
+
spec.author = 'Walter Horstman'
|
13
|
+
spec.email = 'walter.horstman@itonrails.com'
|
14
|
+
spec.homepage = 'https://github.com/walterhorstman/bulk-insert-active-record'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_path = 'lib'
|
20
|
+
|
21
|
+
spec.add_dependency('activerecord', '>= 3')
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative('inserters')
|
2
|
+
|
3
|
+
module BulkInsertActiveRecord
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
|
8
|
+
def self.bulk_insert(records, column_names = self.column_names)
|
9
|
+
fail('No connection with the database') unless self.connection.active?
|
10
|
+
|
11
|
+
inserter = Inserters::factory(self)
|
12
|
+
self.transaction do
|
13
|
+
if inserter.nil?
|
14
|
+
self.insert_one_by_one(records, column_names)
|
15
|
+
else
|
16
|
+
sql = inserter.statement(records, column_names)
|
17
|
+
self.connection.insert(sql)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def self.insert_one_by_one(records, column_names)
|
25
|
+
self.transaction do
|
26
|
+
records.each do |record|
|
27
|
+
if record.is_a?(self)
|
28
|
+
record.save
|
29
|
+
else
|
30
|
+
item = self.new
|
31
|
+
column_names.each_with_index do |column_name, index|
|
32
|
+
item[column_name] = record[index]
|
33
|
+
end
|
34
|
+
item.save
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
ActiveSupport.on_load(:active_record) do
|
44
|
+
include(BulkInsertActiveRecord)
|
45
|
+
end
|
data/lib/inserters.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Dir[File.expand_path('../inserters/*.rb', __FILE__)].each { |file_name| require(file_name) }
|
2
|
+
|
3
|
+
module BulkInsertActiveRecord
|
4
|
+
module Inserters
|
5
|
+
|
6
|
+
def self.factory(active_record_class, options = {})
|
7
|
+
inserter_class = case active_record_class.connection.adapter_name.downcase
|
8
|
+
when 'mssql', 'mysql', 'sqlserver' then Base
|
9
|
+
when 'oracle' then Oracle
|
10
|
+
else nil
|
11
|
+
end
|
12
|
+
|
13
|
+
inserter_class.nil? ? nil : inserter_class.new(active_record_class, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This base implementation works for MySQL and SQLServer
|
2
|
+
module BulkInsertActiveRecord
|
3
|
+
module Inserters
|
4
|
+
class Base
|
5
|
+
|
6
|
+
def initialize(active_record_class, options = {})
|
7
|
+
@connection = active_record_class.connection
|
8
|
+
@quoted_table_name = active_record_class.quoted_table_name
|
9
|
+
|
10
|
+
# basic bulk insert statement
|
11
|
+
@statement = options[:statement] || 'INSERT INTO %{table_name}(%{columns_clause}) VALUES %{values_clause}'
|
12
|
+
# character(s) used to separate columns in the columns_clause of the statement
|
13
|
+
@column_separator = options[:column_separator] || ','
|
14
|
+
# character(s) used to separate records in the values_clause of the statement
|
15
|
+
@record_separator = options[:record_separator] || ','
|
16
|
+
# sql fragment for individual records in the values_clause of the statement
|
17
|
+
@record_statement = options[:record_statement] || '(%{value_clause})'
|
18
|
+
# character(s) used to separate values in the value_clause of the record statement
|
19
|
+
@value_separator = options[:value_separator] || ','
|
20
|
+
end
|
21
|
+
|
22
|
+
# returns bulk insert statement
|
23
|
+
def statement(records, column_names)
|
24
|
+
@statement % {
|
25
|
+
table_name: @quoted_table_name,
|
26
|
+
columns_clause: column_names.map { |column_name| @connection.quote_column_name(column_name) }.join(@column_separator),
|
27
|
+
values_clause: records.map do |record|
|
28
|
+
@record_statement % {
|
29
|
+
value_clause: record.map { |value| @connection.quote(value) }.join(@value_separator)
|
30
|
+
}
|
31
|
+
end.join(@record_separator)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative('base')
|
2
|
+
|
3
|
+
module BulkInsertActiveRecord
|
4
|
+
module Inserters
|
5
|
+
class Oracle < Base
|
6
|
+
|
7
|
+
def initialize(active_record_class, options = {})
|
8
|
+
super(active_record_class, {
|
9
|
+
statement: 'INSERT INTO %{table_name}(%{columns_clause}) %{values_clause}',
|
10
|
+
record_statement: 'SELECT %{value_clause} FROM dual',
|
11
|
+
record_separator: ' UNION '
|
12
|
+
}.merge(options))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bulk-insert-active-record
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Walter Horstman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3'
|
27
|
+
description: This gem allows you to insert multiple rows as once, dramatically increasing
|
28
|
+
performance.
|
29
|
+
email: walter.horstman@itonrails.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- ".ruby-gemset"
|
36
|
+
- Gemfile
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- bulk-insert-active-record.gemspec
|
40
|
+
- lib/bulk-insert-active-record.rb
|
41
|
+
- lib/inserters.rb
|
42
|
+
- lib/inserters/base.rb
|
43
|
+
- lib/inserters/oracle.rb
|
44
|
+
homepage: https://github.com/walterhorstman/bulk-insert-active-record
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.9.2
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.2.2
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Lightweight bulk insert mechanism for ActiveRecord 3 or higher
|
67
|
+
test_files: []
|