tachyon 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -24
- data/lib/tachyon.rb +54 -16
- data/lib/tachyon/version.rb +1 -1
- data/tachyon.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e508417f45cc19402918a4a554f8928cd43919d
|
4
|
+
data.tar.gz: 0f97c7354af65aebbd184ee4f85eb735eb841a01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e1a77ae53773d6c6e7d0aaa81765bf8ede459dfca2cd06120402c8314cade4e7f73e33c4e85149913c5e7304a41bc7a630f6f2ce51a69d74a28287686f0f8dc
|
7
|
+
data.tar.gz: 177c88d41f2809cfd356d4ada6acd192101c28943425d5431d1d337dce1d688c6338a9862ac9ab318a53af9d66bb02d7d7d8dbc63f43fc45c4284ef501386465
|
data/README.md
CHANGED
@@ -1,41 +1,43 @@
|
|
1
1
|
# Tachyon
|
2
2
|
|
3
|
-
Tachyon is a simple library designed to insert rows into any DB managed by ActiveRecord as fast as possible. Tachyon does not do validations
|
4
|
-
|
5
|
-
Tachyon is roughly as fast as executing raw SQL statements, but with a much more readable syntax. Tachyon uses Arel to geneate the SQL statements and to manage type-casting, this helps to avoid the fragility that can come with manually generating SQL.
|
3
|
+
Tachyon is a simple library designed to insert rows into any DB managed by ActiveRecord as fast as possible. Tachyon does not do validations, and only does minimal typescasting. Tachyon simply gets records into the DB as fast as possible. This is very useful in the case when you need to bulk-insert data for some reason, but it really shouldn't be used to replace your normal ActiveRecord DB operations.
|
6
4
|
|
7
5
|
## How fast is it?
|
8
6
|
|
9
|
-
|
7
|
+
Tachyon is as fast (or faster) than executing raw SQL via `ActiveRecord::Base.connection`:
|
10
8
|
|
11
9
|
```
|
12
|
-
Benchmark Results (
|
13
|
-
|
14
|
-
User.create()
|
15
|
-
Raw SQL
|
16
|
-
Tachyon.insert(User, Hash)
|
17
|
-
Tachyon.insert(User, Array) : 1.078880 secs
|
10
|
+
Benchmark Results (Inserting 10,000 rows):
|
11
|
+
------------------------------------------------
|
12
|
+
User.create(Hash) : 7.72 seconds
|
13
|
+
Raw SQL (w/ string interpolation) : 1.01 seconds
|
14
|
+
Tachyon.insert(User, Hash) : 1.00 seconds
|
18
15
|
```
|
19
16
|
|
20
|
-
##
|
17
|
+
## Features
|
21
18
|
|
22
|
-
|
19
|
+
* As fast (or faster!) than generating SQL via string interpolation, but with a much nicer syntax!
|
20
|
+
* Suppresses duplicate key errors, which makes life easier when doing bulk data imports
|
21
|
+
* Allows you to dump records from the database in a useful format via `Tachyon.dump_record`
|
22
|
+
* Compatible with MySQL, PostgreSQL and SQLite3
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
## Caveats
|
25
|
+
|
26
|
+
* Tachyon does not perform validations
|
27
|
+
* Tachyon only does minimal typecasting
|
28
|
+
|
29
|
+
## Typecasting
|
27
30
|
|
28
|
-
|
31
|
+
Tachyon does extremely minimal typecasting. Integers and Floats are passed through as literals, nils are converted to NULLs, pretty much all other types should be supplied as strings where appropriate.
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Simply supply the model class along with a hash of attributes:
|
29
36
|
|
30
37
|
```ruby
|
31
|
-
Tachyon.insert(
|
32
|
-
{id: 1, article_id: 34, title: "Super comment"},
|
33
|
-
{id: 2, article_id: 12, title: "Another one"},
|
34
|
-
{id: 3, article_id: 90, title: "Comment duex"},
|
35
|
-
])
|
38
|
+
Tachyon.insert(Article, id: 13, title: "Brand new article")
|
36
39
|
```
|
37
40
|
|
38
|
-
|
39
41
|
## Installation
|
40
42
|
|
41
43
|
Add this line to your application's Gemfile:
|
@@ -52,8 +54,6 @@ Or install it yourself as:
|
|
52
54
|
|
53
55
|
$ gem install tachyon
|
54
56
|
|
55
|
-
|
56
|
-
|
57
57
|
## License
|
58
58
|
|
59
59
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/tachyon.rb
CHANGED
@@ -1,29 +1,67 @@
|
|
1
1
|
require "tachyon/version"
|
2
2
|
|
3
3
|
class Tachyon
|
4
|
+
|
5
|
+
@@sql_cache = {}
|
6
|
+
@@connection_cache = {}
|
7
|
+
|
4
8
|
def self.insert(klass, data)
|
5
|
-
|
6
|
-
|
9
|
+
self.connection_for(klass).execute(self.sql_for(klass, data))
|
10
|
+
rescue ActiveRecord::RecordNotUnique
|
11
|
+
# NO OP
|
12
|
+
end
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
self.insert_record(klass, data)
|
12
|
-
end
|
14
|
+
def self.connection_for(klass)
|
15
|
+
return @@connection_cache[klass] if @@connection_cache.has_key?(klass)
|
16
|
+
@@connection_cache[klass] = klass.connection
|
13
17
|
end
|
14
18
|
|
15
|
-
def self.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
def self.sql_for(klass, data)
|
20
|
+
self.sql_template_for(klass) % self.quote_data(data)
|
21
|
+
rescue KeyError => e
|
22
|
+
raise "Data was not supplied for all columns - " + e.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.sql_template_for(klass)
|
26
|
+
return @@sql_cache[klass] if @@sql_cache.has_key?(klass)
|
27
|
+
|
28
|
+
columns = klass.columns.map(&:name)
|
29
|
+
table_name = klass.table_name
|
30
|
+
columns_string = columns.map {|x| "`#{x}`" }.join(", ")
|
31
|
+
values_string = columns.map {|x| "%{#{x}}" }.join(", ")
|
32
|
+
|
33
|
+
sql = "INSERT INTO `#{table_name}` (#{columns_string}) VALUES (#{values_string})"
|
34
|
+
|
35
|
+
@@sql_cache[klass] = sql
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.quote_data(data)
|
39
|
+
data.map do |key, value|
|
40
|
+
[key, self.quote_value(value)]
|
41
|
+
end.to_h
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.quote_value(value)
|
45
|
+
case value
|
46
|
+
when String then "'#{value.gsub("'", "''")}'"
|
47
|
+
when NilClass then "NULL"
|
48
|
+
else value
|
19
49
|
end
|
20
50
|
end
|
21
51
|
|
22
|
-
def self.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
52
|
+
def self.dump_record(record)
|
53
|
+
record.attributes_before_type_cast.map do |key, value|
|
54
|
+
[key.to_sym, self.dump_attribute(value)]
|
55
|
+
end.to_h
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.dump_attribute(attribute)
|
59
|
+
case attribute
|
60
|
+
when Time then attribute.to_s(:db)
|
61
|
+
when Date then attribute.to_s(:db)
|
62
|
+
when TrueClass then 1
|
63
|
+
when FalseClass then 0
|
64
|
+
else attribute
|
27
65
|
end
|
28
66
|
end
|
29
67
|
end
|
data/lib/tachyon/version.rb
CHANGED
data/tachyon.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tachyon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Gough
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ruby-prof
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
description: Create records in a DB managed by ActiveRecord as fast as possible.
|
98
112
|
email:
|
99
113
|
- aaron@aarongough.com
|