em-pg-client-helper 2.0.3 → 2.0.4
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/lib/em-pg-client-helper/transaction.rb +45 -35
- data/spec/db_bulk_insert_spec.rb +19 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3bf320941966b1a2de9c01df789aaf6969bd371
|
4
|
+
data.tar.gz: a9d7145ae5bc7e361f27659103a9143450c5063c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4876c2c54967b115f76f2278158ad59eaa9a9b7a8c86d793d018da553dc620d60d60a4e67897a2903208c486786d0282cc639c03dc8b85da1ce5e3e58834fe00
|
7
|
+
data.tar.gz: 1285b6bb57a77d7aeb3876375ccbd52b4d00a2a1db90fc8c868bc74bf9b9945c380d2c5b92a2268058db13aae3f7475747fa51ee343b34630a0d9b258e51eab2
|
@@ -245,45 +245,55 @@ class PG::EM::Client::Helper::Transaction
|
|
245
245
|
df.callback(&blk) if blk
|
246
246
|
|
247
247
|
unique_index_columns_for_table(tbl) do |indexes|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
q_cols = columns.map { |c| usdb.literal(c) }
|
252
|
-
|
253
|
-
# If there are any unique indexes which the set of columns to
|
254
|
-
# be inserted into *doesn't* completely cover, we need to error
|
255
|
-
# out, because that will cause no rows (or, at most, one row) to
|
256
|
-
# be successfully inserted. In *theory*, a unique index with all-but-one
|
257
|
-
# row inserted *could* work, but that would only work if every value
|
258
|
-
# inserted was different, but quite frankly, I think that's a wicked
|
259
|
-
# corner case I'm not going to go *anywhere* near.
|
260
|
-
#
|
261
|
-
unless indexes.all? { |i| (i - columns).empty? }
|
262
|
-
ex = ArgumentError.new("Unique index columns not covered by data columns")
|
263
|
-
if @autorollback_on_error
|
264
|
-
df.fail(ex)
|
265
|
-
rollback(ex)
|
266
|
-
else
|
267
|
-
df.fail(ex)
|
248
|
+
q = if indexes.empty?
|
249
|
+
sequel_sql do |db|
|
250
|
+
db[tbl.to_sym].multi_insert_sql(columns, rows)
|
268
251
|
end
|
269
252
|
else
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
253
|
+
# Guh hand-hacked SQL is fugly... but what I'm doing is so utterly
|
254
|
+
# niche that Sequel doesn't support it.
|
255
|
+
q_tbl = usdb.literal(tbl.to_sym)
|
256
|
+
q_cols = columns.map { |c| usdb.literal(c) }
|
257
|
+
|
258
|
+
# If there are any unique indexes which the set of columns to
|
259
|
+
# be inserted into *doesn't* completely cover, we need to error
|
260
|
+
# out, because that will cause no rows (or, at most, one row) to
|
261
|
+
# be successfully inserted. In *theory*, a unique index with all-but-one
|
262
|
+
# row inserted *could* work, but that would only work if every value
|
263
|
+
# inserted was different, but quite frankly, I think that's a wicked
|
264
|
+
# corner case I'm not going to go *anywhere* near.
|
265
|
+
#
|
266
|
+
unless indexes.all? { |i| (i - columns).empty? }
|
267
|
+
ex = ArgumentError.new("Unique index columns not covered by data columns")
|
268
|
+
if @autorollback_on_error
|
269
|
+
df.fail(ex)
|
270
|
+
rollback(ex)
|
271
|
+
else
|
272
|
+
df.fail(ex)
|
273
|
+
end
|
274
|
+
else
|
275
|
+
subselect_where = indexes.map do |idx|
|
276
|
+
"(" + idx.map do |c|
|
277
|
+
"src.#{usdb.literal(c)}=dst.#{usdb.literal(c)}"
|
278
|
+
end.join(" AND ") + ")"
|
279
|
+
end.join(" OR ")
|
280
|
+
|
281
|
+
subselect = "SELECT 1 FROM #{q_tbl} AS dst WHERE #{subselect_where}"
|
282
|
+
|
283
|
+
vals = rows.map do |row|
|
284
|
+
"(" + row.map { |v| usdb.literal(v) }.join(", ") + ")"
|
285
|
+
end.join(", ")
|
286
|
+
|
287
|
+
"INSERT INTO #{q_tbl} (SELECT * FROM (VALUES #{vals}) " +
|
288
|
+
"AS src (#{q_cols.join(", ")}) WHERE NOT EXISTS (#{subselect}))"
|
285
289
|
end
|
286
290
|
end
|
291
|
+
|
292
|
+
exec(q) do |res|
|
293
|
+
df.succeed(res.cmd_tuples)
|
294
|
+
end.errback do |ex|
|
295
|
+
df.fail(ex)
|
296
|
+
end
|
287
297
|
end.errback do |ex|
|
288
298
|
df.fail(ex)
|
289
299
|
end
|
data/spec/db_bulk_insert_spec.rb
CHANGED
@@ -41,4 +41,23 @@ describe "PG::EM::Client::Helper#db_bulk_insert" do
|
|
41
41
|
end.errback { dbl.errback; EM.stop }
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
it "inserts multiple records without a UNIQUE index" do
|
46
|
+
expect(dbl = double).to receive(:results).with(2)
|
47
|
+
expect(dbl).to_not receive(:errback)
|
48
|
+
|
49
|
+
in_em do
|
50
|
+
expect_query("BEGIN")
|
51
|
+
expect_unique_indexes_query([])
|
52
|
+
expect_query('INSERT INTO "foo" ("bar", "baz") VALUES (1, \'x\'), (3, \'y\')',
|
53
|
+
[], 0.001, :succeed, Struct.new(:cmd_tuples).new(2)
|
54
|
+
)
|
55
|
+
expect_query("COMMIT")
|
56
|
+
|
57
|
+
db_bulk_insert(mock_conn, "foo", [:bar, :baz], [[1, "x"], [3, "y"]]) do |count|
|
58
|
+
dbl.results(count)
|
59
|
+
EM.stop
|
60
|
+
end.errback { dbl.errback; EM.stop }
|
61
|
+
end
|
62
|
+
end
|
44
63
|
end
|