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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e403ffd510814ad862057a3059f8ce8e65d974d4
4
- data.tar.gz: 142ba5495b4d63641f23b1e54ab2c855a9f858d9
3
+ metadata.gz: 8a8d49c15022e8faa065c2f060349210b28998b9
4
+ data.tar.gz: 3814d296ef548257347af887ca39a04b801ceb91
5
5
  SHA512:
6
- metadata.gz: d4ad43d341e5fefbecac30c296f4dc6956e4e513a68e1aca95ea0026017ce882849b59144282cc9ac82f7eabea5bfc9297a134b7f3b6320b9ad717be180d977d
7
- data.tar.gz: 3bec3b12605a00058fb654d718baa5cc6adef91ea8e1b6931e22248a3f45f1a3652db43183923346516675edf4ff0269d3a0122199ac941784851c996d6f0583
6
+ metadata.gz: e3a2553e8a0d143bb90592d1dc7f5a4ccd9224386fdce394dceef2ad2f46e186a853e61560ef1d6ea93f52b5bb7e948659c62398c60cc6c5d8c5887bdd9c6d0f
7
+ data.tar.gz: 864fcc5434d104ae1c4d5e8d68a8e8546217612be2d710b01a8ecfbd5e25435f2181a8c59afd7f6224b388762276f93256be6c7cec4ea5e18e994129ba1b396d
@@ -3,9 +3,13 @@ global:
3
3
  - USERNAME=travis
4
4
  PASSWORD=
5
5
  rvm:
6
+ - 2.2.0
7
+ - 2.1.0
8
+ - 2.0.0
6
9
  - 1.9.3
7
10
  - 1.9.2
8
11
  - 1.8.7
12
+ - rbx-2
9
13
  env:
10
14
  - DB=postgresql
11
15
  - DB=mysql
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
  [![Build Status](https://travis-ci.org/seamusabshere/upsert.svg?branch=master)](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
 
@@ -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
- merge_function_class.execute self, Row.new(selector, setter, options)
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 ||= MergeFunction.unique_name table_name, selector_keys, setter_keys
43
+ @name ||= self.class.unique_name table_name, selector_keys, setter_keys
57
44
  end
58
45
 
59
46
  def connection
@@ -1,3 +1,3 @@
1
1
  class Upsert
2
- VERSION = '2.0.4'
2
+ VERSION = '2.1.0'
3
3
  end
@@ -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
- # no create!
25
- Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
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
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-01-27 00:00:00.000000000 Z
11
+ date: 2015-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-core