upsert 2.0.4 → 2.1.0
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 +4 -4
- data/.travis.yml +4 -0
- data/CHANGELOG +10 -0
- data/README.md +1 -3
- data/lib/upsert.rb +8 -1
- data/lib/upsert/merge_function.rb +1 -14
- data/lib/upsert/version.rb +1 -1
- data/spec/database_functions_spec.rb +49 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a8d49c15022e8faa065c2f060349210b28998b9
|
4
|
+
data.tar.gz: 3814d296ef548257347af887ca39a04b801ceb91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3a2553e8a0d143bb90592d1dc7f5a4ccd9224386fdce394dceef2ad2f46e186a853e61560ef1d6ea93f52b5bb7e948659c62398c60cc6c5d8c5887bdd9c6d0f
|
7
|
+
data.tar.gz: 864fcc5434d104ae1c4d5e8d68a8e8546217612be2d710b01a8ecfbd5e25435f2181a8c59afd7f6224b388762276f93256be6c7cec4ea5e18e994129ba1b396d
|
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
2.1.0 / 2015-03-13
|
2
|
+
|
3
|
+
* Bug fixes
|
4
|
+
|
5
|
+
* Thread safety with Sidekiq! thanks @evadne and @thbar ! https://github.com/seamusabshere/upsert/pull/47
|
6
|
+
|
7
|
+
* Known issues
|
8
|
+
|
9
|
+
* speed_spec fails against activerecord-import on mysql... need some advice on properly testing it
|
10
|
+
|
1
11
|
2.0.4 / 2015-01-27
|
2
12
|
|
3
13
|
* Bug fixes
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# Upsert
|
2
2
|
|
3
|
-
**note** There is a known problem with mysql2 and sidekiq - we're working on it in https://github.com/seamusabshere/upsert/tree/real_thread_safe and various issues
|
4
|
-
|
5
3
|
[](https://travis-ci.org/seamusabshere/upsert)
|
6
4
|
|
7
5
|
Make it easy to upsert on traditional RDBMS like MySQL, PostgreSQL, and SQLite3—hey look NoSQL!. Transparently creates (and re-uses) stored procedures/functions when necessary.
|
@@ -157,7 +155,7 @@ From the tests (updated 11/7/12):
|
|
157
155
|
Upsert was 82% faster than find + new/set/save
|
158
156
|
Upsert was 85% faster than find_or_create + update_attributes
|
159
157
|
Upsert was 90% faster than create + rescue/find/update
|
160
|
-
Upsert was 46% faster than faking upserts with activerecord-import
|
158
|
+
Upsert was 46% faster than faking upserts with activerecord-import (note: in question as of 3/13/15, need some expert advice)
|
161
159
|
|
162
160
|
#### SQL MERGE trick
|
163
161
|
|
data/lib/upsert.rb
CHANGED
@@ -194,6 +194,7 @@ class Upsert
|
|
194
194
|
end
|
195
195
|
@connection = Connection.const_get(adapter).new self, metal
|
196
196
|
@merge_function_class = MergeFunction.const_get adapter
|
197
|
+
@merge_function_cache = {}
|
197
198
|
@assume_function_exists = options.fetch :assume_function_exists, false
|
198
199
|
end
|
199
200
|
|
@@ -213,7 +214,8 @@ class Upsert
|
|
213
214
|
# upsert.row({:name => 'Jerry'}, :breed => 'beagle')
|
214
215
|
# upsert.row({:name => 'Pierre'}, :breed => 'tabby')
|
215
216
|
def row(selector, setter = {}, options = nil)
|
216
|
-
|
217
|
+
row_object = Row.new(selector, setter, options)
|
218
|
+
merge_function(row_object).execute(row_object)
|
217
219
|
nil
|
218
220
|
end
|
219
221
|
|
@@ -221,6 +223,11 @@ class Upsert
|
|
221
223
|
def clear_database_functions
|
222
224
|
merge_function_class.clear connection
|
223
225
|
end
|
226
|
+
|
227
|
+
def merge_function(row)
|
228
|
+
cache_key = [row.selector.keys, row.setter.keys]
|
229
|
+
@merge_function_cache[cache_key] ||= merge_function_class.new(self, row.selector.keys, row.setter.keys, assume_function_exists?)
|
230
|
+
end
|
224
231
|
|
225
232
|
# @private
|
226
233
|
def quoted_table_name
|
@@ -8,11 +8,6 @@ class Upsert
|
|
8
8
|
NAME_PREFIX = "upsert#{Upsert::VERSION.gsub('.', '_')}"
|
9
9
|
|
10
10
|
class << self
|
11
|
-
def execute(controller, row)
|
12
|
-
merge_function = lookup controller, row
|
13
|
-
merge_function.execute row
|
14
|
-
end
|
15
|
-
|
16
11
|
def unique_name(table_name, selector_keys, setter_keys)
|
17
12
|
parts = [
|
18
13
|
NAME_PREFIX,
|
@@ -30,14 +25,6 @@ class Upsert
|
|
30
25
|
parts
|
31
26
|
end
|
32
27
|
end
|
33
|
-
|
34
|
-
def lookup(controller, row)
|
35
|
-
@lookup ||= {}
|
36
|
-
selector_keys = row.selector.keys
|
37
|
-
setter_keys = row.setter.keys
|
38
|
-
key = [controller.table_name, selector_keys, setter_keys]
|
39
|
-
@lookup[key] ||= new(controller, selector_keys, setter_keys, controller.assume_function_exists?)
|
40
|
-
end
|
41
28
|
end
|
42
29
|
|
43
30
|
attr_reader :controller
|
@@ -53,7 +40,7 @@ class Upsert
|
|
53
40
|
end
|
54
41
|
|
55
42
|
def name
|
56
|
-
@name ||=
|
43
|
+
@name ||= self.class.unique_name table_name, selector_keys, setter_keys
|
57
44
|
end
|
58
45
|
|
59
46
|
def connection
|
data/lib/upsert/version.rb
CHANGED
@@ -2,27 +2,43 @@ require 'spec_helper'
|
|
2
2
|
require 'stringio'
|
3
3
|
describe Upsert do
|
4
4
|
describe 'database functions' do
|
5
|
-
|
6
|
-
it "re-uses merge functions across connections" do
|
5
|
+
it "does not re-use merge functions across connections" do
|
7
6
|
begin
|
8
7
|
io = StringIO.new
|
9
8
|
old_logger = Upsert.logger
|
10
9
|
Upsert.logger = Logger.new io, Logger::INFO
|
11
10
|
|
12
|
-
# clear
|
11
|
+
# clear, create (#1)
|
13
12
|
Upsert.clear_database_functions($conn_factory.new_connection)
|
14
|
-
|
15
|
-
# create
|
16
13
|
Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
|
17
14
|
|
18
|
-
# clear
|
15
|
+
# clear, create (#2)
|
19
16
|
Upsert.clear_database_functions($conn_factory.new_connection)
|
20
|
-
|
21
|
-
# create (#2)
|
22
17
|
Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
|
18
|
+
|
19
|
+
io.rewind
|
20
|
+
hits = io.read.split("\n").grep(/Creating or replacing/)
|
21
|
+
hits.length.should == 2
|
22
|
+
ensure
|
23
|
+
Upsert.logger = old_logger
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "does not re-use merge functions even when on the same connection" do
|
28
|
+
begin
|
29
|
+
io = StringIO.new
|
30
|
+
old_logger = Upsert.logger
|
31
|
+
Upsert.logger = Logger.new io, Logger::INFO
|
32
|
+
|
33
|
+
connection = $conn_factory.new_connection
|
23
34
|
|
24
|
-
#
|
25
|
-
Upsert.
|
35
|
+
# clear, create (#1)
|
36
|
+
Upsert.clear_database_functions(connection)
|
37
|
+
Upsert.new(connection, :pets).row :name => 'hello'
|
38
|
+
|
39
|
+
# clear, create (#2)
|
40
|
+
Upsert.clear_database_functions(connection)
|
41
|
+
Upsert.new(connection, :pets).row :name => 'hello'
|
26
42
|
|
27
43
|
io.rewind
|
28
44
|
hits = io.read.split("\n").grep(/Creating or replacing/)
|
@@ -31,6 +47,29 @@ describe Upsert do
|
|
31
47
|
Upsert.logger = old_logger
|
32
48
|
end
|
33
49
|
end
|
50
|
+
|
51
|
+
it "re-uses merge functions within batch" do
|
52
|
+
begin
|
53
|
+
io = StringIO.new
|
54
|
+
old_logger = Upsert.logger
|
55
|
+
Upsert.logger = Logger.new io, Logger::INFO
|
56
|
+
|
57
|
+
# clear
|
58
|
+
Upsert.clear_database_functions($conn_factory.new_connection)
|
59
|
+
|
60
|
+
# create
|
61
|
+
Upsert.batch($conn_factory.new_connection, :pets) do |upsert|
|
62
|
+
upsert.row :name => 'hello'
|
63
|
+
upsert.row :name => 'world'
|
64
|
+
end
|
65
|
+
|
66
|
+
io.rewind
|
67
|
+
hits = io.read.split("\n").grep(/Creating or replacing/)
|
68
|
+
hits.length.should == 1
|
69
|
+
ensure
|
70
|
+
Upsert.logger = old_logger
|
71
|
+
end
|
72
|
+
end
|
34
73
|
|
35
74
|
it "assumes function exists if told to" do
|
36
75
|
begin
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: upsert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seamus Abshere
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|