bulk-insert-active-record 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|