mongo 1.0.3 → 1.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.
- data/HISTORY +17 -0
- data/lib/mongo.rb +12 -5
- data/lib/mongo/collection.rb +13 -3
- data/lib/mongo/connection.rb +22 -6
- data/lib/mongo/cursor.rb +17 -16
- data/lib/mongo/db.rb +39 -41
- data/lib/mongo/gridfs/grid.rb +3 -2
- data/lib/mongo/gridfs/grid_io.rb +7 -0
- data/test/collection_test.rb +19 -2
- data/test/cursor_fail_test.rb +76 -0
- data/test/cursor_message_test.rb +32 -0
- data/test/cursor_test.rb +25 -1
- data/test/db_api_test.rb +1 -1
- data/test/db_test.rb +9 -1
- data/test/grid_io_test.rb +1 -3
- data/test/grid_test.rb +6 -0
- data/test/unit/connection_test.rb +7 -0
- data/test/unit/cursor_test.rb +0 -7
- data/test/unit/db_test.rb +5 -5
- metadata +7 -5
data/HISTORY
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
1.0.4 2010-7-13
|
2
|
+
|
3
|
+
* Removed deprecated
|
4
|
+
- Cursor admin option
|
5
|
+
- DB#query
|
6
|
+
- DB#create_index (use Collection#create_index)
|
7
|
+
- DB#command only takes hash options now
|
8
|
+
* j2bson executable (neomantra)
|
9
|
+
* Fixed bson_ext compilation on Solaris (slyphon)
|
10
|
+
* System JS helpers (neovintage)
|
11
|
+
* Use one mutex per thread on pooled connections (cremes)
|
12
|
+
* Check for CursorNotFound response flag
|
13
|
+
* MapReduce can return raw command output using :raw
|
14
|
+
* BSON::OrderedHash equality with other Ruby hashes (Ryan Angilly)
|
15
|
+
* Fix for broken Socket.send with large payloads (Frédéric De Jaeger)
|
16
|
+
* Lots of minor improvements. See commmits.
|
17
|
+
|
1
18
|
1.0.3 2010-6-15
|
2
19
|
|
3
20
|
* Optimiztion for BSON::OrderedHash
|
data/lib/mongo.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
4
|
|
5
5
|
module Mongo
|
6
|
-
VERSION = "1.0.
|
6
|
+
VERSION = "1.0.4"
|
7
7
|
end
|
8
8
|
|
9
9
|
module Mongo
|
@@ -21,11 +21,18 @@ module Mongo
|
|
21
21
|
OP_DELETE = 2006
|
22
22
|
OP_KILL_CURSORS = 2007
|
23
23
|
|
24
|
-
OP_QUERY_TAILABLE = 2
|
25
|
-
OP_QUERY_SLAVE_OK =
|
26
|
-
|
24
|
+
OP_QUERY_TAILABLE = 2 ** 1
|
25
|
+
OP_QUERY_SLAVE_OK = 2 ** 2
|
26
|
+
OP_QUERY_OPLOG_REPLAY = 2 ** 3
|
27
|
+
OP_QUERY_NO_CURSOR_TIMEOUT = 2 ** 4
|
28
|
+
OP_QUERY_AWAIT_DATA = 2 ** 5
|
29
|
+
OP_QUERY_EXHAUST = 2 ** 6
|
30
|
+
|
31
|
+
REPLY_CURSOR_NOT_FOUND = 2 ** 0
|
32
|
+
REPLY_QUERY_FAILURE = 2 ** 1
|
33
|
+
REPLY_SHARD_CONFIG_STALE = 2 ** 2
|
34
|
+
REPLY_AWAIT_CAPABLE = 2 ** 3
|
27
35
|
end
|
28
|
-
|
29
36
|
end
|
30
37
|
|
31
38
|
require 'bson'
|
data/lib/mongo/collection.rb
CHANGED
@@ -157,7 +157,8 @@ module Mongo
|
|
157
157
|
raise RuntimeError, "Unknown options [#{opts.inspect}]" unless opts.empty?
|
158
158
|
|
159
159
|
cursor = Cursor.new(self, :selector => selector, :fields => fields, :skip => skip, :limit => limit,
|
160
|
-
|
160
|
+
:order => sort, :hint => hint, :snapshot => snapshot, :timeout => timeout, :batch_size => batch_size)
|
161
|
+
|
161
162
|
if block_given?
|
162
163
|
yield cursor
|
163
164
|
cursor.close()
|
@@ -470,6 +471,8 @@ module Mongo
|
|
470
471
|
# @option opts [String] :out (nil) the name of the output collection. If specified, the collection will not be treated as temporary.
|
471
472
|
# @option opts [Boolean] :keeptemp (false) if true, the generated collection will be persisted. default is false.
|
472
473
|
# @option opts [Boolean ] :verbose (false) if true, provides statistics on job execution time.
|
474
|
+
# @options opts [Boolean] :raw (false) if true, return the raw result object from the map_reduce command, and not
|
475
|
+
# the instantiated collection that's returned by default.
|
473
476
|
#
|
474
477
|
# @return [Collection] a collection containing the results of the operation.
|
475
478
|
#
|
@@ -477,8 +480,10 @@ module Mongo
|
|
477
480
|
#
|
478
481
|
# @core mapreduce map_reduce-instance_method
|
479
482
|
def map_reduce(map, reduce, opts={})
|
483
|
+
opts.assert_valid_keys(:query, :sort, :limit, :finalize, :keeptemp, :verbose, :raw)
|
480
484
|
map = BSON::Code.new(map) unless map.is_a?(BSON::Code)
|
481
485
|
reduce = BSON::Code.new(reduce) unless reduce.is_a?(BSON::Code)
|
486
|
+
raw = opts.delete(:raw)
|
482
487
|
|
483
488
|
hash = BSON::OrderedHash.new
|
484
489
|
hash['mapreduce'] = self.name
|
@@ -487,10 +492,15 @@ module Mongo
|
|
487
492
|
hash.merge! opts
|
488
493
|
|
489
494
|
result = @db.command(hash)
|
490
|
-
unless result
|
495
|
+
unless Mongo::Support.ok?(result)
|
491
496
|
raise Mongo::OperationFailure, "map-reduce failed: #{result['errmsg']}"
|
492
497
|
end
|
493
|
-
|
498
|
+
|
499
|
+
if raw
|
500
|
+
result
|
501
|
+
else
|
502
|
+
@db[result["result"]]
|
503
|
+
end
|
494
504
|
end
|
495
505
|
alias :mapreduce :map_reduce
|
496
506
|
|
data/lib/mongo/connection.rb
CHANGED
@@ -32,7 +32,7 @@ module Mongo
|
|
32
32
|
STANDARD_HEADER_SIZE = 16
|
33
33
|
RESPONSE_HEADER_SIZE = 20
|
34
34
|
|
35
|
-
MONGODB_URI_MATCHER = /(([.\w\d]+):([\w\d]+)@)?([-.\w\d]+)(:([\w\d]+))?(\/([-\d\w]+))?/
|
35
|
+
MONGODB_URI_MATCHER = /(([-_.\w\d]+):([-_\w\d]+)@)?([-.\w\d]+)(:([\w\d]+))?(\/([-\d\w]+))?/
|
36
36
|
MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]"
|
37
37
|
|
38
38
|
attr_reader :logger, :size, :host, :port, :nodes, :auths, :sockets, :checked_out
|
@@ -97,7 +97,11 @@ module Mongo
|
|
97
97
|
|
98
98
|
# Mutex for synchronizing pool access
|
99
99
|
@connection_mutex = Mutex.new
|
100
|
-
|
100
|
+
|
101
|
+
|
102
|
+
# Create a mutex when a new key, in this case a socket,
|
103
|
+
# is added to the hash.
|
104
|
+
@safe_mutexes = Hash.new { |h, k| h[k] = Mutex.new }
|
101
105
|
|
102
106
|
# Condition variable for signal and wait
|
103
107
|
@queue = ConditionVariable.new
|
@@ -368,7 +372,7 @@ module Mongo
|
|
368
372
|
sock = checkout
|
369
373
|
packed_message = message_with_headers.append!(message_with_check).to_s
|
370
374
|
docs = num_received = cursor_id = ''
|
371
|
-
@
|
375
|
+
@safe_mutexes[sock].synchronize do
|
372
376
|
send_message_on_socket(packed_message, sock)
|
373
377
|
docs, num_received, cursor_id = receive(sock)
|
374
378
|
end
|
@@ -398,7 +402,7 @@ module Mongo
|
|
398
402
|
sock = socket || checkout
|
399
403
|
|
400
404
|
result = ''
|
401
|
-
@
|
405
|
+
@safe_mutexes[sock].synchronize do
|
402
406
|
send_message_on_socket(packed_message, sock)
|
403
407
|
result = receive(sock)
|
404
408
|
end
|
@@ -632,13 +636,22 @@ module Mongo
|
|
632
636
|
"expected #{RESPONSE_HEADER_SIZE} bytes, saw #{header_buf.length}"
|
633
637
|
end
|
634
638
|
header_buf.rewind
|
635
|
-
|
639
|
+
check_response_flags(header_buf.get_int)
|
636
640
|
cursor_id = header_buf.get_long
|
637
641
|
starting_from = header_buf.get_int
|
638
642
|
number_remaining = header_buf.get_int
|
639
643
|
[number_remaining, cursor_id]
|
640
644
|
end
|
641
645
|
|
646
|
+
def check_response_flags(flags)
|
647
|
+
if flags & Mongo::Constants::REPLY_CURSOR_NOT_FOUND != 0
|
648
|
+
raise Mongo::OperationFailure, "Query response returned CURSOR_NOT_FOUND. " +
|
649
|
+
"Either an invalid cursor was specified, or the cursor may have timed out on the server."
|
650
|
+
elsif flags & Mongo::Constants::REPLY_QUERY_FAILURE != 0
|
651
|
+
# Getting odd failures when a exception is raised here.
|
652
|
+
end
|
653
|
+
end
|
654
|
+
|
642
655
|
def read_documents(number_received, cursor_id, sock)
|
643
656
|
docs = []
|
644
657
|
number_remaining = number_received
|
@@ -696,7 +709,10 @@ module Mongo
|
|
696
709
|
# Requires a packed message and an available socket,
|
697
710
|
def send_message_on_socket(packed_message, socket)
|
698
711
|
begin
|
699
|
-
|
712
|
+
while packed_message.size > 0
|
713
|
+
byte_sent = socket.send(packed_message, 0)
|
714
|
+
packed_message.slice!(0, byte_sent)
|
715
|
+
end
|
700
716
|
rescue => ex
|
701
717
|
close
|
702
718
|
raise ConnectionFailure, "Operation failed with the following exception: #{ex}"
|
data/lib/mongo/cursor.rb
CHANGED
@@ -21,9 +21,9 @@ module Mongo
|
|
21
21
|
include Mongo::Conversions
|
22
22
|
include Enumerable
|
23
23
|
|
24
|
-
attr_reader :collection, :selector, :
|
24
|
+
attr_reader :collection, :selector, :fields,
|
25
25
|
:order, :hint, :snapshot, :timeout,
|
26
|
-
:full_collection_name
|
26
|
+
:full_collection_name, :batch_size
|
27
27
|
|
28
28
|
# Create a new cursor.
|
29
29
|
#
|
@@ -40,10 +40,6 @@ module Mongo
|
|
40
40
|
|
41
41
|
@selector = convert_selector_for_query(options[:selector])
|
42
42
|
@fields = convert_fields_for_query(options[:fields])
|
43
|
-
if options[:admin]
|
44
|
-
warn "The admin option to Cursor#new has been deprecated. The cursor should now be passed the admin collection explicitly."
|
45
|
-
end
|
46
|
-
@admin = options[:admin] || false
|
47
43
|
@skip = options[:skip] || 0
|
48
44
|
@limit = options[:limit] || 0
|
49
45
|
@order = options[:order]
|
@@ -237,7 +233,7 @@ module Mongo
|
|
237
233
|
message = BSON::ByteBuffer.new([0, 0, 0, 0])
|
238
234
|
message.put_int(1)
|
239
235
|
message.put_long(@cursor_id)
|
240
|
-
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close")
|
236
|
+
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close #{@cursor_id}")
|
241
237
|
end
|
242
238
|
@cursor_id = 0
|
243
239
|
@closed = true
|
@@ -255,10 +251,11 @@ module Mongo
|
|
255
251
|
# @see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
|
256
252
|
# The MongoDB wire protocol.
|
257
253
|
def query_opts
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
254
|
+
opts = 0
|
255
|
+
opts |= Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT unless @timeout
|
256
|
+
opts |= Mongo::Constants::OP_QUERY_SLAVE_OK if @connection.slave_ok?
|
257
|
+
opts |= Mongo::Constants::OP_QUERY_TAILABLE if @tailable
|
258
|
+
opts
|
262
259
|
end
|
263
260
|
|
264
261
|
# Get the query options for this Cursor.
|
@@ -275,6 +272,12 @@ module Mongo
|
|
275
272
|
:timeout => @timeout }
|
276
273
|
end
|
277
274
|
|
275
|
+
# Clean output for inspect.
|
276
|
+
def inspect
|
277
|
+
"<Mongo::Cursor:0x#{object_id.to_s(16)} namespace='#{@db.name}.#{@collection.name}' " +
|
278
|
+
"@selector=#{@selector.inspect}>"
|
279
|
+
end
|
280
|
+
|
278
281
|
private
|
279
282
|
|
280
283
|
# Convert the +:fields+ parameter from a single field name or an array
|
@@ -325,8 +328,7 @@ module Mongo
|
|
325
328
|
message = BSON::ByteBuffer.new([0, 0, 0, 0])
|
326
329
|
|
327
330
|
# DB name.
|
328
|
-
|
329
|
-
BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
331
|
+
BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@collection.name}")
|
330
332
|
|
331
333
|
# Number of results to return.
|
332
334
|
message.put_int(@batch_size)
|
@@ -356,8 +358,7 @@ module Mongo
|
|
356
358
|
def construct_query_message
|
357
359
|
message = BSON::ByteBuffer.new
|
358
360
|
message.put_int(query_opts)
|
359
|
-
|
360
|
-
BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
361
|
+
BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@collection.name}")
|
361
362
|
message.put_int(@skip)
|
362
363
|
message.put_int(@limit)
|
363
364
|
spec = query_contains_special_fields? ? construct_query_spec : @selector
|
@@ -367,7 +368,7 @@ module Mongo
|
|
367
368
|
end
|
368
369
|
|
369
370
|
def query_log_message
|
370
|
-
"#{@
|
371
|
+
"#{@db.name}['#{@collection.name}'].find(#{@selector.inspect}, #{@fields ? @fields.inspect : '{}'})" +
|
371
372
|
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}" +
|
372
373
|
"#{@order ? ('.sort(' + @order.inspect + ')') : ''}"
|
373
374
|
end
|
data/lib/mongo/db.rb
CHANGED
@@ -29,6 +29,7 @@ module Mongo
|
|
29
29
|
SYSTEM_INDEX_COLLECTION = "system.indexes"
|
30
30
|
SYSTEM_PROFILE_COLLECTION = "system.profile"
|
31
31
|
SYSTEM_USER_COLLECTION = "system.users"
|
32
|
+
SYSTEM_JS_COLLECTION = "system.js"
|
32
33
|
SYSTEM_COMMAND_COLLECTION = "$cmd"
|
33
34
|
|
34
35
|
# Counter for generating unique request ids.
|
@@ -106,6 +107,36 @@ module Mongo
|
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
110
|
+
# Adds a stored Javascript function to the database which can executed
|
111
|
+
# server-side in map_reduce, db.eval and $where clauses.
|
112
|
+
#
|
113
|
+
# @param [String] function_name
|
114
|
+
# @param [String] code
|
115
|
+
#
|
116
|
+
# @return [String] the function name saved to the database
|
117
|
+
def add_stored_function(function_name, code)
|
118
|
+
self[SYSTEM_JS_COLLECTION].save(
|
119
|
+
{
|
120
|
+
"_id" => function_name,
|
121
|
+
:value => BSON::Code.new(code)
|
122
|
+
}
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Removes stored Javascript function from the database. Returns
|
127
|
+
# false if the function does not exist
|
128
|
+
#
|
129
|
+
# @param [String] function_name
|
130
|
+
#
|
131
|
+
# @return [Boolean]
|
132
|
+
def remove_stored_function(function_name)
|
133
|
+
if self[SYSTEM_JS_COLLECTION].find_one({"_id" => function_name})
|
134
|
+
self[SYSTEM_JS_COLLECTION].remove({"_id" => function_name}, :safe => true)
|
135
|
+
else
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
109
140
|
# Adds a user to this database for use with authentication. If the user already
|
110
141
|
# exists in the system, the password will be updated.
|
111
142
|
#
|
@@ -238,7 +269,7 @@ module Mongo
|
|
238
269
|
#
|
239
270
|
# @param [String] name
|
240
271
|
#
|
241
|
-
# @return [Boolean]
|
272
|
+
# @return [Boolean] +true+ on success or +false+ if the collection name doesn't exist.
|
242
273
|
def drop_collection(name)
|
243
274
|
return true unless collection_names.include?(name)
|
244
275
|
|
@@ -304,17 +335,6 @@ module Mongo
|
|
304
335
|
command(:reseterror => 1)
|
305
336
|
end
|
306
337
|
|
307
|
-
# @deprecated please use Collection#find to create queries.
|
308
|
-
#
|
309
|
-
# Returns a Cursor over the query results.
|
310
|
-
#
|
311
|
-
# Note that the query gets sent lazily; the cursor calls
|
312
|
-
# Connection#send_message when needed. If the caller never requests an
|
313
|
-
# object from the cursor, the query never gets sent.
|
314
|
-
def query(collection, query, admin=false)
|
315
|
-
Cursor.new(self, collection, query, admin)
|
316
|
-
end
|
317
|
-
|
318
338
|
# Dereference a DBRef, returning the document it points to.
|
319
339
|
#
|
320
340
|
# @param [Mongo::DBRef] dbref
|
@@ -375,7 +395,7 @@ module Mongo
|
|
375
395
|
oh = BSON::OrderedHash.new
|
376
396
|
oh[:deleteIndexes] = collection_name
|
377
397
|
oh[:index] = index_name
|
378
|
-
doc = command(oh)
|
398
|
+
doc = command(oh, :check_response => false)
|
379
399
|
ok?(doc) || raise(MongoDBError, "Error with drop_index command: #{doc.inspect}")
|
380
400
|
end
|
381
401
|
|
@@ -403,23 +423,6 @@ module Mongo
|
|
403
423
|
self.command({:dbstats => 1})
|
404
424
|
end
|
405
425
|
|
406
|
-
# Create a new index on the given collection.
|
407
|
-
# Normally called by Collection#create_index.
|
408
|
-
#
|
409
|
-
# @param [String] collection_name
|
410
|
-
# @param [String, Array] field_or_spec either either a single field name
|
411
|
-
# or an array of [field name, direction] pairs. Directions should be specified as
|
412
|
-
# Mongo::ASCENDING or Mongo::DESCENDING.
|
413
|
-
# @param [Boolean] unique if +true+, the created index will enforce a uniqueness constraint.
|
414
|
-
#
|
415
|
-
# @return [String] the name of the index created.
|
416
|
-
#
|
417
|
-
# @deprecated
|
418
|
-
def create_index(collection_name, field_or_spec, unique=false)
|
419
|
-
warn "DB#create_index is now deprecated. Please use Collection#create_index instead."
|
420
|
-
self.collection(collection_name).create_index(field_or_spec, :unique => unique)
|
421
|
-
end
|
422
|
-
|
423
426
|
# Return +true+ if the supplied +doc+ contains an 'ok' field with the value 1.
|
424
427
|
#
|
425
428
|
# @param [Hash] doc
|
@@ -453,24 +456,19 @@ module Mongo
|
|
453
456
|
#
|
454
457
|
# @core commands command_instance-method
|
455
458
|
def command(selector, opts={}, old_check_response=false, old_sock=nil)
|
456
|
-
|
457
|
-
|
458
|
-
sock = opts[:sock]
|
459
|
-
else
|
460
|
-
warn "The options passed to DB#command should now be passed as hash keys; the admin option has been deprecated."
|
461
|
-
admin = opts
|
462
|
-
check_response = old_check_response
|
463
|
-
sock = old_sock
|
464
|
-
end
|
459
|
+
check_response = opts[:check_response].nil? ? true : opts[:check_response]
|
460
|
+
sock = opts[:sock]
|
465
461
|
raise MongoArgumentError, "command must be given a selector" unless selector.is_a?(Hash) && !selector.empty?
|
466
462
|
if selector.keys.length > 1 && RUBY_VERSION < '1.9' && selector.class != BSON::OrderedHash
|
467
463
|
raise MongoArgumentError, "DB#command requires an OrderedHash when hash contains multiple keys"
|
468
464
|
end
|
469
465
|
|
470
|
-
result = Cursor.new(system_command_collection,
|
466
|
+
result = Cursor.new(system_command_collection,
|
471
467
|
:limit => -1, :selector => selector, :socket => sock).next_document
|
472
468
|
|
473
|
-
if result.nil?
|
469
|
+
if result.nil?
|
470
|
+
raise OperationFailure, "Database command '#{selector.keys.first}' failed: returned null."
|
471
|
+
elsif (check_response && !ok?(result))
|
474
472
|
raise OperationFailure, "Database command '#{selector.keys.first}' failed: #{result.inspect}"
|
475
473
|
else
|
476
474
|
result
|
data/lib/mongo/gridfs/grid.rb
CHANGED
@@ -41,10 +41,11 @@ module Mongo
|
|
41
41
|
@chunks.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
|
42
42
|
end
|
43
43
|
|
44
|
-
# Store a file in the file store.
|
44
|
+
# Store a file in the file store. This method is designed only for writing new files;
|
45
|
+
# if you need to update a given file, first delete it using #Grid#delete.
|
45
46
|
#
|
46
47
|
# Note that arbitary metadata attributes can be saved to the file by passing
|
47
|
-
# them
|
48
|
+
# them in as options.
|
48
49
|
#
|
49
50
|
# @param [String, #read] data a string or io-like object to store.
|
50
51
|
#
|
data/lib/mongo/gridfs/grid_io.rb
CHANGED
@@ -315,11 +315,18 @@ module Mongo
|
|
315
315
|
@aliases = opts.delete(:aliases) if opts[:aliases]
|
316
316
|
@file_length = 0
|
317
317
|
opts.each {|k, v| self[k] = v}
|
318
|
+
check_existing_file if @safe
|
318
319
|
|
319
320
|
@current_chunk = create_chunk(0)
|
320
321
|
@file_position = 0
|
321
322
|
end
|
322
323
|
|
324
|
+
def check_existing_file
|
325
|
+
if @files.find_one('_id' => @files_id)
|
326
|
+
raise GridError, "Attempting to overwrite with Grid#put. You must delete the file first."
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
323
330
|
def to_mongo_object
|
324
331
|
h = BSON::OrderedHash.new
|
325
332
|
h['_id'] = @files_id
|
data/test/collection_test.rb
CHANGED
@@ -393,7 +393,7 @@ class TestCollection < Test::Unit::TestCase
|
|
393
393
|
assert c.closed?
|
394
394
|
end
|
395
395
|
|
396
|
-
if @@version
|
396
|
+
if @@version > "1.1.1"
|
397
397
|
def test_map_reduce
|
398
398
|
@@test << { "user_id" => 1 }
|
399
399
|
@@test << { "user_id" => 2 }
|
@@ -429,6 +429,23 @@ class TestCollection < Test::Unit::TestCase
|
|
429
429
|
assert res.find_one({"_id" => 2})
|
430
430
|
assert res.find_one({"_id" => 3})
|
431
431
|
end
|
432
|
+
|
433
|
+
def test_map_reduce_with_raw_response
|
434
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
435
|
+
r = Code.new("function(k,vals) { return 1; }")
|
436
|
+
res = @@test.map_reduce(m, r, :raw => true)
|
437
|
+
assert res["result"]
|
438
|
+
assert res["counts"]
|
439
|
+
assert res["timeMillis"]
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_allows_only_valid_keys
|
443
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
444
|
+
r = Code.new("function(k,vals) { return 1; }")
|
445
|
+
assert_raise ArgumentError do
|
446
|
+
@@test.map_reduce(m, r, :foo => true)
|
447
|
+
end
|
448
|
+
end
|
432
449
|
end
|
433
450
|
|
434
451
|
if @@version > "1.3.0"
|
@@ -686,7 +703,7 @@ class TestCollection < Test::Unit::TestCase
|
|
686
703
|
assert_nil cursor.next_document
|
687
704
|
end
|
688
705
|
|
689
|
-
should "" do
|
706
|
+
should "fail tailable cursor on a non-capped collection" do
|
690
707
|
col = @@db['regular-collection']
|
691
708
|
col.insert({:a => 1000})
|
692
709
|
tail = Cursor.new(col, :tailable => true, :order => [['$natural', 1]])
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
class CursorTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
include Mongo
|
7
|
+
|
8
|
+
@@connection = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
9
|
+
ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT)
|
10
|
+
@@db = @@connection.db(MONGO_TEST_DB)
|
11
|
+
@@coll = @@db.collection('test')
|
12
|
+
@@version = @@connection.server_version
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@@coll.remove
|
16
|
+
@@coll.insert('a' => 1) # collection not created until it's used
|
17
|
+
@@coll_full_name = "#{MONGO_TEST_DB}.test"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_refill_via_get_more
|
21
|
+
assert_equal 1, @@coll.count
|
22
|
+
1000.times { |i|
|
23
|
+
assert_equal 1 + i, @@coll.count
|
24
|
+
@@coll.insert('a' => i)
|
25
|
+
}
|
26
|
+
|
27
|
+
assert_equal 1001, @@coll.count
|
28
|
+
count = 0
|
29
|
+
@@coll.find.each { |obj|
|
30
|
+
count += obj['a']
|
31
|
+
}
|
32
|
+
assert_equal 1001, @@coll.count
|
33
|
+
|
34
|
+
# do the same thing again for debugging
|
35
|
+
assert_equal 1001, @@coll.count
|
36
|
+
count2 = 0
|
37
|
+
@@coll.find.each { |obj|
|
38
|
+
count2 += obj['a']
|
39
|
+
}
|
40
|
+
assert_equal 1001, @@coll.count
|
41
|
+
|
42
|
+
assert_equal count, count2
|
43
|
+
assert_equal 499501, count
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_refill_via_get_more_alt_coll
|
47
|
+
coll = @@db.collection('test-alt-coll')
|
48
|
+
coll.remove
|
49
|
+
coll.insert('a' => 1) # collection not created until it's used
|
50
|
+
assert_equal 1, coll.count
|
51
|
+
|
52
|
+
1000.times { |i|
|
53
|
+
assert_equal 1 + i, coll.count
|
54
|
+
coll.insert('a' => i)
|
55
|
+
}
|
56
|
+
|
57
|
+
assert_equal 1001, coll.count
|
58
|
+
count = 0
|
59
|
+
coll.find.each { |obj|
|
60
|
+
count += obj['a']
|
61
|
+
}
|
62
|
+
assert_equal 1001, coll.count
|
63
|
+
|
64
|
+
# do the same thing again for debugging
|
65
|
+
assert_equal 1001, coll.count
|
66
|
+
count2 = 0
|
67
|
+
coll.find.each { |obj|
|
68
|
+
count2 += obj['a']
|
69
|
+
}
|
70
|
+
assert_equal 1001, coll.count
|
71
|
+
|
72
|
+
assert_equal count, count2
|
73
|
+
assert_equal 499501, count
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
class CursorTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
include Mongo
|
7
|
+
|
8
|
+
@@connection = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
9
|
+
ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT)
|
10
|
+
@@db = @@connection.db(MONGO_TEST_DB)
|
11
|
+
@@coll = @@db.collection('test')
|
12
|
+
@@version = @@connection.server_version
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@@coll.remove
|
16
|
+
@@coll.insert('a' => 1) # collection not created until it's used
|
17
|
+
@@coll_full_name = "#{MONGO_TEST_DB}.test"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_cursor_invalid
|
21
|
+
100.times do |n|
|
22
|
+
@@coll.insert({:a => "HELLO" * 50000})
|
23
|
+
end
|
24
|
+
|
25
|
+
cursor = @@coll.find({}, :batch_size => 50)
|
26
|
+
cursor.next_document
|
27
|
+
p @@db.command("cursorInfo" => 1)
|
28
|
+
cursor.close
|
29
|
+
p @@db.command("cursorInfo" => 1)
|
30
|
+
cursor.next_document
|
31
|
+
end
|
32
|
+
end
|
data/test/cursor_test.rb
CHANGED
@@ -17,6 +17,13 @@ class CursorTest < Test::Unit::TestCase
|
|
17
17
|
@@coll_full_name = "#{MONGO_TEST_DB}.test"
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_inspect
|
21
|
+
selector = {:a => 1}
|
22
|
+
cursor = @@coll.find(selector)
|
23
|
+
assert_equal "<Mongo::Cursor:0x#{cursor.object_id.to_s(16)} namespace='#{@@db.name}.#{@@coll.name}' " +
|
24
|
+
"@selector=#{selector.inspect}>", cursor.inspect
|
25
|
+
end
|
26
|
+
|
20
27
|
def test_explain
|
21
28
|
cursor = @@coll.find('a' => 1)
|
22
29
|
explaination = cursor.explain
|
@@ -130,7 +137,7 @@ class CursorTest < Test::Unit::TestCase
|
|
130
137
|
@@coll.save({:t => 't2'})
|
131
138
|
@@coll.save({:t => 't2'})
|
132
139
|
|
133
|
-
assert_equal 3, @@coll.find({'_id' => {'$gt' => t1_id
|
140
|
+
assert_equal 3, @@coll.find({'_id' => {'$gt' => t1_id, '$lt' => t2_id}}).count
|
134
141
|
@@coll.find({'_id' => {'$gt' => t2_id}}).each do |doc|
|
135
142
|
assert_equal 't2', doc['t']
|
136
143
|
end
|
@@ -389,4 +396,21 @@ class CursorTest < Test::Unit::TestCase
|
|
389
396
|
|
390
397
|
assert_equal false, cursor.has_next?
|
391
398
|
end
|
399
|
+
|
400
|
+
def test_cursor_invalid
|
401
|
+
@@coll.remove
|
402
|
+
1000.times do |n|
|
403
|
+
@@coll.insert({:a => n})
|
404
|
+
end
|
405
|
+
|
406
|
+
cursor = @@coll.find({})
|
407
|
+
cursor.next_document
|
408
|
+
cursor.close
|
409
|
+
|
410
|
+
assert_raise_error(Mongo::OperationFailure, "CURSOR_NOT_FOUND") do
|
411
|
+
999.times do
|
412
|
+
cursor.next_document
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
392
416
|
end
|
data/test/db_api_test.rb
CHANGED
@@ -289,7 +289,7 @@ class DBAPITest < Test::Unit::TestCase
|
|
289
289
|
def test_index_create_with_symbol
|
290
290
|
assert_equal @@coll.index_information.length, 1
|
291
291
|
|
292
|
-
name = @@
|
292
|
+
name = @@coll.create_index([['a', 1]])
|
293
293
|
info = @@db.index_information(@@coll.name)
|
294
294
|
assert_equal name, "a_1"
|
295
295
|
assert_equal @@coll.index_information, info
|
data/test/db_test.rb
CHANGED
@@ -230,7 +230,7 @@ class DBTest < Test::Unit::TestCase
|
|
230
230
|
def test_text_port_number_raises_no_errors
|
231
231
|
conn = Connection.new(@@host, @@port.to_s)
|
232
232
|
db = conn[MONGO_TEST_DB]
|
233
|
-
|
233
|
+
db.collection('users').remove
|
234
234
|
end
|
235
235
|
|
236
236
|
def test_user_management
|
@@ -247,6 +247,14 @@ class DBTest < Test::Unit::TestCase
|
|
247
247
|
assert !@@db.remove_user("joe")
|
248
248
|
end
|
249
249
|
|
250
|
+
def test_stored_function_management
|
251
|
+
@@db.add_stored_function("sum", "function (x, y) { return x + y; }")
|
252
|
+
assert_equal @@db.eval("return sum(2,3);"), 5
|
253
|
+
assert @@db.remove_stored_function("sum")
|
254
|
+
assert_raise OperationFailure do
|
255
|
+
@@db.eval("return sum(2,3);")
|
256
|
+
end
|
257
|
+
end
|
250
258
|
|
251
259
|
if @@version >= "1.3.5"
|
252
260
|
def test_db_stats
|
data/test/grid_io_test.rb
CHANGED
@@ -52,9 +52,7 @@ class GridIOTest < Test::Unit::TestCase
|
|
52
52
|
|
53
53
|
should "raise an exception when check fails" do
|
54
54
|
io = File.open(File.join(File.dirname(__FILE__), 'data', 'sample_file.pdf'), 'r')
|
55
|
-
db
|
56
|
-
db.stubs(:command).returns({'md5' => '12345'})
|
57
|
-
@files.expects(:db).returns(db)
|
55
|
+
@db.stubs(:command).returns({'md5' => '12345'})
|
58
56
|
file = GridIO.new(@files, @chunks, 'bigfile', 'w', :safe => true)
|
59
57
|
file.write(io)
|
60
58
|
assert_raise GridMD5Failure do
|
data/test/grid_test.rb
CHANGED
@@ -27,6 +27,12 @@ class GridTest < Test::Unit::TestCase
|
|
27
27
|
assert_equal 'sample', file['filename']
|
28
28
|
end
|
29
29
|
|
30
|
+
should "not be able to overwrite an exising file" do
|
31
|
+
assert_raise GridError do
|
32
|
+
@grid.put(@data, :filename => 'sample', :_id => @id, :safe => true)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
30
36
|
should "return nil if it doesn't exist" do
|
31
37
|
assert_nil @grid.exist?(:metadata => 'foo')
|
32
38
|
end
|
@@ -88,6 +88,13 @@ class ConnectionTest < Test::Unit::TestCase
|
|
88
88
|
assert_equal auth_hash, @conn.auths[1]
|
89
89
|
end
|
90
90
|
|
91
|
+
should "parse a uri with a hyphen & underscore in the username or password" do
|
92
|
+
@conn = Connection.from_uri("mongodb://hyphen-user_name:p-s_s@localhost:27017/db", :connect => false)
|
93
|
+
assert_equal ['localhost', 27017], @conn.nodes[0]
|
94
|
+
auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
|
95
|
+
assert_equal auth_hash, @conn.auths[0]
|
96
|
+
end
|
97
|
+
|
91
98
|
should "attempt to connect" do
|
92
99
|
TCPSocket.stubs(:new).returns(new_mock_socket)
|
93
100
|
@conn = Connection.from_uri("mongodb://localhost", :connect => false)
|
data/test/unit/cursor_test.rb
CHANGED
@@ -9,13 +9,6 @@ class CursorTest < Test::Unit::TestCase
|
|
9
9
|
@cursor = Cursor.new(@collection)
|
10
10
|
end
|
11
11
|
|
12
|
-
should "set admin to false" do
|
13
|
-
assert_equal false, @cursor.admin
|
14
|
-
|
15
|
-
@cursor = Cursor.new(@collection, :admin => true)
|
16
|
-
assert_equal true, @cursor.admin
|
17
|
-
end
|
18
|
-
|
19
12
|
should "set selector" do
|
20
13
|
assert @cursor.selector == {}
|
21
14
|
|
data/test/unit/db_test.rb
CHANGED
@@ -31,25 +31,25 @@ class DBTest < Test::Unit::TestCase
|
|
31
31
|
|
32
32
|
should "raise an error if the selector is omitted" do
|
33
33
|
assert_raise MongoArgumentError do
|
34
|
-
@db.command({}, true)
|
34
|
+
@db.command({}, :check_response => true)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
should "create the proper cursor" do
|
39
39
|
@cursor = mock(:next_document => {"ok" => 1})
|
40
|
-
Cursor.expects(:new).with(@collection,
|
40
|
+
Cursor.expects(:new).with(@collection,
|
41
41
|
:limit => -1, :selector => {:buildinfo => 1}, :socket => nil).returns(@cursor)
|
42
42
|
command = {:buildinfo => 1}
|
43
|
-
@db.command(command, true)
|
43
|
+
@db.command(command, :check_response => true)
|
44
44
|
end
|
45
45
|
|
46
46
|
should "raise an error when the command fails" do
|
47
47
|
@cursor = mock(:next_document => {"ok" => 0})
|
48
|
-
Cursor.expects(:new).with(@collection,
|
48
|
+
Cursor.expects(:new).with(@collection,
|
49
49
|
:limit => -1, :selector => {:buildinfo => 1}, :socket => nil).returns(@cursor)
|
50
50
|
assert_raise OperationFailure do
|
51
51
|
command = {:buildinfo => 1}
|
52
|
-
@db.command(command,
|
52
|
+
@db.command(command, :check_response => true)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 4
|
9
|
+
version: 1.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jim Menard
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-
|
19
|
+
date: 2010-07-13 00:00:00 -04:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -29,8 +29,8 @@ dependencies:
|
|
29
29
|
segments:
|
30
30
|
- 1
|
31
31
|
- 0
|
32
|
-
-
|
33
|
-
version: 1.0.
|
32
|
+
- 4
|
33
|
+
version: 1.0.4
|
34
34
|
type: :runtime
|
35
35
|
version_requirements: *id001
|
36
36
|
description: A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.
|
@@ -112,6 +112,8 @@ test_files:
|
|
112
112
|
- test/collection_test.rb
|
113
113
|
- test/connection_test.rb
|
114
114
|
- test/conversions_test.rb
|
115
|
+
- test/cursor_fail_test.rb
|
116
|
+
- test/cursor_message_test.rb
|
115
117
|
- test/cursor_test.rb
|
116
118
|
- test/db_api_test.rb
|
117
119
|
- test/db_connection_test.rb
|