RUBY-319 support continue_on_error insert flag

This commit is contained in:
Kyle Banker 2011-08-29 12:04:01 -04:00
parent 8c241cded7
commit a6ea525e3d
2 changed files with 44 additions and 6 deletions

View File

@ -311,6 +311,11 @@ module Mongo
# its database object, or the current connection. See the options on # its database object, or the current connection. See the options on
# for DB#get_last_error. # for DB#get_last_error.
# #
# @option opts [Boolean] :continue_on_error (+false+) If true, then
# continue a bulk insert even if one of the documents inserted
# triggers a database assertion (as in a duplicate insert, for instance).
# MongoDB v2.0+.
#
# @see DB#remove for options that can be passed to :safe. # @see DB#remove for options that can be passed to :safe.
# #
# @core insert insert-instance_method # @core insert insert-instance_method
@ -318,7 +323,7 @@ module Mongo
doc_or_docs = [doc_or_docs] unless doc_or_docs.is_a?(Array) doc_or_docs = [doc_or_docs] unless doc_or_docs.is_a?(Array)
doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) } doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) }
safe = opts.fetch(:safe, @safe) safe = opts.fetch(:safe, @safe)
result = insert_documents(doc_or_docs, @name, true, safe) result = insert_documents(doc_or_docs, @name, true, safe, opts)
result.size > 1 ? result : result.first result.size > 1 ? result : result.first
end end
alias_method :<<, :insert alias_method :<<, :insert
@ -892,9 +897,13 @@ module Mongo
# Sends a Mongo::Constants::OP_INSERT message to the database. # Sends a Mongo::Constants::OP_INSERT message to the database.
# Takes an array of +documents+, an optional +collection_name+, and a # Takes an array of +documents+, an optional +collection_name+, and a
# +check_keys+ setting. # +check_keys+ setting.
def insert_documents(documents, collection_name=@name, check_keys=true, safe=false) def insert_documents(documents, collection_name=@name, check_keys=true, safe=false, flags={})
# Initial byte is 0. if flags[:continue_on_error]
message = BSON::ByteBuffer.new("\0\0\0\0") message = BSON::ByteBuffer.new
message.put_int(1)
else
message = BSON::ByteBuffer.new("\0\0\0\0")
end
BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{collection_name}") BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{collection_name}")
documents.each do |doc| documents.each do |doc|
message.put_binary(BSON::BSON_CODER.serialize(doc, check_keys, true, @connection.max_bson_size).to_s) message.put_binary(BSON::BSON_CODER.serialize(doc, check_keys, true, @connection.max_bson_size).to_s)

View File

@ -15,7 +15,7 @@ class TestCollection < Test::Unit::TestCase
assert !@@db['normal'].capped? assert !@@db['normal'].capped?
@@db.drop_collection('normal') @@db.drop_collection('normal')
@@db.create_collection('c', :capped => true) @@db.create_collection('c', :capped => true, :size => 100_000)
assert @@db['c'].capped? assert @@db['c'].capped?
@@db.drop_collection('c') @@db.drop_collection('c')
end end
@ -151,6 +151,35 @@ class TestCollection < Test::Unit::TestCase
end end
end end
def test_bulk_insert_with_continue_on_error
if @@version >= "2.0"
@@test.create_index([["foo", 1]], :unique => true)
docs = []
docs << {:foo => 1}
docs << {:foo => 1}
docs << {:foo => 2}
docs << {:foo => 3}
assert_raise OperationFailure do
@@test.insert(docs, :safe => true)
end
assert_equal 1, @@test.count
@@test.remove
docs = []
docs << {:foo => 1}
docs << {:foo => 1}
docs << {:foo => 2}
docs << {:foo => 3}
assert_raise OperationFailure do
@@test.insert(docs, :safe => true, :continue_on_error => true)
end
assert_equal 3, @@test.count
@@test.remove
@@test.drop_index("foo_1")
end
end
def test_maximum_insert_size def test_maximum_insert_size
docs = [] docs = []
16.times do 16.times do