Return primary keys when using blocks or values#43
Return primary keys when using blocks or values#43pomier wants to merge 1 commit intojamis:masterfrom
Conversation
ed126ba to
61fa3b6
Compare
|
I have updated the Pull Request with new updates from master, it should be good to be merged. |
10a728f to
d60a046
Compare
I've just rebased the master branch! |
mberlanda
left a comment
There was a problem hiding this comment.
The code looks clear, however the build is not passing yet:
https://github.com/jamis/bulk_insert/runs/2216453436
This is mainly due to:
- the lack of support of the feature is not explicit (e.g. I would suggest to raise an argument error when it is not supported)
- the tests on the postgresql adapter are expecting empty arrays instead of the primary keys
I put several comments to address these two points. Feel free to comment and ask questions if anything is not clear
| def inserted_ids | ||
| @return_primary_keys ? @result_sets.map(&:rows).flatten : nil | ||
| end |
There was a problem hiding this comment.
This option on non postgresql adapters may lead to some errors like:
Old rails versions
NoMethodError: undefined method `rows' for nil:NilClass
/home/travis/build/jamis/bulk_insert/lib/bulk_insert/worker.rb:40:in `map'
/home/travis/build/jamis/bulk_insert/lib/bulk_insert/worker.rb:40:in `inserted_ids'
/home/travis/build/jamis/bulk_insert/test/bulk_insert/worker_test.rb:163:in `block in <class:BulkInsertWorkerTest>'
Or it may return empty arrays in SQLite and Mysql (only if rails >=6).
In order to avoid confusion and future bugs, I would suggest to fail as soon as possible in case of misconfiguration.
E.g.
bulk_insert/lib/bulk_insert/worker.rb
Lines 22 to 23 in 4a69aff
# Add at line 23
validate_return_primary_keys!
# ---
def validate_return_primary_keys!
if @return_primary_keys && !@statement_adapter.is_a?(StatementAdapters::PostgreSQLAdapter)
raise ArgumentError, "Unsupported option 'return_primary_keys' for adapter #{@adapter_name}"
end
end
| @@ -159,11 +160,13 @@ class BulkInsertWorkerTest < ActiveSupport::TestCase | |||
| worker.add greeting: "second" | |||
| worker.save! | |||
| assert_equal 1, worker.result_sets.count | |||
There was a problem hiding this comment.
Here the result_sets for non postgresql adapters would look like
- mysql rails < 6
[ nil ] - sqlite and mysql rails > 6
[#<ActiveRecord::Result:0x0000563f19834d08 @columns=[], @rows=[], @hash_rows=nil, @column_types={}>]
| @@ -159,11 +160,13 @@ class BulkInsertWorkerTest < ActiveSupport::TestCase | |||
| worker.add greeting: "second" | |||
There was a problem hiding this comment.
On this test I would follow something similar to:
bulk_insert/test/bulk_insert_test.rb
Lines 34 to 43 in 4a69aff
if Testing.connection.adapter_name =~ /\APost(?:greSQL|GIS)/i
worker = BulkInsert::Worker.new(
Testing.connection,
Testing.table_name,
'id',
%w(greeting age happy created_at updated_at color),
500,
false,
false,
true
)
# put the rest of the test here
else
assert_raise(ArgumentError) { worker = BulkInsert::Worker.new(Testing.connection, Testing.table_name, 'id', %w(greeting age happy created_at updated_at color), 500, false, false, true) }
you can eventually also capture the error message as per the example linked and perform a partial matching on the error message
| worker.add greeting: "fourth" | ||
| worker.save! | ||
| assert_equal 2, worker.result_sets.count | ||
| assert_equal [], worker.inserted_ids |
There was a problem hiding this comment.
the expected result here should be
assert_equal Testing.last(2).map(&:id).sort, worker.inserted_ids.sort
| output = Testing.bulk_insert( | ||
| values: [["Hello", 15, true]], | ||
| return_primary_keys: true | ||
| ) |
There was a problem hiding this comment.
same as per the previous comment on skip based on the adapter.
| values: [["Hello", 15, true]], | ||
| return_primary_keys: true | ||
| ) | ||
| assert_equal output, [] |
There was a problem hiding this comment.
the expected result here should be
assert_equal [Testing.last(1).id], output
| worker.add greeting: "second" | ||
| worker.save! | ||
| assert_equal 1, worker.result_sets.count | ||
| assert_equal [], worker.inserted_ids |
There was a problem hiding this comment.
the expected result here should be
assert_equal [ Testing.last(1).id ], worker.inserted_ids
In #32, @psloomis did a great job in adding the possibility to retrieve the primary keys inserted in PostGIS and PostgreSQL.
However, this requires to manupulate the
Workerinstance directly to retrieve the returned ids.Besides, the provided example in the
README.mdwas not working, as it assumes that the worker instance is returned by thebulk_insertfunction, which is not. When used with a block or thevaluesargument, the function returnsnil. In these cases there is no way of retrieving the inserted ids.I submit here an improvement proposal which returns the list of inserted ids when the
return_primary_keys: trueoption is provided with a block or thevaluesargument.For retro-compatibility purpose, this function continues to return
nilwhenreturn_primary_keysisfalse: