upsert 2.1.0 → 2.9.10
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 +5 -5
- data/.ruby-version +1 -0
- data/.standard.yml +1 -0
- data/.travis.yml +60 -12
- data/CHANGELOG +39 -0
- data/Gemfile +12 -1
- data/LICENSE +3 -1
- data/README.md +47 -6
- data/Rakefile +7 -1
- data/lib/upsert.rb +54 -11
- data/lib/upsert/column_definition/mysql.rb +2 -2
- data/lib/upsert/column_definition/postgresql.rb +9 -8
- data/lib/upsert/column_definition/sqlite3.rb +3 -3
- data/lib/upsert/connection/Java_ComMysqlJdbc_JDBC4Connection.rb +11 -5
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc_PgConnection.rb +33 -0
- data/lib/upsert/connection/PG_Connection.rb +10 -1
- data/lib/upsert/connection/jdbc.rb +20 -1
- data/lib/upsert/connection/postgresql.rb +2 -3
- data/lib/upsert/merge_function.rb +5 -4
- data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc_PgConnection.rb +27 -0
- data/lib/upsert/merge_function/PG_Connection.rb +11 -42
- data/lib/upsert/merge_function/postgresql.rb +215 -1
- data/lib/upsert/merge_function/sqlite3.rb +10 -0
- data/lib/upsert/version.rb +1 -1
- data/spec/active_record_upsert_spec.rb +10 -0
- data/spec/correctness_spec.rb +34 -5
- data/spec/database_functions_spec.rb +16 -9
- data/spec/database_spec.rb +7 -0
- data/spec/hstore_spec.rb +56 -55
- data/spec/jruby_spec.rb +9 -0
- data/spec/logger_spec.rb +8 -6
- data/spec/postgresql_spec.rb +94 -0
- data/spec/reserved_words_spec.rb +21 -17
- data/spec/sequel_spec.rb +26 -7
- data/spec/spec_helper.rb +251 -92
- data/spec/speed_spec.rb +3 -32
- data/spec/threaded_spec.rb +35 -12
- data/spec/type_safety_spec.rb +2 -1
- data/travis/install_postgres.sh +18 -0
- data/travis/run_docker_db.sh +20 -0
- data/travis/tune_mysql.sh +7 -0
- data/upsert-java.gemspec +13 -0
- data/upsert.gemspec +9 -57
- data/upsert.gemspec.common +107 -0
- metadata +53 -40
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -15
- data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -39
@@ -2,6 +2,16 @@ class Upsert
|
|
2
2
|
class MergeFunction
|
3
3
|
# @private
|
4
4
|
module Sqlite3
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def clear(*)
|
11
|
+
# not necessary
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
attr_reader :quoted_setter_names
|
6
16
|
attr_reader :quoted_update_names
|
7
17
|
attr_reader :quoted_selector_names
|
data/lib/upsert/version.rb
CHANGED
@@ -11,6 +11,16 @@ describe Upsert do
|
|
11
11
|
Pet.upsert({:name => 'Jerry'}, :good => true)
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
it "doesn't fail inside a transaction" do
|
16
|
+
Upsert.clear_database_functions(Pet.connection)
|
17
|
+
expect {
|
18
|
+
Pet.transaction do
|
19
|
+
Pet.upsert({name: 'Simba'}, good: true)
|
20
|
+
end
|
21
|
+
}.to_not raise_error
|
22
|
+
expect(Pet.first.name).to eq('Simba')
|
23
|
+
end
|
14
24
|
end
|
15
25
|
end
|
16
26
|
end
|
data/spec/correctness_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
describe Upsert do
|
3
5
|
describe 'clever correctness' do
|
@@ -11,7 +13,8 @@ describe Upsert do
|
|
11
13
|
u = Upsert.new($conn, :pets)
|
12
14
|
selector = {:name => 'Jerry', :tag_number => 6}
|
13
15
|
u.row(selector)
|
14
|
-
|
16
|
+
p.reload.tag_number.should == 5
|
17
|
+
next
|
15
18
|
|
16
19
|
# won't change anything because selector is wrong
|
17
20
|
u = Upsert.new($conn, :pets)
|
@@ -78,6 +81,18 @@ describe Upsert do
|
|
78
81
|
end
|
79
82
|
end
|
80
83
|
|
84
|
+
it "works with utf-8 data" do
|
85
|
+
u = Upsert.new($conn, :pets)
|
86
|
+
records = [
|
87
|
+
{:name => '你好', :home_address => '人'},
|
88
|
+
{:name => 'Здравствуйте', :home_address => 'человек'},
|
89
|
+
{:name => '😀', :home_address => '😂'},
|
90
|
+
]
|
91
|
+
assert_creates(Pet, records) do
|
92
|
+
records.each { |rec| u.row(rec) }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
81
96
|
it "tells you if you request a column that doesn't exist" do
|
82
97
|
u = Upsert.new($conn, :pets)
|
83
98
|
lambda { u.row(:gibberish => 'ba') }.should raise_error(/invalid col/i)
|
@@ -86,6 +101,15 @@ describe Upsert do
|
|
86
101
|
lambda { u.row(:name => 'Jerry', :gibberish => 'ba', :gender => 'male') }.should raise_error(/invalid col/i)
|
87
102
|
end
|
88
103
|
|
104
|
+
it "works with a long setter hash" do
|
105
|
+
Upsert.batch($conn, :alphabets) do |batch|
|
106
|
+
10_000.times do |time|
|
107
|
+
setter = Hash[("a".."z").map { |letter| ["the_letter_#{letter}".to_sym, rand(100)] }]
|
108
|
+
selector = Hash[("a".."z").map { |letter| ["the_letter_#{letter}".to_sym, rand(100)] }]
|
109
|
+
batch.row(setter, selector)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
89
113
|
end
|
90
114
|
|
91
115
|
describe "is just as correct as other ways" do
|
@@ -93,8 +117,8 @@ describe Upsert do
|
|
93
117
|
it "is as correct as than new/set/save" do
|
94
118
|
assert_same_result lotsa_records do |records|
|
95
119
|
records.each do |selector, setter|
|
96
|
-
if pet = Pet.where(selector).first
|
97
|
-
pet.update_attributes
|
120
|
+
if (pet = Pet.where(selector).first)
|
121
|
+
pet.update_attributes(setter)
|
98
122
|
else
|
99
123
|
pet = Pet.new
|
100
124
|
selector.each do |k, v|
|
@@ -134,12 +158,15 @@ describe Upsert do
|
|
134
158
|
# end
|
135
159
|
end
|
136
160
|
|
137
|
-
if ENV['DB'] == 'mysql' &&
|
161
|
+
if ENV['DB'] == 'mysql' || (UNIQUE_CONSTRAINT && ENV["DB"] == "postgresql")
|
138
162
|
describe 'compared to activerecord-import' do
|
139
163
|
it "is as correct as faking upserts with activerecord-import" do
|
140
164
|
assert_same_result lotsa_records do |records|
|
141
165
|
columns = nil
|
142
166
|
all_values = []
|
167
|
+
# Reverse because we want to mimic an 'overwrite' of previous values
|
168
|
+
records = records.reverse.uniq { |s, _| s } if ENV['DB'] == "postgresql"
|
169
|
+
|
143
170
|
records.each do |selector, setter|
|
144
171
|
columns ||= (selector.keys + setter.keys).uniq
|
145
172
|
all_values << columns.map do |k|
|
@@ -151,7 +178,9 @@ describe Upsert do
|
|
151
178
|
end
|
152
179
|
end
|
153
180
|
end
|
154
|
-
|
181
|
+
|
182
|
+
conflict_update = ENV['DB'] == "postgresql" ? {conflict_target: records.first.first.keys, columns: columns} : columns
|
183
|
+
Pet.import columns, all_values, :timestamps => false, :on_duplicate_key_update => conflict_update
|
155
184
|
end
|
156
185
|
end
|
157
186
|
end
|
@@ -1,7 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'stringio'
|
3
|
+
require 'upsert/merge_function/postgresql'
|
4
|
+
|
3
5
|
describe Upsert do
|
4
6
|
describe 'database functions' do
|
7
|
+
version = 'postgresql' == ENV['DB'] ? Upsert::MergeFunction::Postgresql.extract_version(
|
8
|
+
Pet.connection.select_value("SHOW server_version")
|
9
|
+
) : 0
|
10
|
+
before(:each) {
|
11
|
+
skip "Not using DB functions" if 'postgresql' == ENV['DB'] && UNIQUE_CONSTRAINT && version >= 90500
|
12
|
+
}
|
5
13
|
it "does not re-use merge functions across connections" do
|
6
14
|
begin
|
7
15
|
io = StringIO.new
|
@@ -15,7 +23,7 @@ describe Upsert do
|
|
15
23
|
# clear, create (#2)
|
16
24
|
Upsert.clear_database_functions($conn_factory.new_connection)
|
17
25
|
Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
|
18
|
-
|
26
|
+
|
19
27
|
io.rewind
|
20
28
|
hits = io.read.split("\n").grep(/Creating or replacing/)
|
21
29
|
hits.length.should == 2
|
@@ -23,13 +31,13 @@ describe Upsert do
|
|
23
31
|
Upsert.logger = old_logger
|
24
32
|
end
|
25
33
|
end
|
26
|
-
|
34
|
+
|
27
35
|
it "does not re-use merge functions even when on the same connection" do
|
28
36
|
begin
|
29
37
|
io = StringIO.new
|
30
38
|
old_logger = Upsert.logger
|
31
39
|
Upsert.logger = Logger.new io, Logger::INFO
|
32
|
-
|
40
|
+
|
33
41
|
connection = $conn_factory.new_connection
|
34
42
|
|
35
43
|
# clear, create (#1)
|
@@ -39,7 +47,7 @@ describe Upsert do
|
|
39
47
|
# clear, create (#2)
|
40
48
|
Upsert.clear_database_functions(connection)
|
41
49
|
Upsert.new(connection, :pets).row :name => 'hello'
|
42
|
-
|
50
|
+
|
43
51
|
io.rewind
|
44
52
|
hits = io.read.split("\n").grep(/Creating or replacing/)
|
45
53
|
hits.length.should == 2
|
@@ -47,7 +55,7 @@ describe Upsert do
|
|
47
55
|
Upsert.logger = old_logger
|
48
56
|
end
|
49
57
|
end
|
50
|
-
|
58
|
+
|
51
59
|
it "re-uses merge functions within batch" do
|
52
60
|
begin
|
53
61
|
io = StringIO.new
|
@@ -56,13 +64,13 @@ describe Upsert do
|
|
56
64
|
|
57
65
|
# clear
|
58
66
|
Upsert.clear_database_functions($conn_factory.new_connection)
|
59
|
-
|
67
|
+
|
60
68
|
# create
|
61
69
|
Upsert.batch($conn_factory.new_connection, :pets) do |upsert|
|
62
70
|
upsert.row :name => 'hello'
|
63
71
|
upsert.row :name => 'world'
|
64
72
|
end
|
65
|
-
|
73
|
+
|
66
74
|
io.rewind
|
67
75
|
hits = io.read.split("\n").grep(/Creating or replacing/)
|
68
76
|
hits.length.should == 1
|
@@ -79,7 +87,7 @@ describe Upsert do
|
|
79
87
|
|
80
88
|
# clear
|
81
89
|
Upsert.clear_database_functions($conn_factory.new_connection)
|
82
|
-
|
90
|
+
|
83
91
|
# tries, "went missing", creates
|
84
92
|
Upsert.new($conn_factory.new_connection, :pets, :assume_function_exists => true).row :name => 'hello'
|
85
93
|
|
@@ -94,6 +102,5 @@ describe Upsert do
|
|
94
102
|
Upsert.logger = old_logger
|
95
103
|
end
|
96
104
|
end
|
97
|
-
|
98
105
|
end
|
99
106
|
end if %w{ postgresql mysql }.include?(ENV['DB'])
|
data/spec/database_spec.rb
CHANGED
@@ -83,6 +83,13 @@ describe Upsert do
|
|
83
83
|
upsert.row({:id => jerry.id}, :gender => :male)
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
it "works for column names with spaces in them" do
|
88
|
+
upsert = Upsert.new $conn, :people
|
89
|
+
assert_creates(Person, [{:"First Name" => 'Major', :"Last Name" => 'Major'}]) do
|
90
|
+
upsert.row({:"First Name" => 'Major'}, :"Last Name" => 'Major')
|
91
|
+
end
|
92
|
+
end
|
86
93
|
end
|
87
94
|
describe :batch do
|
88
95
|
it "works for multiple rows (base case)" do
|
data/spec/hstore_spec.rb
CHANGED
@@ -3,7 +3,22 @@ require 'spec_helper'
|
|
3
3
|
describe Upsert do
|
4
4
|
describe 'hstore on pg' do
|
5
5
|
require 'pg_hstore'
|
6
|
-
|
6
|
+
|
7
|
+
let(:deserializer) do
|
8
|
+
klass = PgHstore.dup
|
9
|
+
if RUBY_PLATFORM == "java"
|
10
|
+
# activerecord-jdbc-adapter has native support for hstore
|
11
|
+
klass.class_eval do
|
12
|
+
def self.parse(obj)
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
klass
|
19
|
+
end
|
20
|
+
|
21
|
+
Pet.connection.execute 'CREATE EXTENSION IF NOT EXISTS HSTORE'
|
7
22
|
Pet.connection.execute "ALTER TABLE pets ADD COLUMN crazy HSTORE"
|
8
23
|
Pet.connection.execute "ALTER TABLE pets ADD COLUMN cool HSTORE"
|
9
24
|
|
@@ -11,27 +26,26 @@ describe Upsert do
|
|
11
26
|
Pet.delete_all
|
12
27
|
end
|
13
28
|
|
29
|
+
let(:upsert) { Upsert.new $conn, :pets }
|
30
|
+
|
14
31
|
it "works for ugly text" do
|
15
|
-
upsert = Upsert.new $conn, :pets
|
16
32
|
uggy = <<-EOS
|
17
33
|
{"results":[{"locations":[],"providedLocation":{"location":"3001 STRATTON WAY, MADISON, WI 53719 UNITED STATES"}}],"options":{"ignoreLatLngInput":true,"maxResults":1,"thumbMaps":false},"info":{"copyright":{"text":"© 2012 MapQuest, Inc.","imageUrl":"http://api.mqcdn.com/res/mqlogo.gif","imageAltText":"© 2012 MapQuest, Inc."},"statuscode":0,"messages":[]}}
|
18
34
|
EOS
|
19
35
|
upsert.row({:name => 'Uggy'}, :crazy => {:uggy => uggy})
|
20
36
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Uggy'})
|
21
|
-
crazy =
|
37
|
+
crazy = deserializer.parse row['crazy']
|
22
38
|
crazy.should == { 'uggy' => uggy }
|
23
39
|
end
|
24
40
|
|
25
41
|
it "just works" do
|
26
|
-
upsert = Upsert.new $conn, :pets
|
27
|
-
|
28
42
|
upsert.row({:name => 'Bill'}, :crazy => nil)
|
29
43
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
30
44
|
row['crazy'].should == nil
|
31
45
|
|
32
46
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1})
|
33
47
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
34
|
-
crazy =
|
48
|
+
crazy = deserializer.parse row['crazy']
|
35
49
|
crazy.should == { 'a' => '1' }
|
36
50
|
|
37
51
|
upsert.row({:name => 'Bill'}, :crazy => nil)
|
@@ -40,31 +54,29 @@ EOS
|
|
40
54
|
|
41
55
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1})
|
42
56
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
43
|
-
crazy =
|
57
|
+
crazy = deserializer.parse row['crazy']
|
44
58
|
crazy.should == { 'a' => '1' }
|
45
59
|
|
46
60
|
upsert.row({:name => 'Bill'}, :crazy => {:whatdat => 'whodat'})
|
47
61
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
48
|
-
crazy =
|
62
|
+
crazy = deserializer.parse row['crazy']
|
49
63
|
crazy.should == { 'a' => '1', 'whatdat' => 'whodat' }
|
50
64
|
|
51
65
|
upsert.row({:name => 'Bill'}, :crazy => {:whatdat => "D'ONOFRIO"})
|
52
66
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
53
|
-
crazy =
|
67
|
+
crazy = deserializer.parse row['crazy']
|
54
68
|
crazy.should == { 'a' => '1', 'whatdat' => "D'ONOFRIO" }
|
55
69
|
|
56
70
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 2})
|
57
71
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
58
|
-
crazy =
|
72
|
+
crazy = deserializer.parse row['crazy']
|
59
73
|
crazy.should == { 'a' => '2', 'whatdat' => "D'ONOFRIO" }
|
60
74
|
end
|
61
75
|
|
62
76
|
it "can nullify entire hstore" do
|
63
|
-
upsert = Upsert.new $conn, :pets
|
64
|
-
|
65
77
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1})
|
66
78
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
67
|
-
crazy =
|
79
|
+
crazy = deserializer.parse row['crazy']
|
68
80
|
crazy.should == { 'a' => '1' }
|
69
81
|
|
70
82
|
upsert.row({:name => 'Bill'}, :crazy => nil)
|
@@ -73,174 +85,163 @@ EOS
|
|
73
85
|
end
|
74
86
|
|
75
87
|
it "deletes keys that are nil" do
|
76
|
-
upsert = Upsert.new $conn, :pets
|
77
|
-
|
78
88
|
upsert.row({:name => 'Bill'}, :crazy => nil)
|
79
89
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
80
90
|
row['crazy'].should == nil
|
81
91
|
|
82
92
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1})
|
83
93
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
84
|
-
crazy =
|
94
|
+
crazy = deserializer.parse row['crazy']
|
85
95
|
crazy.should == { 'a' => '1' }
|
86
96
|
|
87
97
|
upsert.row({:name => 'Bill'}, :crazy => {})
|
88
98
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
89
|
-
crazy =
|
99
|
+
crazy = deserializer.parse row['crazy']
|
90
100
|
crazy.should == { 'a' => '1' }
|
91
101
|
|
92
102
|
upsert.row({:name => 'Bill'}, :crazy => {:a => nil})
|
93
103
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
94
|
-
crazy =
|
104
|
+
crazy = deserializer.parse row['crazy']
|
95
105
|
crazy.should == {}
|
96
106
|
|
97
107
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1, :b => 5})
|
98
108
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
99
|
-
crazy =
|
109
|
+
crazy = deserializer.parse row['crazy']
|
100
110
|
crazy.should == { 'a' => '1', 'b' => '5' }
|
101
111
|
|
102
112
|
upsert.row({:name => 'Bill'}, :crazy => {})
|
103
113
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
104
|
-
crazy =
|
114
|
+
crazy = deserializer.parse row['crazy']
|
105
115
|
crazy.should == { 'a' => '1', 'b' => '5' }
|
106
116
|
|
107
117
|
upsert.row({:name => 'Bill'}, :crazy => {:a => nil})
|
108
118
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
109
|
-
crazy =
|
119
|
+
crazy = deserializer.parse row['crazy']
|
110
120
|
crazy.should == { 'b' => '5' }
|
111
121
|
|
112
122
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1, :b => 5})
|
113
123
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
114
|
-
crazy =
|
124
|
+
crazy = deserializer.parse row['crazy']
|
115
125
|
crazy.should == { 'a' => '1', 'b' => '5' }
|
116
126
|
|
117
127
|
upsert.row({:name => 'Bill'}, :crazy => {:a => nil, :b => nil, :c => 12})
|
118
128
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
119
|
-
crazy =
|
129
|
+
crazy = deserializer.parse row['crazy']
|
120
130
|
crazy.should == { 'c' => '12' }
|
121
131
|
end
|
122
132
|
|
123
133
|
it "takes dangerous keys" do
|
124
|
-
upsert = Upsert.new $conn, :pets
|
125
|
-
|
126
134
|
upsert.row({:name => 'Bill'}, :crazy => nil)
|
127
135
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
128
136
|
row['crazy'].should == nil
|
129
137
|
|
130
138
|
upsert.row({:name => 'Bill'}, :crazy => {:'foo"bar' => 1})
|
131
139
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
132
|
-
crazy =
|
140
|
+
crazy = deserializer.parse row['crazy']
|
133
141
|
crazy.should == { 'foo"bar' => '1' }
|
134
142
|
|
135
143
|
upsert.row({:name => 'Bill'}, :crazy => {})
|
136
144
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
137
|
-
crazy =
|
145
|
+
crazy = deserializer.parse row['crazy']
|
138
146
|
crazy.should == { 'foo"bar' => '1' }
|
139
147
|
|
140
148
|
upsert.row({:name => 'Bill'}, :crazy => {:'foo"bar' => nil})
|
141
149
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
142
|
-
crazy =
|
150
|
+
crazy = deserializer.parse row['crazy']
|
143
151
|
crazy.should == {}
|
144
152
|
|
145
153
|
upsert.row({:name => 'Bill'}, :crazy => {:'foo"bar' => 1, :b => 5})
|
146
154
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
147
|
-
crazy =
|
155
|
+
crazy = deserializer.parse row['crazy']
|
148
156
|
crazy.should == { 'foo"bar' => '1', 'b' => '5' }
|
149
157
|
|
150
158
|
upsert.row({:name => 'Bill'}, :crazy => {})
|
151
159
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
152
|
-
crazy =
|
160
|
+
crazy = deserializer.parse row['crazy']
|
153
161
|
crazy.should == { 'foo"bar' => '1', 'b' => '5' }
|
154
162
|
|
155
163
|
upsert.row({:name => 'Bill'}, :crazy => {:'foo"bar' => nil})
|
156
164
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
157
|
-
crazy =
|
165
|
+
crazy = deserializer.parse row['crazy']
|
158
166
|
crazy.should == { 'b' => '5' }
|
159
167
|
|
160
168
|
upsert.row({:name => 'Bill'}, :crazy => {:'foo"bar' => 1, :b => 5})
|
161
169
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
162
|
-
crazy =
|
170
|
+
crazy = deserializer.parse row['crazy']
|
163
171
|
crazy.should == { 'foo"bar' => '1', 'b' => '5' }
|
164
172
|
|
165
173
|
upsert.row({:name => 'Bill'}, :crazy => {:'foo"bar' => nil, :b => nil, :c => 12})
|
166
174
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
167
|
-
crazy =
|
175
|
+
crazy = deserializer.parse row['crazy']
|
168
176
|
crazy.should == { 'c' => '12' }
|
169
177
|
end
|
170
178
|
|
171
179
|
it "handles multiple hstores" do
|
172
|
-
upsert = Upsert.new $conn, :pets
|
173
180
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1, :b => 9}, :cool => {:c => 12, :d => 19})
|
174
181
|
row = Pet.connection.select_one(%{SELECT crazy, cool FROM pets WHERE name = 'Bill'})
|
175
|
-
crazy =
|
182
|
+
crazy = deserializer.parse row['crazy']
|
176
183
|
crazy.should == { 'a' => '1', 'b' => '9' }
|
177
|
-
cool =
|
184
|
+
cool = deserializer.parse row['cool']
|
178
185
|
cool.should == { 'c' => '12', 'd' => '19' }
|
179
186
|
end
|
180
187
|
|
181
188
|
it "can deletes keys from multiple hstores at once" do
|
182
|
-
upsert = Upsert.new $conn, :pets
|
183
|
-
|
184
189
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1}, :cool => {5 => 9})
|
185
190
|
row = Pet.connection.select_one(%{SELECT crazy, cool FROM pets WHERE name = 'Bill'})
|
186
|
-
crazy =
|
191
|
+
crazy = deserializer.parse row['crazy']
|
187
192
|
crazy.should == { 'a' => '1' }
|
188
|
-
cool =
|
193
|
+
cool = deserializer.parse row['cool']
|
189
194
|
cool.should == { '5' => '9' }
|
190
195
|
|
191
196
|
# NOOP
|
192
197
|
upsert.row({:name => 'Bill'}, :crazy => {}, :cool => {})
|
193
198
|
row = Pet.connection.select_one(%{SELECT crazy, cool FROM pets WHERE name = 'Bill'})
|
194
|
-
crazy =
|
199
|
+
crazy = deserializer.parse row['crazy']
|
195
200
|
crazy.should == { 'a' => '1' }
|
196
|
-
cool =
|
201
|
+
cool = deserializer.parse row['cool']
|
197
202
|
cool.should == { '5' => '9' }
|
198
203
|
|
199
204
|
upsert.row({:name => 'Bill'}, :crazy => {:a => nil}, :cool => {13 => 17})
|
200
205
|
row = Pet.connection.select_one(%{SELECT crazy, cool FROM pets WHERE name = 'Bill'})
|
201
|
-
crazy =
|
206
|
+
crazy = deserializer.parse row['crazy']
|
202
207
|
crazy.should == {}
|
203
|
-
cool =
|
208
|
+
cool = deserializer.parse row['cool']
|
204
209
|
cool.should == { '5' => '9', '13' => '17' }
|
205
210
|
|
206
211
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1, :b => 5})
|
207
212
|
row = Pet.connection.select_one(%{SELECT crazy, cool FROM pets WHERE name = 'Bill'})
|
208
|
-
crazy =
|
213
|
+
crazy = deserializer.parse row['crazy']
|
209
214
|
crazy.should == { 'a' => '1', 'b' => '5' }
|
210
215
|
|
211
216
|
upsert.row({:name => 'Bill'}, :crazy => {:b => nil}, :cool => {5 => nil})
|
212
217
|
row = Pet.connection.select_one(%{SELECT crazy, cool FROM pets WHERE name = 'Bill'})
|
213
|
-
crazy =
|
218
|
+
crazy = deserializer.parse row['crazy']
|
214
219
|
crazy.should == {'a' => '1'}
|
215
|
-
cool =
|
220
|
+
cool = deserializer.parse row['cool']
|
216
221
|
cool.should == {'13' => '17' }
|
217
222
|
end
|
218
223
|
|
219
224
|
it "deletes keys whether new or existing record" do
|
220
|
-
upsert = Upsert.new $conn, :pets
|
221
|
-
|
222
225
|
upsert.row({:name => 'Bill'}, :crazy => {:z => 1, :x => nil})
|
223
226
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
224
|
-
crazy =
|
227
|
+
crazy = deserializer.parse row['crazy']
|
225
228
|
crazy.should == { 'z' => '1' }
|
226
229
|
|
227
230
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1})
|
228
231
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
229
|
-
crazy =
|
232
|
+
crazy = deserializer.parse row['crazy']
|
230
233
|
crazy.should == { 'a' => '1', 'z' => '1' }
|
231
234
|
end
|
232
235
|
|
233
236
|
it "can turn off eager nullify" do
|
234
|
-
upsert = Upsert.new $conn, :pets
|
235
|
-
|
236
237
|
upsert.row({:name => 'Bill'}, {:crazy => {:z => 1, :x => nil}}, :eager_nullify => false)
|
237
238
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
238
|
-
crazy =
|
239
|
+
crazy = deserializer.parse row['crazy']
|
239
240
|
crazy.should == { 'z' => '1', 'x' => nil }
|
240
241
|
|
241
242
|
upsert.row({:name => 'Bill'}, :crazy => {:a => 1})
|
242
243
|
row = Pet.connection.select_one(%{SELECT crazy FROM pets WHERE name = 'Bill'})
|
243
|
-
crazy =
|
244
|
+
crazy = deserializer.parse row['crazy']
|
244
245
|
crazy.should == { 'a' => '1', 'z' => '1', 'x' => nil}
|
245
246
|
end
|
246
247
|
|