Update and remove return error object in safe mode

This commit is contained in:
Kyle Banker 2010-11-09 13:07:01 -05:00
parent 59ba221066
commit ced3bfbfe8
4 changed files with 43 additions and 13 deletions

View File

@ -256,8 +256,7 @@ module Mongo
# a document (as a hash) or array of documents to be inserted. # a document (as a hash) or array of documents to be inserted.
# #
# @return [ObjectId, Array] # @return [ObjectId, Array]
# the _id of the inserted document or a list of _ids of all inserted documents. # The _id of the inserted document or a list of _ids of all inserted documents.
# Note: the object may have been modified by the database's PK factory, if it has one.
# #
# @option opts [Boolean, Hash] :safe (+false+) # @option opts [Boolean, Hash] :safe (+false+)
# run the operation in safe mode, which run a getlasterror command on the # run the operation in safe mode, which run a getlasterror command on the
@ -298,7 +297,8 @@ module Mongo
# @example remove only documents that have expired: # @example remove only documents that have expired:
# users.remove({:expire => {"$lte" => Time.now}}) # users.remove({:expire => {"$lte" => Time.now}})
# #
# @return [True] # @return [Hash, true] Returns a Hash containing the last error object if running in safe mode.
# Otherwise, returns true.
# #
# @raise [Mongo::OperationFailure] an exception will be raised iff safe mode is enabled # @raise [Mongo::OperationFailure] an exception will be raised iff safe mode is enabled
# and the operation fails. # and the operation fails.
@ -317,15 +317,12 @@ module Mongo
@logger.debug("MONGODB #{@db.name}['#{@name}'].remove(#{selector.inspect})") if @logger @logger.debug("MONGODB #{@db.name}['#{@name}'].remove(#{selector.inspect})") if @logger
if safe if safe
@connection.send_message_with_safe_check(Mongo::Constants::OP_DELETE, message, @db.name, nil, safe) @connection.send_message_with_safe_check(Mongo::Constants::OP_DELETE, message, @db.name, nil, safe)
# the return value of send_message_with_safe_check isn't actually meaningful --
# only the fact that it didn't raise an error is -- so just return true
true
else else
@connection.send_message(Mongo::Constants::OP_DELETE, message) @connection.send_message(Mongo::Constants::OP_DELETE, message)
end end
end end
# Update a single document in this collection. # Update one or more documents in this collection.
# #
# @param [Hash] selector # @param [Hash] selector
# a hash specifying elements which must be present for a document to be updated. Note: # a hash specifying elements which must be present for a document to be updated. Note:
@ -346,6 +343,9 @@ module Mongo
# options set on this collection, its database object, or the current collection. # options set on this collection, its database object, or the current collection.
# See the options for DB#get_last_error for details. # See the options for DB#get_last_error for details.
# #
# @return [Hash, true] Returns a Hash containing the last error object if running in safe mode.
# Otherwise, returns true.
#
# @core update update-instance_method # @core update update-instance_method
def update(selector, document, options={}) def update(selector, document, options={})
# Initial byte is 0. # Initial byte is 0.

View File

@ -422,9 +422,7 @@ module Mongo
# #
# @see DB#get_last_error for valid last error params. # @see DB#get_last_error for valid last error params.
# #
# @return [Array] # @return [Hash] The document returned by the call to getlasterror.
# An array whose indexes include [0] documents returned, [1] number of document received,
# and [3] a cursor_id.
def send_message_with_safe_check(operation, message, db_name, log_message=nil, last_error_params=false) def send_message_with_safe_check(operation, message, db_name, log_message=nil, last_error_params=false)
message_with_headers = add_message_headers(operation, message) message_with_headers = add_message_headers(operation, message)
message_with_check = last_error_message(db_name, last_error_params) message_with_check = last_error_message(db_name, last_error_params)
@ -439,11 +437,13 @@ module Mongo
ensure ensure
checkin(sock) checkin(sock)
end end
if num_received == 1 && (error = docs[0]['err'] || docs[0]['errmsg']) if num_received == 1 && (error = docs[0]['err'] || docs[0]['errmsg'])
close if error == "not master" close if error == "not master"
raise Mongo::OperationFailure, error raise Mongo::OperationFailure, docs[0]['code'].to_s + ': ' + error
end end
[docs, num_received, cursor_id]
docs[0]
end end
# Sends a message to the database and waits for the response. # Sends a message to the database and waits for the response.

View File

@ -175,6 +175,10 @@ class DBTest < Test::Unit::TestCase
assert_nil @@db.previous_error assert_nil @@db.previous_error
end end
def test_get_last_error_helper
p @@db.get_last_error
end
def test_check_command_response def test_check_command_response
command = {:forceerror => 1} command = {:forceerror => 1}
assert_raise OperationFailure do assert_raise OperationFailure do

View File

@ -2,7 +2,7 @@ require './test/test_helper'
include Mongo include Mongo
class SafeTest < Test::Unit::TestCase class SafeTest < Test::Unit::TestCase
context "Safe tests: " do context "Safe mode propogation: " do
setup do setup do
@con = standard_connection(:safe => {:w => 1}) @con = standard_connection(:safe => {:w => 1})
@db = @con[MONGO_TEST_DB] @db = @con[MONGO_TEST_DB]
@ -39,4 +39,30 @@ class SafeTest < Test::Unit::TestCase
@col.update({:a => 2}, {:a => 1}, :safe => false) @col.update({:a => 2}, {:a => 1}, :safe => false)
end end
end end
context "Safe error objects" do
setup do
@con = standard_connection
@db = @con[MONGO_TEST_DB]
@col = @db['test']
@col.remove
@col.insert({:a => 1})
@col.insert({:a => 1})
@col.insert({:a => 1})
end
should "return object on update" do
response = @col.update({:a => 1}, {"$set" => {:a => 2}},
:multi => true, :safe => true)
assert response['updatedExisting']
assert_equal 3, response['n']
end
should "return object on remove" do
response = @col.remove({}, :safe => true)
assert_equal 3, response['n']
end
end
end end