mongo 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,6 +49,21 @@ be running, of course.
49
49
  See also the test code, especially tests/test_db_api.rb.
50
50
 
51
51
 
52
+ = Notes
53
+
54
+ == String Encoding
55
+
56
+ The BSON ("Binary JSON") format used to communicate with Mongo requires that
57
+ strings be UTF-8 (http://en.wikipedia.org/wiki/UTF-8).
58
+
59
+ Ruby 1.9 has built-in character encoding support. All strings sent to Mongo
60
+ and received from Mongo are converted to UTF-8 when necessary, and strings
61
+ read from Mongo will have their character encodings set to UTF-8.
62
+
63
+ When used with Ruby 1.8, the bytes in each string are written to and read from
64
+ Mongo as-is. If the string is ASCII all is well, because ASCII is a subset of
65
+ UTF-8. If the string is not ASCII then it may not be a well-formed UTF-8 string.
66
+
52
67
  = Testing
53
68
 
54
69
  If you have the source code, you can run the tests.
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'rake/gempackagetask'
7
7
  require 'rake/contrib/rubyforgepublisher'
8
8
 
9
9
  GEM = "mongo"
10
- GEM_VERSION = '0.0.3'
10
+ GEM_VERSION = '0.0.4'
11
11
  SUMMARY = 'Simple pure-Ruby driver for the 10gen Mongo DB'
12
12
  DESCRIPTION = 'This is a simple pure-Ruby driver for the 10gen Mongo DB. For more information about Mongo, see http://www.mongodb.org.'
13
13
  AUTHOR = 'Jim Menard'
@@ -1,8 +1,10 @@
1
+ require 'mongo/types/binary'
2
+ require 'mongo/types/dbref'
3
+ require 'mongo/types/objectid'
4
+ require 'mongo/types/regexp_of_holding'
5
+ require 'mongo/types/undefined'
6
+
1
7
  require 'mongo/mongo'
2
- require 'mongo/objectid'
3
- require 'mongo/dbref'
4
- require 'mongo/binary'
5
- require 'mongo/undefined'
6
8
  require 'mongo/message'
7
9
  require 'mongo/db'
8
10
  require 'mongo/cursor'
@@ -66,7 +66,7 @@ module XGen
66
66
  # Return an array contining current profiling information from the
67
67
  # database.
68
68
  def profiling_info
69
- @db.query(DB::SYSTEM_PROFILE_COLLECTION, Query.new({})).to_a
69
+ @db.query(Collection.new(@db, DB::SYSTEM_PROFILE_COLLECTION), Query.new({})).to_a
70
70
  end
71
71
 
72
72
  # Validate a named collection by raising an exception if there is a
@@ -23,13 +23,22 @@ module XGen
23
23
  # A named collection of records in a database.
24
24
  class Collection
25
25
 
26
- attr_reader :db, :name
26
+ attr_reader :db, :name, :hint_fields
27
27
 
28
28
  def initialize(db, name)
29
29
  @db = db
30
30
  @name = name
31
31
  end
32
32
 
33
+ # Set hint fields to use and return +self+. hint_fields may be a
34
+ # single field name or array of field names. May be +nil+. If no hint
35
+ # fields are specified, the ones in the collection are used if they
36
+ # exist.
37
+ def hint(hint_fields)
38
+ @hint_fileds = hint_fileds
39
+ self
40
+ end
41
+
33
42
  # Return records that match a +selector+ hash. See Mongo docs for
34
43
  # details.
35
44
  #
@@ -47,7 +56,7 @@ module XGen
47
56
  limit = options.delete(:limit) || 0
48
57
  sort = options.delete(:sort)
49
58
  raise RuntimeError, "Unknown options [#{options.inspect}]" unless options.empty?
50
- @db.query(@name, Query.new(selector, fields, offset, limit, sort))
59
+ @db.query(self, Query.new(selector, fields, offset, limit, sort))
51
60
  end
52
61
 
53
62
  # Insert +objects+, which are hashes. "<<" is aliased to this method.
@@ -29,12 +29,26 @@ module XGen
29
29
 
30
30
  RESPONSE_HEADER_SIZE = 20
31
31
 
32
- def initialize(db, collection, num_to_return=0)
33
- @db, @collection, @num_to_return = db, collection, num_to_return
32
+ attr_reader :db, :collection, :query
33
+
34
+ def initialize(db, collection, query)
35
+ @db, @collection, @query = db, collection, query
36
+ @num_to_return = @query.number_to_return || 0
34
37
  @cache = []
35
38
  @closed = false
36
39
  @can_call_to_a = true
37
- read_all
40
+ @query_run = false
41
+ end
42
+
43
+ def closed?; @closed; end
44
+
45
+ # Set hint fields to use and return +self+. hint_fields may be a
46
+ # single field name or array of field names. May be +nil+. If no hint
47
+ # fields are specified, the ones in the collection are used if they
48
+ # exist.
49
+ def hint(hint_fields)
50
+ @hint_fields = hint_fields
51
+ self
38
52
  end
39
53
 
40
54
  # Return +true+ if there are more records to retrieve. We do not check
@@ -100,9 +114,20 @@ module XGen
100
114
  @rows
101
115
  end
102
116
 
117
+ # Returns an explain plan record.
118
+ def explain
119
+ sel = OrderedHash.new
120
+ sel['query'] = @query.selector
121
+ sel['$explain'] = true
122
+ c = Cursor.new(@db, @collection, Query.new(sel))
123
+ e = c.next_object
124
+ c.close
125
+ e
126
+ end
127
+
103
128
  # Close the cursor.
104
129
  def close
105
- @db.send_to_db(KillCursorMessage(@cursor_id)) if @cursor_id
130
+ @db.send_to_db(KillCursorsMessage.new(@cursor_id)) if @cursor_id
106
131
  @cache = []
107
132
  @cursor_id = 0
108
133
  @closed = true
@@ -146,6 +171,7 @@ module XGen
146
171
  private
147
172
 
148
173
  def next_object_on_wire
174
+ send_query_if_needed
149
175
  # if @n_remaining is 0 but we have a non-zero cursor, there are more
150
176
  # to fetch, so do a GetMore operation, but don't do it here - do it
151
177
  # when someone pulls an object out of the cache and it's empty
@@ -154,8 +180,9 @@ module XGen
154
180
  end
155
181
 
156
182
  def refill_via_get_more
183
+ send_query_if_needed
157
184
  return if @cursor_id == 0
158
- @db.send_to_db(GetMoreMessage.new(@db.name, @collection, @cursor_id))
185
+ @db.send_to_db(GetMoreMessage.new(@db.name, @collection.name, @cursor_id))
159
186
  read_all
160
187
  end
161
188
 
@@ -170,6 +197,27 @@ module XGen
170
197
  BSON.new(@db).deserialize(buf)
171
198
  end
172
199
 
200
+ def send_query_if_needed
201
+ # Run query first time we request an object from the wire
202
+ unless @query_run
203
+ hints = @hint_fields || @collection.hint_fields
204
+ hints = [hints] if hints.kind_of?(String)
205
+ query = if hints
206
+ h = {}
207
+ hints.each { |field| h[field] = 1 }
208
+ sel = OrderedHash.new
209
+ sel['query'] = @query.selector
210
+ sel['$hint'] = h
211
+ Query.new(sel)
212
+ else
213
+ @query
214
+ end
215
+ @db.send_query_message(QueryMessage.new(@db.name, @collection.name, query))
216
+ @query_run = true
217
+ read_all
218
+ end
219
+ end
220
+
173
221
  def to_s
174
222
  "DBResponse(flags=#@result_flags, cursor_id=#@cursor_id, start=#@starting_from, n_returned=#@n_returned)"
175
223
  end
@@ -177,4 +225,3 @@ module XGen
177
225
  end
178
226
  end
179
227
  end
180
-
@@ -49,6 +49,8 @@ module XGen
49
49
  # The name of the database.
50
50
  attr_reader :name
51
51
 
52
+ attr_reader :host, :port
53
+
52
54
  # The database's socket. For internal use only.
53
55
  attr_reader :socket
54
56
 
@@ -82,7 +84,7 @@ module XGen
82
84
  def collections_info(coll_name=nil)
83
85
  selector = {}
84
86
  selector[:name] = full_coll_name(coll_name) if coll_name
85
- query(SYSTEM_NAMESPACE_COLLECTION, Query.new(selector))
87
+ query(Collection.new(self, SYSTEM_NAMESPACE_COLLECTION), Query.new(selector))
86
88
  end
87
89
 
88
90
  # Create a collection. If +strict+ is false, will return existing or
@@ -151,6 +153,20 @@ module XGen
151
153
  ok?(doc) && is_master.kind_of?(Numeric) && is_master.to_i == 1
152
154
  end
153
155
 
156
+ # Returns a string of the form "host:port" that points to the master
157
+ # database. Works even if this is the master database.
158
+ def master
159
+ doc = db_command(:ismaster => 1)
160
+ is_master = doc['ismaster']
161
+ raise "Error retrieving master database" unless ok?(doc) && is_master.kind_of?(Numeric)
162
+ case is_master.to_i
163
+ when 1
164
+ "#@host:#@port"
165
+ else
166
+ doc['remote']
167
+ end
168
+ end
169
+
154
170
  # Close the connection to the database.
155
171
  def close
156
172
  @socket.close
@@ -161,12 +177,19 @@ module XGen
161
177
  send_to_db(MsgMessage.new(msg))
162
178
  end
163
179
 
164
- # Send a Query to +collection_name+ and return a Cursor over the
165
- # results.
166
- def query(collection_name, query)
180
+ # Returns a Cursor over the query results.
181
+ #
182
+ # Note that the query gets sent lazily; the cursor calls
183
+ # #send_query_message when needed. If the caller never requests an
184
+ # object from the cursor, the query never gets sent.
185
+ def query(collection, query)
186
+ Cursor.new(self, collection, query)
187
+ end
188
+
189
+ # Used by a Cursor to lazily send the query to the database.
190
+ def send_query_message(query_message)
167
191
  @semaphore.synchronize {
168
- send_to_db(QueryMessage.new(@name, collection_name, query))
169
- Cursor.new(self, collection_name, query.number_to_return)
192
+ send_to_db(query_message)
170
193
  }
171
194
  end
172
195
 
@@ -233,7 +256,7 @@ module XGen
233
256
  # :ns :: Namespace; same as +collection_name+.
234
257
  def index_information(collection_name)
235
258
  sel = {:ns => full_coll_name(collection_name)}
236
- query(SYSTEM_INDEX_COLLECTION, Query.new(sel)).collect { |row|
259
+ query(Collection.new(self, SYSTEM_INDEX_COLLECTION), Query.new(sel)).collect { |row|
237
260
  h = {:name => row['name']}
238
261
  raise "Name of index on return from db was nil. Coll = #{full_coll_name(collection_name)}" unless h[:name]
239
262
 
@@ -298,7 +321,7 @@ module XGen
298
321
 
299
322
  q = Query.new(selector)
300
323
  q.number_to_return = 1
301
- query(SYSTEM_COMMAND_COLLECTION, q).next_object
324
+ query(Collection.new(self, SYSTEM_COMMAND_COLLECTION), q).next_object
302
325
  end
303
326
 
304
327
  end
@@ -8,8 +8,11 @@ module XGen
8
8
 
9
9
  class QueryMessage < Message
10
10
 
11
+ attr_reader :query
12
+
11
13
  def initialize(db_name, collection_name, query)
12
14
  super(OP_QUERY)
15
+ @query = query
13
16
  write_int(0)
14
17
  write_string("#{db_name}.#{collection_name}")
15
18
  write_int(query.number_to_skip)
File without changes
File without changes
@@ -0,0 +1,44 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ module XGen
18
+ module Mongo
19
+ module Driver
20
+
21
+ # A Regexp that can hold on to extra options and ignore them. Mongo
22
+ # regexes may contain option characters beyond 'i', 'm', and 'x'. (Note
23
+ # that Mongo only uses those three, but that regexes coming from other
24
+ # languages may store different option characters.)
25
+ #
26
+ # Note that you do not have to use this class at all if you wish to
27
+ # store regular expressions in Mongo. The Mongo and Ruby regex option
28
+ # flags are the same. Storing regexes is discouraged, in any case.
29
+ class RegexpOfHolding < Regexp
30
+
31
+ attr_accessor :extra_options_str
32
+
33
+ # +str+ and +options+ are the same as Regexp. +extra_options_str+
34
+ # contains all the other flags that were in Mongo but we do not use or
35
+ # understand.
36
+ def initialize(str, options, extra_options_str)
37
+ super(str, options)
38
+ @extra_options_str = extra_options_str
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -17,8 +17,11 @@
17
17
  require 'base64'
18
18
  require 'mongo/util/byte_buffer'
19
19
  require 'mongo/util/ordered_hash'
20
- require 'mongo/objectid'
21
- require 'mongo/dbref'
20
+ require 'mongo/types/binary'
21
+ require 'mongo/types/dbref'
22
+ require 'mongo/types/objectid'
23
+ require 'mongo/types/regexp_of_holding'
24
+ require 'mongo/types/undefined'
22
25
 
23
26
  # A BSON seralizer/deserializer.
24
27
  class BSON
@@ -43,8 +46,18 @@ class BSON
43
46
  NUMBER_INT = 16
44
47
  MAXKEY = 127
45
48
 
49
+ if RUBY_VERSION >= '1.9'
50
+ def self.to_utf8(str)
51
+ str.encode("utf-8")
52
+ end
53
+ else
54
+ def self.to_utf8(str)
55
+ str # TODO punt for now
56
+ end
57
+ end
58
+
46
59
  def self.serialize_cstr(buf, val)
47
- buf.put_array(val.to_s.unpack("C*") + [0])
60
+ buf.put_array(to_utf8(val.to_s).unpack("C*") + [0])
48
61
  end
49
62
 
50
63
  def initialize(db=nil)
@@ -67,7 +80,7 @@ class BSON
67
80
  obj.each {|k, v|
68
81
  type = bson_type(v, k)
69
82
  case type
70
- when STRING, CODE
83
+ when STRING, CODE, SYMBOL
71
84
  serialize_string_element(@buf, k, v, type)
72
85
  when NUMBER, NUMBER_INT
73
86
  serialize_number_element(@buf, k, v, type)
@@ -87,8 +100,6 @@ class BSON
87
100
  serialize_null_element(@buf, k)
88
101
  when REF
89
102
  serialize_dbref_element(@buf, k, v)
90
- when SYMBOL
91
- serialize_symbol_element(@buf, k, v)
92
103
  when BINARY
93
104
  serialize_binary_element(@buf, k, v)
94
105
  when UNDEFINED
@@ -118,6 +129,9 @@ class BSON
118
129
  when STRING, CODE
119
130
  key = deserialize_cstr(@buf)
120
131
  doc[key] = deserialize_string_data(@buf)
132
+ when SYMBOL
133
+ key = deserialize_cstr(@buf)
134
+ doc[key] = deserialize_string_data(@buf).intern
121
135
  when NUMBER
122
136
  key = deserialize_cstr(@buf)
123
137
  doc[key] = deserialize_number_data(@buf)
@@ -151,9 +165,6 @@ class BSON
151
165
  when REF
152
166
  key = deserialize_cstr(@buf)
153
167
  doc[key] = deserialize_dbref_data(@buf, key, parent)
154
- when SYMBOL
155
- key = deserialize_cstr(@buf)
156
- doc[key] = deserialize_symbol_data(@buf)
157
168
  when BINARY
158
169
  key = deserialize_cstr(@buf)
159
170
  doc[key] = deserialize_binary_data(@buf)
@@ -170,6 +181,7 @@ class BSON
170
181
  doc
171
182
  end
172
183
 
184
+ # For debugging.
173
185
  def hex_dump
174
186
  str = ''
175
187
  @buf.to_a.each_with_index { |b,i|
@@ -221,13 +233,18 @@ class BSON
221
233
  options |= Regexp::IGNORECASE if options_str.include?('i')
222
234
  options |= Regexp::MULTILINE if options_str.include?('m')
223
235
  options |= Regexp::EXTENDED if options_str.include?('x')
224
- Regexp.new(str, options)
236
+ options_str.gsub!(/[imx]/, '') # Now remove the three we understand
237
+ XGen::Mongo::Driver::RegexpOfHolding.new(str, options, options_str)
225
238
  end
226
239
 
227
240
  def deserialize_string_data(buf)
228
241
  len = buf.get_int
229
242
  bytes = buf.get(len)
230
- bytes[0..-2].pack("C*")
243
+ str = bytes[0..-2].pack("C*")
244
+ if RUBY_VERSION >= '1.9'
245
+ str.force_encoding("utf-8")
246
+ end
247
+ str
231
248
  end
232
249
 
233
250
  def deserialize_oid_data(buf)
@@ -240,10 +257,6 @@ class BSON
240
257
  XGen::Mongo::Driver::DBRef.new(parent, key, @db, ns, oid)
241
258
  end
242
259
 
243
- def deserialize_symbol_data(buf)
244
- deserialize_cstr(buf).intern
245
- end
246
-
247
260
  def deserialize_binary_data(buf)
248
261
  len = buf.get_int
249
262
  bytes = buf.get(len)
@@ -268,12 +281,6 @@ class BSON
268
281
  buf.put_array(val.object_id.to_a)
269
282
  end
270
283
 
271
- def serialize_symbol_element(buf, key, val)
272
- buf.put(SYMBOL)
273
- self.class.serialize_cstr(buf, key)
274
- self.class.serialize_cstr(buf, val)
275
- end
276
-
277
284
  def serialize_binary_element(buf, key, val)
278
285
  buf.put(BINARY)
279
286
  self.class.serialize_cstr(buf, key)
@@ -342,7 +349,9 @@ class BSON
342
349
  options_str << 'i' if ((options & Regexp::IGNORECASE) != 0)
343
350
  options_str << 'm' if ((options & Regexp::MULTILINE) != 0)
344
351
  options_str << 'x' if ((options & Regexp::EXTENDED) != 0)
345
- self.class.serialize_cstr(buf, options_str)
352
+ options_str << val.extra_options_str if val.respond_to?(:extra_options_str)
353
+ # Must store option chars in alphabetical order
354
+ self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join)
346
355
  end
347
356
 
348
357
  def serialize_oid_element(buf, key, val)
@@ -379,6 +388,9 @@ class BSON
379
388
  break if b == 0
380
389
  chars << b.chr
381
390
  end
391
+ if RUBY_VERSION >= '1.9'
392
+ chars.force_encoding("utf-8") # Mongo stores UTF-8
393
+ end
382
394
  chars
383
395
  end
384
396
 
@@ -15,8 +15,14 @@
15
15
  # ++
16
16
 
17
17
  # A hash in which the order of keys are preserved.
18
+ #
19
+ # Under Ruby 1.9 and greater, this class has no added methods because Ruby's
20
+ # Hash already keeps its keys ordered by order of insertion.
18
21
  class OrderedHash < Hash
19
22
 
23
+ # We only need the body of this class if the RUBY_VERSION is before 1.9
24
+ if RUBY_VERSION < '1.9'
25
+
20
26
  attr_accessor :ordered_keys
21
27
 
22
28
  def keys
@@ -57,4 +63,6 @@ class OrderedHash < Hash
57
63
  str << '}'
58
64
  end
59
65
 
66
+ end # Ruby before 1.9
67
+
60
68
  end
@@ -59,7 +59,26 @@ class BSONTest < Test::Unit::TestCase
59
59
  def test_regex
60
60
  doc = {'doc' => /foobar/i}
61
61
  @b.serialize(doc)
62
- assert_equal doc, @b.deserialize
62
+ doc2 = @b.deserialize
63
+ assert_equal doc, doc2
64
+
65
+ r = doc2['doc']
66
+ assert_kind_of XGen::Mongo::Driver::RegexpOfHolding, r
67
+ assert_equal '', r.extra_options_str
68
+
69
+ r.extra_options_str << 'zywcab'
70
+ assert_equal 'zywcab', r.extra_options_str
71
+
72
+ b = BSON.new
73
+ doc = {'doc' => r}
74
+ b.serialize(doc)
75
+ doc2 = nil
76
+ doc2 = b.deserialize
77
+ assert_equal doc, doc2
78
+
79
+ r = doc2['doc']
80
+ assert_kind_of XGen::Mongo::Driver::RegexpOfHolding, r
81
+ assert_equal 'abcwyz', r.extra_options_str # must be sorted
63
82
  end
64
83
 
65
84
  def test_boolean
@@ -0,0 +1,63 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'mongo'
3
+ require 'test/unit'
4
+
5
+ # NOTE: assumes Mongo is running
6
+ class CursorTest < Test::Unit::TestCase
7
+
8
+ include XGen::Mongo::Driver
9
+
10
+ def setup
11
+ host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
12
+ port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT
13
+ @db = Mongo.new(host, port).db('ruby-mongo-test')
14
+ @coll = @db.collection('test')
15
+ @coll.clear
16
+ @r1 = @coll.insert('a' => 1) # collection not created until it's used
17
+ @coll_full_name = 'ruby-mongo-test.test'
18
+ end
19
+
20
+ def teardown
21
+ @coll.clear unless @coll == nil || @db.socket.closed?
22
+ end
23
+
24
+ def test_explain
25
+ cursor = @coll.find('a' => 1)
26
+ explaination = cursor.explain
27
+ assert_not_nil explaination['cursor']
28
+ assert_kind_of Numeric, explaination['n']
29
+ assert_kind_of Numeric, explaination['millis']
30
+ assert_kind_of Numeric, explaination['nscanned']
31
+ end
32
+
33
+ def test_close_no_query_sent
34
+ begin
35
+ cursor = @coll.find('a' => 1)
36
+ cursor.close
37
+ assert cursor.closed?
38
+ rescue => ex
39
+ fail ex.to_s
40
+ end
41
+ end
42
+
43
+ def test_close_after_query_sent
44
+ begin
45
+ cursor = @coll.find('a' => 1)
46
+ cursor.next_object
47
+ cursor.close
48
+ assert cursor.closed?
49
+ rescue => ex
50
+ fail ex.to_s
51
+ end
52
+ end
53
+
54
+ def test_hint
55
+ begin
56
+ cursor = @coll.find('a' => 1).hint('a')
57
+ assert_equal 1, cursor.to_a.size
58
+ rescue => ex
59
+ fail ex.to_s
60
+ end
61
+ end
62
+
63
+ end
@@ -354,4 +354,8 @@ class DBAPITest < Test::Unit::TestCase
354
354
  assert @db.master?
355
355
  end
356
356
 
357
+ def test_master
358
+ assert_equal "#{@db.host}:#{@db.port}", @db.master
359
+ end
360
+
357
361
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Menard
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-12 00:00:00 -05:00
12
+ date: 2009-01-14 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -25,11 +25,9 @@ files:
25
25
  - bin/mongo_console
26
26
  - bin/validate
27
27
  - lib/mongo/admin.rb
28
- - lib/mongo/binary.rb
29
28
  - lib/mongo/collection.rb
30
29
  - lib/mongo/cursor.rb
31
30
  - lib/mongo/db.rb
32
- - lib/mongo/dbref.rb
33
31
  - lib/mongo/message/get_more_message.rb
34
32
  - lib/mongo/message/insert_message.rb
35
33
  - lib/mongo/message/kill_cursors_message.rb
@@ -42,9 +40,12 @@ files:
42
40
  - lib/mongo/message/update_message.rb
43
41
  - lib/mongo/message.rb
44
42
  - lib/mongo/mongo.rb
45
- - lib/mongo/objectid.rb
46
43
  - lib/mongo/query.rb
47
- - lib/mongo/undefined.rb
44
+ - lib/mongo/types/binary.rb
45
+ - lib/mongo/types/dbref.rb
46
+ - lib/mongo/types/objectid.rb
47
+ - lib/mongo/types/regexp_of_holding.rb
48
+ - lib/mongo/types/undefined.rb
48
49
  - lib/mongo/util/bson.rb
49
50
  - lib/mongo/util/byte_buffer.rb
50
51
  - lib/mongo/util/ordered_hash.rb
@@ -53,6 +54,7 @@ files:
53
54
  - tests/test_admin.rb
54
55
  - tests/test_bson.rb
55
56
  - tests/test_byte_buffer.rb
57
+ - tests/test_cursor.rb
56
58
  - tests/test_db_api.rb
57
59
  - tests/test_db_connection.rb
58
60
  - tests/test_message.rb