upsert 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/Gemfile +4 -0
- data/README.md +115 -66
- data/Rakefile +16 -5
- data/lib/upsert.rb +86 -25
- data/lib/upsert/binary.rb +2 -0
- data/lib/upsert/column_definition.rb +27 -3
- data/lib/upsert/column_definition/mysql.rb +20 -0
- data/lib/upsert/column_definition/{PG_Connection.rb → postgresql.rb} +1 -1
- data/lib/upsert/connection.rb +20 -22
- data/lib/upsert/connection/Java_ComMysqlJdbc_JDBC4Connection.rb +25 -0
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +14 -0
- data/lib/upsert/connection/Java_OrgSqliteConn.rb +17 -0
- data/lib/upsert/connection/Mysql2_Client.rb +40 -18
- data/lib/upsert/connection/PG_Connection.rb +7 -3
- data/lib/upsert/connection/SQLite3_Database.rb +10 -2
- data/lib/upsert/connection/jdbc.rb +81 -0
- data/lib/upsert/connection/sqlite3.rb +23 -0
- data/lib/upsert/merge_function/Java_ComMysqlJdbc_JDBC4Connection.rb +42 -0
- data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +35 -0
- data/lib/upsert/merge_function/Java_OrgSqliteConn.rb +10 -0
- data/lib/upsert/merge_function/Mysql2_Client.rb +5 -58
- data/lib/upsert/merge_function/PG_Connection.rb +6 -78
- data/lib/upsert/merge_function/SQLite3_Database.rb +3 -22
- data/lib/upsert/merge_function/mysql.rb +67 -0
- data/lib/upsert/merge_function/postgresql.rb +94 -0
- data/lib/upsert/merge_function/sqlite3.rb +30 -0
- data/lib/upsert/row.rb +3 -6
- data/lib/upsert/version.rb +1 -1
- data/spec/binary_spec.rb +0 -2
- data/spec/correctness_spec.rb +26 -25
- data/spec/database_functions_spec.rb +6 -14
- data/spec/logger_spec.rb +22 -10
- data/spec/precision_spec.rb +1 -1
- data/spec/spec_helper.rb +115 -31
- data/spec/speed_spec.rb +1 -1
- data/spec/timezones_spec.rb +35 -14
- data/spec/type_safety_spec.rb +2 -2
- data/upsert.gemspec +18 -6
- metadata +25 -38
- data/lib/upsert/cell.rb +0 -5
- data/lib/upsert/cell/Mysql2_Client.rb +0 -16
- data/lib/upsert/cell/PG_Connection.rb +0 -28
- data/lib/upsert/cell/SQLite3_Database.rb +0 -36
- data/lib/upsert/column_definition/Mysql2_Client.rb +0 -24
- data/lib/upsert/column_definition/SQLite3_Database.rb +0 -7
- data/lib/upsert/row/Mysql2_Client.rb +0 -21
- data/lib/upsert/row/PG_Connection.rb +0 -7
- data/lib/upsert/row/SQLite3_Database.rb +0 -7
@@ -0,0 +1,30 @@
|
|
1
|
+
class Upsert
|
2
|
+
class MergeFunction
|
3
|
+
# @private
|
4
|
+
module Sqlite3
|
5
|
+
attr_reader :quoted_setter_names
|
6
|
+
attr_reader :quoted_selector_names
|
7
|
+
|
8
|
+
def initialize(*)
|
9
|
+
super
|
10
|
+
@quoted_setter_names = setter_keys.map { |k| connection.quote_ident k }
|
11
|
+
@quoted_selector_names = selector_keys.map { |k| connection.quote_ident k }
|
12
|
+
end
|
13
|
+
|
14
|
+
def create!
|
15
|
+
# not necessary
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(row)
|
19
|
+
bind_setter_values = row.setter.values.map { |v| connection.bind_value v }
|
20
|
+
bind_selector_values = row.selector.values.map { |v| connection.bind_value v }
|
21
|
+
|
22
|
+
insert_or_ignore_sql = %{INSERT OR IGNORE INTO #{quoted_table_name} (#{quoted_setter_names.join(',')}) VALUES (#{Array.new(bind_setter_values.length, '?').join(',')})}
|
23
|
+
connection.execute insert_or_ignore_sql, bind_setter_values
|
24
|
+
|
25
|
+
update_sql = %{UPDATE #{quoted_table_name} SET #{quoted_setter_names.map { |qk| "#{qk}=?" }.join(',')} WHERE #{quoted_selector_names.map { |qk| "#{qk}=?" }.join(' AND ')}}
|
26
|
+
connection.execute update_sql, (bind_setter_values + bind_selector_values)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/upsert/row.rb
CHANGED
@@ -16,17 +16,14 @@ class Upsert
|
|
16
16
|
attr_reader :setter
|
17
17
|
|
18
18
|
|
19
|
-
def initialize(
|
20
|
-
connection = controller.connection
|
21
|
-
cell_class = controller.cell_class
|
22
|
-
|
19
|
+
def initialize(raw_selector, raw_setter)
|
23
20
|
@selector = raw_selector.inject({}) do |memo, (k, v)|
|
24
|
-
memo[k.to_s] =
|
21
|
+
memo[k.to_s] = v
|
25
22
|
memo
|
26
23
|
end
|
27
24
|
|
28
25
|
@setter = raw_setter.inject({}) do |memo, (k, v)|
|
29
|
-
memo[k.to_s] =
|
26
|
+
memo[k.to_s] = v
|
30
27
|
memo
|
31
28
|
end
|
32
29
|
|
data/lib/upsert/version.rb
CHANGED
data/spec/binary_spec.rb
CHANGED
@@ -13,9 +13,7 @@ describe Upsert do
|
|
13
13
|
upsert = Upsert.new $conn, :pets
|
14
14
|
assert_creates(Pet, [{:name => name, :zipped_biography => zipped_biography}]) do
|
15
15
|
upsert.row({:name => name}, {:zipped_biography => Upsert.binary(zipped_biography)})
|
16
|
-
# binding.pry
|
17
16
|
end
|
18
|
-
|
19
17
|
Zlib::Inflate.inflate(Pet.find_by_name(name).zipped_biography).should == biography
|
20
18
|
end
|
21
19
|
end
|
data/spec/correctness_spec.rb
CHANGED
@@ -47,6 +47,7 @@ describe Upsert do
|
|
47
47
|
Pet.find_by_name_and_gender('Jerry', 'blue').tag_number.should == 777
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
50
51
|
describe "is just as correct as other ways" do
|
51
52
|
describe 'compared to native ActiveRecord' do
|
52
53
|
it "is as correct as than new/set/save" do
|
@@ -67,33 +68,33 @@ describe Upsert do
|
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
70
|
-
it "is as correct as than find_or_create + update_attributes" do
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
it "is as correct as than create + rescue/find/update" do
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
71
|
+
# it "is as correct as than find_or_create + update_attributes" do
|
72
|
+
# assert_same_result lotsa_records do |records|
|
73
|
+
# dynamic_method = nil
|
74
|
+
# records.each do |selector, setter|
|
75
|
+
# dynamic_method ||= "find_or_create_by_#{selector.keys.join('_or_')}"
|
76
|
+
# pet = Pet.send(dynamic_method, *selector.values)
|
77
|
+
# pet.update_attributes setter, :without_protection => true
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
# it "is as correct as than create + rescue/find/update" do
|
82
|
+
# assert_same_result lotsa_records do |records|
|
83
|
+
# dynamic_method = nil
|
84
|
+
# records.each do |selector, setter|
|
85
|
+
# dynamic_method ||= "find_or_create_by_#{selector.keys.join('_or_')}"
|
86
|
+
# begin
|
87
|
+
# Pet.create selector.merge(setter), :without_protection => true
|
88
|
+
# rescue
|
89
|
+
# pet = Pet.send(dynamic_method, *selector.values)
|
90
|
+
# pet.update_attributes setter, :without_protection => true
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
# end
|
94
95
|
end
|
95
96
|
|
96
|
-
if ENV['
|
97
|
+
if ENV['DB'] == 'mysql'
|
97
98
|
describe 'compared to activerecord-import' do
|
98
99
|
it "is as correct as faking upserts with activerecord-import" do
|
99
100
|
assert_same_result lotsa_records do |records|
|
@@ -1,14 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'stringio'
|
3
3
|
describe Upsert do
|
4
|
-
def fresh_connection
|
5
|
-
case ENV['ADAPTER']
|
6
|
-
when 'postgresql'
|
7
|
-
PGconn.new $conn_config
|
8
|
-
when 'mysql2'
|
9
|
-
Mysql2::Client.new $conn_config
|
10
|
-
end
|
11
|
-
end
|
12
4
|
describe 'database functions' do
|
13
5
|
it "re-uses merge functions across connections" do
|
14
6
|
begin
|
@@ -17,19 +9,19 @@ describe Upsert do
|
|
17
9
|
Upsert.logger = Logger.new io, Logger::INFO
|
18
10
|
|
19
11
|
# clear
|
20
|
-
Upsert.clear_database_functions(
|
12
|
+
Upsert.clear_database_functions($conn_factory.new_connection)
|
21
13
|
|
22
14
|
# create
|
23
|
-
Upsert.new(
|
15
|
+
Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
|
24
16
|
|
25
17
|
# clear
|
26
|
-
Upsert.clear_database_functions(
|
18
|
+
Upsert.clear_database_functions($conn_factory.new_connection)
|
27
19
|
|
28
20
|
# create (#2)
|
29
|
-
Upsert.new(
|
21
|
+
Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
|
30
22
|
|
31
23
|
# no create!
|
32
|
-
Upsert.new(
|
24
|
+
Upsert.new($conn_factory.new_connection, :pets).row :name => 'hello'
|
33
25
|
|
34
26
|
io.rewind
|
35
27
|
hits = io.read.split("\n").grep(/Creating or replacing/)
|
@@ -39,4 +31,4 @@ describe Upsert do
|
|
39
31
|
end
|
40
32
|
end
|
41
33
|
end
|
42
|
-
end if %w{ postgresql
|
34
|
+
end if %w{ postgresql mysql }.include?(ENV['DB'])
|
data/spec/logger_spec.rb
CHANGED
@@ -7,7 +7,9 @@ describe Upsert do
|
|
7
7
|
io = StringIO.new
|
8
8
|
Thread.exclusive do
|
9
9
|
Upsert.logger = Logger.new(io)
|
10
|
+
|
10
11
|
Upsert.logger.warn "hello"
|
12
|
+
|
11
13
|
io.rewind
|
12
14
|
io.read.chomp.should == 'hello'
|
13
15
|
end
|
@@ -17,21 +19,31 @@ describe Upsert do
|
|
17
19
|
end
|
18
20
|
|
19
21
|
it "logs queries" do
|
20
|
-
require 'sqlite3'
|
21
|
-
db = SQLite3::Database.open(':memory:')
|
22
|
-
db.execute_batch "CREATE TABLE cats (name CHARACTER VARYING(255))"
|
23
22
|
begin
|
24
|
-
io = StringIO.new
|
25
23
|
old_logger = Upsert.logger
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
io = StringIO.new
|
25
|
+
Thread.exclusive do
|
26
|
+
Upsert.logger = Logger.new(io)
|
27
|
+
|
28
|
+
u = Upsert.new($conn, :pets)
|
29
|
+
u.row(name: 'Jerry')
|
30
|
+
|
31
|
+
io.rewind
|
32
|
+
log = io.read.chomp
|
33
|
+
case u.connection.class.name
|
34
|
+
when /sqlite/i
|
35
|
+
log.should =~ /insert or ignore/i
|
36
|
+
when /mysql/i
|
37
|
+
log.should =~ /call upsert_pets_SEL_name/i
|
38
|
+
when /p.*g/i
|
39
|
+
log.should =~ /select upsert_pets_SEL_name/i
|
40
|
+
else
|
41
|
+
raise "not sure"
|
42
|
+
end
|
43
|
+
end
|
31
44
|
ensure
|
32
45
|
Upsert.logger = old_logger
|
33
46
|
end
|
34
47
|
end
|
35
|
-
|
36
48
|
end
|
37
49
|
end
|
data/spec/precision_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -4,33 +4,83 @@ require 'bundler/setup'
|
|
4
4
|
require 'pry'
|
5
5
|
|
6
6
|
require 'active_record'
|
7
|
+
ActiveRecord::Base.default_timezone = :utc
|
8
|
+
|
7
9
|
require 'active_record_inline_schema'
|
8
10
|
require 'activerecord-import'
|
9
11
|
|
10
|
-
ENV['
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
when '
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
12
|
+
ENV['DB'] ||= 'mysql'
|
13
|
+
|
14
|
+
class RawConnectionFactory
|
15
|
+
DATABASE = 'upsert_test'
|
16
|
+
CURRENT_USER = `whoami`.chomp
|
17
|
+
PASSWORD = 'password'
|
18
|
+
|
19
|
+
case ENV['DB']
|
20
|
+
|
21
|
+
when 'postgresql'
|
22
|
+
Kernel.system %{ dropdb upsert_test }
|
23
|
+
Kernel.system %{ createdb upsert_test }
|
24
|
+
if RUBY_PLATFORM == 'java'
|
25
|
+
CONFIG = "jdbc:postgresql://localhost/#{DATABASE}?user=#{CURRENT_USER}"
|
26
|
+
require 'jdbc/postgres'
|
27
|
+
# http://thesymanual.wordpress.com/2011/02/21/connecting-jruby-to-postgresql-with-jdbc-postgre-api/
|
28
|
+
java.sql.DriverManager.register_driver org.postgresql.Driver.new
|
29
|
+
def new_connection
|
30
|
+
java.sql.DriverManager.get_connection CONFIG
|
31
|
+
end
|
32
|
+
else
|
33
|
+
CONFIG = { :dbname => DATABASE }
|
34
|
+
require 'pg'
|
35
|
+
def new_connection
|
36
|
+
PG::Connection.new CONFIG
|
37
|
+
end
|
38
|
+
end
|
39
|
+
ActiveRecord::Base.establish_connection :adapter => 'postgresql', :database => DATABASE, :username => CURRENT_USER
|
40
|
+
|
41
|
+
when 'mysql'
|
42
|
+
Kernel.system %{ mysql -u root -ppassword -e "DROP DATABASE IF EXISTS #{DATABASE}" }
|
43
|
+
Kernel.system %{ mysql -u root -ppassword -e "CREATE DATABASE #{DATABASE} CHARSET utf8" }
|
44
|
+
if RUBY_PLATFORM == 'java'
|
45
|
+
CONFIG = "jdbc:mysql://127.0.0.1/#{DATABASE}?user=root&password=password"
|
46
|
+
require 'jdbc/mysql'
|
47
|
+
java.sql.DriverManager.register_driver com.mysql.jdbc.Driver.new
|
48
|
+
def new_connection
|
49
|
+
java.sql.DriverManager.get_connection CONFIG
|
50
|
+
end
|
51
|
+
else
|
52
|
+
CONFIG = { :username => 'root', :password => PASSWORD, :database => DATABASE}
|
53
|
+
require 'mysql2'
|
54
|
+
def new_connection
|
55
|
+
Mysql2::Client.new CONFIG
|
56
|
+
end
|
57
|
+
end
|
58
|
+
ActiveRecord::Base.establish_connection "#{RUBY_PLATFORM == 'java' ? 'mysql' : 'mysql2'}://root:password@127.0.0.1/#{DATABASE}"
|
59
|
+
|
60
|
+
when 'sqlite3'
|
61
|
+
if RUBY_PLATFORM == 'java'
|
62
|
+
def new_connection
|
63
|
+
ActiveRecord::Base.connection.raw_connection.connection
|
64
|
+
end
|
65
|
+
else
|
66
|
+
require 'sqlite3'
|
67
|
+
def new_connection
|
68
|
+
ActiveRecord::Base.connection.raw_connection
|
69
|
+
end
|
70
|
+
end
|
71
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
72
|
+
|
73
|
+
else
|
74
|
+
raise "not supported"
|
75
|
+
end
|
31
76
|
end
|
32
77
|
|
78
|
+
$conn_factory = RawConnectionFactory.new
|
79
|
+
$conn = $conn_factory.new_connection
|
80
|
+
|
33
81
|
require 'logger'
|
82
|
+
require 'fileutils'
|
83
|
+
FileUtils.rm_f 'test.log'
|
34
84
|
ActiveRecord::Base.logger = Logger.new('test.log')
|
35
85
|
|
36
86
|
if ENV['VERBOSE'] == 'true'
|
@@ -59,6 +109,17 @@ require 'benchmark'
|
|
59
109
|
require 'faker'
|
60
110
|
|
61
111
|
module SpecHelper
|
112
|
+
def random_time_or_datetime
|
113
|
+
time = Time.at(rand * Time.now.to_i)
|
114
|
+
if ENV['DB'] == 'mysql'
|
115
|
+
time = time.change(:usec => 0)
|
116
|
+
end
|
117
|
+
if rand > 0.5
|
118
|
+
time = time.change(:usec => 0).to_datetime
|
119
|
+
end
|
120
|
+
time
|
121
|
+
end
|
122
|
+
|
62
123
|
def lotsa_records
|
63
124
|
@records ||= begin
|
64
125
|
memo = []
|
@@ -69,7 +130,7 @@ module SpecHelper
|
|
69
130
|
2000.times do
|
70
131
|
selector = ActiveSupport::OrderedHash.new
|
71
132
|
selector[:name] = if RUBY_VERSION >= '1.9'
|
72
|
-
names.sample
|
133
|
+
names.sample
|
73
134
|
else
|
74
135
|
names.choice
|
75
136
|
end
|
@@ -79,7 +140,7 @@ module SpecHelper
|
|
79
140
|
:spiel => Faker::Lorem.sentences.join,
|
80
141
|
:good => true,
|
81
142
|
:birthday => Time.at(rand * Time.now.to_i).to_date,
|
82
|
-
:morning_walk_time =>
|
143
|
+
:morning_walk_time => random_time_or_datetime,
|
83
144
|
:home_address => Faker::Lorem.sentences.join,
|
84
145
|
# hard to know how to have AR insert this properly unless Upsert::Binary subclasses String
|
85
146
|
# :zipped_biography => Upsert.binary(Zlib::Deflate.deflate(Faker::Lorem.paragraphs.join, Zlib::BEST_SPEED))
|
@@ -102,19 +163,42 @@ module SpecHelper
|
|
102
163
|
end
|
103
164
|
end
|
104
165
|
ref2 = Pet.order(:name).all.map { |pet| pet.attributes.except('id') }
|
105
|
-
|
106
|
-
ref2a.to_yaml.should == ref1[i].to_yaml
|
107
|
-
end
|
108
|
-
# ref2.should == ref1
|
166
|
+
compare_attribute_sets ref1, ref2
|
109
167
|
end
|
110
168
|
|
111
169
|
def assert_creates(model, expected_records)
|
112
|
-
expected_records.each do |
|
113
|
-
|
170
|
+
expected_records.each do |selector, setter|
|
171
|
+
# should i use setter in where?
|
172
|
+
model.where(selector).count.should == 0
|
114
173
|
end
|
115
174
|
yield
|
116
|
-
expected_records.each do |
|
117
|
-
|
175
|
+
expected_records.each do |selector, setter|
|
176
|
+
setter ||= {}
|
177
|
+
found = model.where(selector).map { |record| record.attributes.except('id') }
|
178
|
+
expected = [ selector.stringify_keys.merge(setter.stringify_keys) ]
|
179
|
+
compare_attribute_sets expected, found
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def compare_attribute_sets(expected, found)
|
184
|
+
e = expected.map { |attrs| simplify_attributes attrs }
|
185
|
+
f = found.map { |attrs| simplify_attributes attrs }
|
186
|
+
f.each_with_index do |fa, i|
|
187
|
+
fa.should == e[i]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def simplify_attributes(attrs)
|
192
|
+
attrs.select do |k, v|
|
193
|
+
v.present?
|
194
|
+
end.inject({}) do |memo, (k, v)|
|
195
|
+
memo[k] = case v
|
196
|
+
when Time, DateTime
|
197
|
+
v.to_time.to_f
|
198
|
+
else
|
199
|
+
v
|
200
|
+
end
|
201
|
+
memo
|
118
202
|
end
|
119
203
|
end
|
120
204
|
|
data/spec/speed_spec.rb
CHANGED
@@ -46,7 +46,7 @@ describe Upsert do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
if ENV['
|
49
|
+
if ENV['DB'] == 'mysql'
|
50
50
|
describe 'compared to activerecord-import' do
|
51
51
|
it "is faster than faking upserts with activerecord-import" do
|
52
52
|
assert_faster_than 'faking upserts with activerecord-import', lotsa_records do |records|
|
data/spec/timezones_spec.rb
CHANGED
@@ -1,28 +1,49 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe Upsert do
|
3
|
-
describe "
|
4
|
-
|
5
|
-
|
3
|
+
describe "timezone support" do
|
4
|
+
it "takes times in UTC" do
|
5
|
+
time = Time.new.utc
|
6
|
+
if ENV['DB'] == 'mysql'
|
7
|
+
time = time.change(:usec => 0)
|
8
|
+
end
|
9
|
+
upsert = Upsert.new $conn, :pets
|
10
|
+
assert_creates(Pet, [[{:name => 'Jerry'}, {:morning_walk_time => time}]]) do
|
11
|
+
upsert.row({:name => 'Jerry'}, {:morning_walk_time => time})
|
12
|
+
end
|
6
13
|
end
|
7
|
-
|
8
|
-
|
14
|
+
|
15
|
+
it "takes times in local" do
|
16
|
+
time = Time.new
|
17
|
+
if ENV['DB'] == 'mysql'
|
18
|
+
time = time.change(:usec => 0)
|
19
|
+
end
|
20
|
+
upsert = Upsert.new $conn, :pets
|
21
|
+
assert_creates(Pet, [[{:name => 'Jerry'}, {:morning_walk_time => time}]]) do
|
22
|
+
upsert.row({:name => 'Jerry'}, {:morning_walk_time => time})
|
23
|
+
end
|
9
24
|
end
|
10
|
-
|
11
|
-
it "
|
12
|
-
|
13
|
-
|
25
|
+
|
26
|
+
it "takes datetimes in UTC" do
|
27
|
+
time = DateTime.now.new_offset(Rational(0, 24))
|
28
|
+
if ENV['DB'] == 'mysql'
|
29
|
+
time = time.change(:usec => 0)
|
30
|
+
end
|
14
31
|
upsert = Upsert.new $conn, :pets
|
15
|
-
assert_creates(Pet, [{:name => 'Jerry', :morning_walk_time => time}]) do
|
32
|
+
assert_creates(Pet, [[{:name => 'Jerry'}, {:morning_walk_time => time}]]) do
|
16
33
|
upsert.row({:name => 'Jerry'}, {:morning_walk_time => time})
|
17
34
|
end
|
18
35
|
end
|
19
|
-
|
20
|
-
|
21
|
-
time =
|
36
|
+
|
37
|
+
it "takes datetimes in local" do
|
38
|
+
time = DateTime.now
|
39
|
+
if ENV['DB'] == 'mysql'
|
40
|
+
time = time.change(:usec => 0)
|
41
|
+
end
|
22
42
|
upsert = Upsert.new $conn, :pets
|
23
|
-
assert_creates(Pet, [{:name => 'Jerry', :morning_walk_time => time}]) do
|
43
|
+
assert_creates(Pet, [[{:name => 'Jerry'}, {:morning_walk_time => time}]]) do
|
24
44
|
upsert.row({:name => 'Jerry'}, {:morning_walk_time => time})
|
25
45
|
end
|
26
46
|
end
|
47
|
+
|
27
48
|
end
|
28
49
|
end
|