mongo 1.8.3 → 1.8.4.rc0
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.
- checksums.yaml +14 -6
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/VERSION +1 -1
- data/lib/mongo.rb +11 -0
- data/lib/mongo/collection.rb +54 -49
- data/lib/mongo/cursor.rb +8 -4
- data/lib/mongo/db.rb +107 -112
- data/lib/mongo/mongo_client.rb +18 -14
- data/lib/mongo/mongo_replica_set_client.rb +17 -10
- data/lib/mongo/util/pool.rb +0 -19
- data/lib/mongo/util/pool_manager.rb +0 -21
- data/lib/mongo/util/read_preference.rb +40 -12
- data/lib/mongo/util/uri_parser.rb +2 -2
- data/mongo.gemspec +1 -0
- data/test/auxillary/pool_reuse_test.rb +0 -0
- data/test/bson/object_id_test.rb +7 -1
- data/test/functional/collection_test.rb +24 -1
- data/test/functional/connection_test.rb +7 -7
- data/test/functional/db_api_test.rb +5 -6
- data/test/functional/uri_test.rb +16 -16
- data/test/replica_set/basic_test.rb +1 -1
- data/test/replica_set/pinning_test.rb +41 -0
- data/test/replica_set/refresh_test.rb +0 -0
- data/test/sharded_cluster/basic_test.rb +0 -0
- data/test/unit/client_test.rb +2 -2
- data/test/unit/collection_test.rb +1 -1
- data/test/unit/connection_test.rb +2 -2
- data/test/unit/db_test.rb +0 -1
- data/test/unit/pool_manager_test.rb +0 -0
- metadata +41 -30
- metadata.gz.sig +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YjU5N2Y3NjIxZDMyODFiMDI3MWYzODQ1MzNiMDk2YjgxZmQwY2EyYg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MTEwZTgzOWQ3MzkyNGNhNmQ3ZDY2YzE0ZGVkMDc0MTJhNWRlOWM4Yg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NjYwYTlmNDYwNTZkZjZiMmQyZTUzNzgxOTM5NGMwMWQ0YjY5MDE3M2M3YmUx
|
10
|
+
MmI3MWNmN2QxMTgwMTZiMTdjNzMyODJhZjAzYTg1M2VkMTI4OTI5ZjNlMjdl
|
11
|
+
NTVlY2E0MDc5MTY3ZmNjOTBhZmFkMjA2MDlkYjAzYjgyNTMyNWE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MGJlZGJlMjk5NWFhYjI1MjhiYjYwMmVkZjViZTdiNDE0ZjY0YWEwZmIxZDRj
|
14
|
+
NzEyYjk5N2Y1MDMyNWM4ZmU1YTM0ODA2ZDQ3ZTQwNTdhNTRmOGNhZmEwNjA3
|
15
|
+
ZTZlNzM5YzRiYmJkN2JlM2VmYTEzNWJhOThjYTRhMzRiNTg2N2U=
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.8.
|
1
|
+
1.8.4.rc0
|
data/lib/mongo.rb
CHANGED
@@ -2,7 +2,18 @@ module Mongo
|
|
2
2
|
ASCENDING = 1
|
3
3
|
DESCENDING = -1
|
4
4
|
GEO2D = '2d'
|
5
|
+
GEO2DSPHERE = '2dsphere'
|
5
6
|
GEOHAYSTACK = 'geoHaystack'
|
7
|
+
TEXT = 'text'
|
8
|
+
HASHED = 'hashed'
|
9
|
+
INDEX_TYPES = [ ASCENDING,
|
10
|
+
DESCENDING,
|
11
|
+
GEO2D,
|
12
|
+
GEO2DSPHERE,
|
13
|
+
GEOHAYSTACK,
|
14
|
+
TEXT,
|
15
|
+
HASHED
|
16
|
+
]
|
6
17
|
|
7
18
|
DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024
|
8
19
|
DEFAULT_MAX_MESSAGE_SIZE = DEFAULT_MAX_BSON_SIZE * 2
|
data/lib/mongo/collection.rb
CHANGED
@@ -9,7 +9,8 @@ module Mongo
|
|
9
9
|
:name,
|
10
10
|
:pk_factory,
|
11
11
|
:hint,
|
12
|
-
:write_concern
|
12
|
+
:write_concern,
|
13
|
+
:capped
|
13
14
|
|
14
15
|
# Read Preference
|
15
16
|
attr_accessor :read,
|
@@ -20,20 +21,20 @@ module Mongo
|
|
20
21
|
#
|
21
22
|
# @param [String, Symbol] name the name of the collection.
|
22
23
|
# @param [DB] db a MongoDB database instance.
|
23
|
-
#
|
24
|
+
#
|
24
25
|
# @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
|
25
26
|
# should be acknowledged
|
26
27
|
# @option opts [Boolean] :j (false) Set journal acknowledgement
|
27
28
|
# @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout
|
28
29
|
# @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
|
29
|
-
#
|
30
|
+
#
|
30
31
|
# Notes about write concern:
|
31
|
-
# These write concern options will be used for insert, update, and remove methods called on this
|
32
|
-
# Collection instance. If no value is provided, the default values set on this instance's DB will be used.
|
32
|
+
# These write concern options will be used for insert, update, and remove methods called on this
|
33
|
+
# Collection instance. If no value is provided, the default values set on this instance's DB will be used.
|
33
34
|
# These option values can be overridden for any invocation of insert, update, or remove.
|
34
35
|
#
|
35
36
|
# @option opts [:create_pk] :pk (BSON::ObjectId) A primary key factory to use
|
36
|
-
# other than the default BSON::ObjectId.
|
37
|
+
# other than the default BSON::ObjectId.
|
37
38
|
# @option opts [:primary, :secondary] :read The default read preference for queries
|
38
39
|
# initiates from this connection object. If +:secondary+ is chosen, reads will be sent
|
39
40
|
# to one of the closest available secondary nodes. If a secondary node cannot be located, the
|
@@ -57,30 +58,26 @@ module Mongo
|
|
57
58
|
db, name = name, db
|
58
59
|
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
raise TypeError, "new_name must be a string or symbol"
|
64
|
-
end
|
65
|
-
|
61
|
+
raise TypeError,
|
62
|
+
"Collection name must be a String or Symbol." unless [String, Symbol].include?(name.class)
|
66
63
|
name = name.to_s
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
if name.include?
|
72
|
-
raise Mongo::InvalidNSName,
|
73
|
-
|
74
|
-
if name.match(/^\./) or name.match(/\.$/)
|
75
|
-
raise Mongo::InvalidNSName, "collection names must not start or end with '.'"
|
65
|
+
raise Mongo::InvalidNSName,
|
66
|
+
"Collection names cannot be empty." if name.empty? || name.include?("..")
|
67
|
+
|
68
|
+
if name.include?("$")
|
69
|
+
raise Mongo::InvalidNSName,
|
70
|
+
"Collection names must not contain '$'" unless name =~ /((^\$cmd)|(oplog\.\$main))/
|
76
71
|
end
|
77
72
|
|
73
|
+
raise Mongo::InvalidNSName,
|
74
|
+
"Collection names must not start or end with '.'" if name.match(/^\./) || name.match(/\.$/)
|
75
|
+
|
76
|
+
pk_factory = nil
|
78
77
|
if opts.respond_to?(:create_pk) || !opts.is_a?(Hash)
|
79
78
|
warn "The method for specifying a primary key factory on a Collection has changed.\n" +
|
80
|
-
|
79
|
+
"Please specify it as an option (e.g., :pk => PkFactory)."
|
81
80
|
pk_factory = opts
|
82
|
-
else
|
83
|
-
pk_factory = nil
|
84
81
|
end
|
85
82
|
|
86
83
|
@db, @name = db, name
|
@@ -92,6 +89,7 @@ module Mongo
|
|
92
89
|
@write_concern = get_write_concern(opts, db)
|
93
90
|
@read = opts[:read] || @db.read
|
94
91
|
Mongo::ReadPreference::validate(@read)
|
92
|
+
@capped = opts[:capped]
|
95
93
|
@tag_sets = opts.fetch(:tag_sets, @db.tag_sets)
|
96
94
|
@acceptable_latency = opts.fetch(:acceptable_latency, @db.acceptable_latency)
|
97
95
|
end
|
@@ -106,7 +104,7 @@ module Mongo
|
|
106
104
|
#
|
107
105
|
# @return [Boolean]
|
108
106
|
def capped?
|
109
|
-
[1, true].include?
|
107
|
+
@capped ||= [1, true].include?(@db.command({:collstats => @name})['capped'])
|
110
108
|
end
|
111
109
|
|
112
110
|
# Return a sub-collection of this collection by name. If 'users' is a collection, then
|
@@ -315,10 +313,10 @@ module Mongo
|
|
315
313
|
# @return [ObjectId] the _id of the saved document.
|
316
314
|
#
|
317
315
|
# @option opts [Hash] :w, :j, :wtimeout, :fsync Set the write concern for this operation.
|
318
|
-
# :w > 0 will run a +getlasterror+ command on the database to report any assertion.
|
316
|
+
# :w > 0 will run a +getlasterror+ command on the database to report any assertion.
|
319
317
|
# :j will confirm a write has been committed to the journal,
|
320
318
|
# :wtimeout specifies how long to wait for write confirmation,
|
321
|
-
# :fsync will confirm that a write has been fsynced.
|
319
|
+
# :fsync will confirm that a write has been fsynced.
|
322
320
|
# Options provided here will override any write concern options set on this collection,
|
323
321
|
# its database object, or the current connection. See the options
|
324
322
|
# for DB#get_last_error.
|
@@ -351,23 +349,23 @@ module Mongo
|
|
351
349
|
# @option opts [Boolean] :j (false) Set journal acknowledgement
|
352
350
|
# @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout
|
353
351
|
# @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
|
354
|
-
#
|
352
|
+
#
|
355
353
|
# Notes on write concern:
|
356
354
|
# Options provided here will override any write concern options set on this collection,
|
357
|
-
# its database object, or the current connection. See the options for +DB#get_last_error+.
|
355
|
+
# its database object, or the current connection. See the options for +DB#get_last_error+.
|
358
356
|
#
|
359
357
|
# @option opts [Boolean] :continue_on_error (+false+) If true, then
|
360
358
|
# continue a bulk insert even if one of the documents inserted
|
361
359
|
# triggers a database assertion (as in a duplicate insert, for instance).
|
362
360
|
# If not acknowledging writes, the list of ids returned will
|
363
361
|
# include the object ids of all documents attempted on insert, even
|
364
|
-
# if some are rejected on error. When acknowledging writes, any error will raise an
|
362
|
+
# if some are rejected on error. When acknowledging writes, any error will raise an
|
365
363
|
# OperationFailure exception.
|
366
364
|
# MongoDB v2.0+.
|
367
365
|
# @option opts [Boolean] :collect_on_error (+false+) if true, then
|
368
366
|
# collects invalid documents as an array. Note that this option changes the result format.
|
369
367
|
#
|
370
|
-
# @raise [Mongo::OperationFailure] will be raised iff :w > 0 and the operation fails.
|
368
|
+
# @raise [Mongo::OperationFailure] will be raised iff :w > 0 and the operation fails.
|
371
369
|
#
|
372
370
|
# @core insert insert-instance_method
|
373
371
|
def insert(doc_or_docs, opts={})
|
@@ -392,7 +390,7 @@ module Mongo
|
|
392
390
|
#
|
393
391
|
# Notes on write concern:
|
394
392
|
# Options provided here will override any write concern options set on this collection,
|
395
|
-
# its database object, or the current connection. See the options for +DB#get_last_error+.
|
393
|
+
# its database object, or the current connection. See the options for +DB#get_last_error+.
|
396
394
|
#
|
397
395
|
# @example remove all documents from the 'users' collection:
|
398
396
|
# users.remove
|
@@ -446,7 +444,7 @@ module Mongo
|
|
446
444
|
#
|
447
445
|
# Notes on write concern:
|
448
446
|
# Options provided here will override any write concern options set on this collection,
|
449
|
-
# its database object, or the current connection. See the options for DB#get_last_error.
|
447
|
+
# its database object, or the current connection. See the options for DB#get_last_error.
|
450
448
|
#
|
451
449
|
# @return [Hash, true] Returns a Hash containing the last error object if acknowledging writes.
|
452
450
|
# Otherwise, returns true.
|
@@ -483,8 +481,9 @@ module Mongo
|
|
483
481
|
#
|
484
482
|
# @param [String, Array] spec
|
485
483
|
# should be either a single field name or an array of
|
486
|
-
# [field name,
|
487
|
-
# as Mongo::ASCENDING, Mongo::DESCENDING,
|
484
|
+
# [field name, type] pairs. Index types should be specified
|
485
|
+
# as Mongo::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D, Mongo::GEO2DSPHERE, Mongo::GEOHAYSTACK,
|
486
|
+
# Mongo::TEXT or Mongo::HASHED.
|
488
487
|
#
|
489
488
|
# Note that geospatial indexing only works with versions of MongoDB >= 1.3.3+. Keep in mind, too,
|
490
489
|
# that in order to geo-index a given field, that field must reference either an array or a sub-object
|
@@ -501,6 +500,8 @@ module Mongo
|
|
501
500
|
# feature is only available in MongoDB >= 1.3.2.
|
502
501
|
# @option opts [Boolean] :drop_dups (nil) If creating a unique index on a collection with pre-existing records,
|
503
502
|
# this option will keep the first document the database indexes and drop all subsequent with duplicate values.
|
503
|
+
# @option opts [Integer] :bucket_size (nil) For use with geoHaystack indexes. Number of documents to group
|
504
|
+
# together within a certain proximity to a given longitude and latitude.
|
504
505
|
# @option opts [Integer] :min (nil) specify the minimum longitude and latitude for a geo index.
|
505
506
|
# @option opts [Integer] :max (nil) specify the maximum longitude and latitude for a geo index.
|
506
507
|
#
|
@@ -525,11 +526,12 @@ module Mongo
|
|
525
526
|
#
|
526
527
|
# @core indexes create_index-instance_method
|
527
528
|
def create_index(spec, opts={})
|
528
|
-
opts[:dropDups]
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
name
|
529
|
+
opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
|
530
|
+
opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
|
531
|
+
field_spec = parse_index_spec(spec)
|
532
|
+
opts = opts.dup
|
533
|
+
name = opts.delete(:name) || generate_index_name(field_spec)
|
534
|
+
name = name.to_s if name
|
533
535
|
generate_indexes(field_spec, name, opts)
|
534
536
|
name
|
535
537
|
end
|
@@ -551,11 +553,12 @@ module Mongo
|
|
551
553
|
#
|
552
554
|
# @return [String] the name of the index.
|
553
555
|
def ensure_index(spec, opts={})
|
554
|
-
now
|
555
|
-
opts[:dropDups]
|
556
|
-
|
557
|
-
|
558
|
-
name
|
556
|
+
now = Time.now.utc.to_i
|
557
|
+
opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
|
558
|
+
opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
|
559
|
+
field_spec = parse_index_spec(spec)
|
560
|
+
name = opts[:name] || generate_index_name(field_spec)
|
561
|
+
name = name.to_s if name
|
559
562
|
|
560
563
|
if !@cache[name] || @cache[name] <= now
|
561
564
|
generate_indexes(field_spec, name, opts)
|
@@ -626,7 +629,7 @@ module Mongo
|
|
626
629
|
#
|
627
630
|
# @param [Array] pipeline Should be a single array of pipeline operator hashes.
|
628
631
|
#
|
629
|
-
# '$project' Reshapes a document stream by including fields, excluding fields, inserting computed fields,
|
632
|
+
# '$project' Reshapes a document stream by including fields, excluding fields, inserting computed fields,
|
630
633
|
# renaming fields,or creating/populating fields that hold sub-documents.
|
631
634
|
#
|
632
635
|
# '$match' Query-like interface for filtering documents out of the aggregation pipeline.
|
@@ -1017,11 +1020,13 @@ module Mongo
|
|
1017
1020
|
end
|
1018
1021
|
elsif spec.is_a?(Array) && spec.all? {|field| field.is_a?(Array) }
|
1019
1022
|
spec.each do |f|
|
1020
|
-
if
|
1023
|
+
if Mongo::INDEX_TYPES.include?(f[1])
|
1021
1024
|
field_spec[f[0].to_s] = f[1]
|
1022
1025
|
else
|
1023
1026
|
raise MongoArgumentError, "Invalid index field #{f[1].inspect}; " +
|
1024
|
-
"should be one of Mongo::ASCENDING (
|
1027
|
+
"should be one of Mongo::ASCENDING (#{Mongo::ASCENDING}), Mongo::DESCENDING (#{Mongo::DESCENDING}), " +
|
1028
|
+
"Mongo::GEOHAYSTACK ('#{Mongo::GEOHAYSTACK}'), Mongo::GEO2DSPHERE ('#{Mongo::GEO2DSPHERE}'), " +
|
1029
|
+
"Mongo::TEXT ('#{Mongo::TEXT}'), or Mongo::HASHED ('#{Mongo::HASHED}')"
|
1025
1030
|
end
|
1026
1031
|
end
|
1027
1032
|
else
|
@@ -1109,8 +1114,8 @@ module Mongo
|
|
1109
1114
|
|
1110
1115
|
def generate_index_name(spec)
|
1111
1116
|
indexes = []
|
1112
|
-
spec.each_pair do |field,
|
1113
|
-
indexes.push("#{field}_#{
|
1117
|
+
spec.each_pair do |field, type|
|
1118
|
+
indexes.push("#{field}_#{type}")
|
1114
1119
|
end
|
1115
1120
|
indexes.join("_")
|
1116
1121
|
end
|
data/lib/mongo/cursor.rb
CHANGED
@@ -6,12 +6,13 @@ module Mongo
|
|
6
6
|
include Mongo::Constants
|
7
7
|
include Mongo::Conversions
|
8
8
|
include Mongo::Logging
|
9
|
+
include Mongo::ReadPreference
|
9
10
|
|
10
11
|
attr_reader :collection, :selector, :fields,
|
11
12
|
:order, :hint, :snapshot, :timeout,
|
12
13
|
:full_collection_name, :transformer,
|
13
14
|
:options, :cursor_id, :show_disk_loc,
|
14
|
-
:comment, :read, :tag_sets
|
15
|
+
:comment, :read, :tag_sets, :acceptable_latency
|
15
16
|
|
16
17
|
# Create a new cursor.
|
17
18
|
#
|
@@ -471,6 +472,7 @@ module Mongo
|
|
471
472
|
nil, @options & OP_QUERY_EXHAUST != 0)
|
472
473
|
rescue ConnectionFailure => ex
|
473
474
|
socket.close if socket
|
475
|
+
@connection.unpin_pool
|
474
476
|
@connection.refresh
|
475
477
|
if tries < 3 && !@socket && (!@command || Mongo::Support::secondary_ok?(@selector))
|
476
478
|
tries += 1
|
@@ -483,6 +485,9 @@ module Mongo
|
|
483
485
|
ensure
|
484
486
|
socket.checkin unless @socket || socket.nil?
|
485
487
|
end
|
488
|
+
if !@socket && !@command
|
489
|
+
@connection.pin_pool(socket.pool, read_preference)
|
490
|
+
end
|
486
491
|
@returned += @n_received
|
487
492
|
@cache += results
|
488
493
|
@query_run = true
|
@@ -530,16 +535,15 @@ module Mongo
|
|
530
535
|
if @pool
|
531
536
|
socket = @pool.checkout
|
532
537
|
elsif @command && !Mongo::Support::secondary_ok?(@selector)
|
533
|
-
socket = @connection.checkout_reader(:primary)
|
538
|
+
socket = @connection.checkout_reader({:mode => :primary})
|
534
539
|
else
|
535
|
-
socket = @connection.checkout_reader(
|
540
|
+
socket = @connection.checkout_reader(read_preference)
|
536
541
|
end
|
537
542
|
rescue SystemStackError, NoMemoryError, SystemCallError => ex
|
538
543
|
@connection.close
|
539
544
|
raise ex
|
540
545
|
end
|
541
546
|
@pool = socket.pool
|
542
|
-
#puts "checkout_socket_from_connection caller:#{caller[0][/:in `([^']+)'/,1]} self:#{self.object_id} @pool.port:#{@pool.port}"
|
543
547
|
socket
|
544
548
|
end
|
545
549
|
|
data/lib/mongo/db.rb
CHANGED
@@ -14,6 +14,12 @@ module Mongo
|
|
14
14
|
SYSTEM_JS_COLLECTION = 'system.js'
|
15
15
|
SYSTEM_COMMAND_COLLECTION = '$cmd'
|
16
16
|
|
17
|
+
PROFILE_LEVEL = {
|
18
|
+
:off => 0,
|
19
|
+
:slow_only => 1,
|
20
|
+
:all => 2
|
21
|
+
}
|
22
|
+
|
17
23
|
# Counter for generating unique request ids.
|
18
24
|
@@current_request_id = 0
|
19
25
|
|
@@ -22,10 +28,24 @@ module Mongo
|
|
22
28
|
# collection that already exists, raises an error.
|
23
29
|
#
|
24
30
|
# Strict mode is disabled by default, but enabled (+true+) at any time.
|
25
|
-
|
31
|
+
#
|
32
|
+
# @deprecated Support for strict mode has been deprecated and will be
|
33
|
+
# removed in version 2.0 of the driver.
|
34
|
+
def strict=(value)
|
35
|
+
unless ENV['TEST_MODE']
|
36
|
+
warn "Support for strict mode has been deprecated and will be " +
|
37
|
+
"removed in version 2.0 of the driver."
|
38
|
+
end
|
39
|
+
@strict = value
|
40
|
+
end
|
26
41
|
|
27
42
|
# Returns the value of the +strict+ flag.
|
28
|
-
|
43
|
+
#
|
44
|
+
# @deprecated Support for strict mode has been deprecated and will be
|
45
|
+
# removed in version 2.0 of the driver.
|
46
|
+
def strict?
|
47
|
+
@strict
|
48
|
+
end
|
29
49
|
|
30
50
|
# The name of the database and the local write concern options.
|
31
51
|
attr_reader :name, :write_concern
|
@@ -45,8 +65,9 @@ module Mongo
|
|
45
65
|
# @param [Mongo::MongoClient] client a connection object pointing to MongoDB. Note
|
46
66
|
# that databases are usually instantiated via the MongoClient class. See the examples below.
|
47
67
|
#
|
48
|
-
# @option opts [Boolean] :strict (False) If true, collections
|
49
|
-
#
|
68
|
+
# @option opts [Boolean] :strict (False) [DEPRECATED] If true, collections existence checks are
|
69
|
+
# performed during a number of relevant operations. See DB#collection, DB#create_collection and
|
70
|
+
# DB#drop_collection.
|
50
71
|
#
|
51
72
|
# @option opts [Object, #create_pk(doc)] :pk (BSON::ObjectId) A primary key factory object,
|
52
73
|
# which should take a hash and return a hash which merges the original hash with any primary key
|
@@ -99,10 +120,8 @@ module Mongo
|
|
99
120
|
#
|
100
121
|
# @core authenticate authenticate-instance_method
|
101
122
|
def authenticate(username, password, save_auth=true)
|
102
|
-
if @connection.pool_size > 1
|
103
|
-
|
104
|
-
raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
|
105
|
-
end
|
123
|
+
if @connection.pool_size > 1 && !save_auth
|
124
|
+
raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
|
106
125
|
end
|
107
126
|
|
108
127
|
begin
|
@@ -126,17 +145,15 @@ module Mongo
|
|
126
145
|
auth['nonce'] = nonce
|
127
146
|
auth['key'] = Mongo::Support.auth_key(username, password, nonce)
|
128
147
|
if ok?(doc = self.command(auth, :check_response => false, :socket => opts[:socket]))
|
129
|
-
if save_auth
|
130
|
-
@connection.add_auth(@name, username, password)
|
131
|
-
end
|
132
|
-
true
|
148
|
+
@connection.add_auth(@name, username, password) if save_auth
|
133
149
|
else
|
134
150
|
message = "Failed to authenticate user '#{username}' on db '#{self.name}'"
|
135
151
|
raise Mongo::AuthenticationError.new(message, doc['code'], doc)
|
136
152
|
end
|
153
|
+
true
|
137
154
|
end
|
138
155
|
|
139
|
-
# Adds a stored Javascript function to the database which can executed
|
156
|
+
# Adds a stored Javascript function to the database which can executed
|
140
157
|
# server-side in map_reduce, db.eval and $where clauses.
|
141
158
|
#
|
142
159
|
# @param [String] function_name
|
@@ -146,7 +163,7 @@ module Mongo
|
|
146
163
|
def add_stored_function(function_name, code)
|
147
164
|
self[SYSTEM_JS_COLLECTION].save(
|
148
165
|
{
|
149
|
-
"_id" => function_name,
|
166
|
+
"_id" => function_name,
|
150
167
|
:value => BSON::Code.new(code)
|
151
168
|
}
|
152
169
|
)
|
@@ -159,11 +176,8 @@ module Mongo
|
|
159
176
|
#
|
160
177
|
# @return [Boolean]
|
161
178
|
def remove_stored_function(function_name)
|
162
|
-
|
163
|
-
|
164
|
-
else
|
165
|
-
return false
|
166
|
-
end
|
179
|
+
return false unless self[SYSTEM_JS_COLLECTION].find_one({"_id" => function_name})
|
180
|
+
self[SYSTEM_JS_COLLECTION].remove({"_id" => function_name}, :w => 1)
|
167
181
|
end
|
168
182
|
|
169
183
|
# Adds a user to this database for use with authentication. If the user already
|
@@ -181,7 +195,7 @@ module Mongo
|
|
181
195
|
user['pwd'] = Mongo::Support.hash_password(username, password)
|
182
196
|
user['readOnly'] = true if read_only;
|
183
197
|
users.save(user)
|
184
|
-
|
198
|
+
user
|
185
199
|
end
|
186
200
|
|
187
201
|
# Remove the given user from this database. Returns false if the user
|
@@ -194,7 +208,7 @@ module Mongo
|
|
194
208
|
if self[SYSTEM_USER_COLLECTION].find_one({:user => username})
|
195
209
|
self[SYSTEM_USER_COLLECTION].remove({:user => username}, :w => 1)
|
196
210
|
else
|
197
|
-
|
211
|
+
false
|
198
212
|
end
|
199
213
|
end
|
200
214
|
|
@@ -206,21 +220,17 @@ module Mongo
|
|
206
220
|
#
|
207
221
|
# @return [Boolean]
|
208
222
|
def logout(opts={})
|
209
|
-
if @connection.pool_size > 1
|
210
|
-
@connection.logout_pools(@name)
|
211
|
-
end
|
212
|
-
|
223
|
+
@connection.logout_pools(@name) if @connection.pool_size > 1
|
213
224
|
issue_logout(opts)
|
214
225
|
end
|
215
226
|
|
216
227
|
def issue_logout(opts={})
|
217
|
-
doc = command({:logout => 1}, :socket => opts[:socket])
|
218
|
-
if ok?(doc)
|
228
|
+
if ok?(doc = command({:logout => 1}, :socket => opts[:socket]))
|
219
229
|
@connection.remove_auth(@name)
|
220
|
-
true
|
221
230
|
else
|
222
|
-
raise MongoDBError, "
|
231
|
+
raise MongoDBError, "Error logging out: #{doc.inspect}"
|
223
232
|
end
|
233
|
+
true
|
224
234
|
end
|
225
235
|
|
226
236
|
# Get an array of collection names in this database.
|
@@ -278,20 +288,19 @@ module Mongo
|
|
278
288
|
# @return [Mongo::Collection]
|
279
289
|
def create_collection(name, opts={})
|
280
290
|
name = name.to_s
|
281
|
-
if collection_names.include?(name)
|
282
|
-
|
283
|
-
raise MongoDBError, "Collection #{name} already exists. " +
|
284
|
-
"Currently in strict mode."
|
285
|
-
else
|
286
|
-
return Collection.new(name, self, opts)
|
287
|
-
end
|
291
|
+
if strict? && collection_names.include?(name)
|
292
|
+
raise MongoDBError, "Collection '#{name}' already exists. (strict=true)"
|
288
293
|
end
|
289
294
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
+
begin
|
296
|
+
cmd = BSON::OrderedHash.new
|
297
|
+
cmd[:create] = name
|
298
|
+
doc = command(cmd.merge(opts || {}))
|
299
|
+
return Collection.new(name, self, :pk => @pk_factory) if ok?(doc)
|
300
|
+
rescue OperationFailure => e
|
301
|
+
return Collection.new(name, self, :pk => @pk_factory) if e.message =~ /exists/
|
302
|
+
raise e
|
303
|
+
end
|
295
304
|
raise MongoDBError, "Error creating collection: #{doc.inspect}"
|
296
305
|
end
|
297
306
|
|
@@ -306,8 +315,7 @@ module Mongo
|
|
306
315
|
# @return [Mongo::Collection]
|
307
316
|
def collection(name, opts={})
|
308
317
|
if strict? && !collection_names.include?(name.to_s)
|
309
|
-
raise
|
310
|
-
"Currently in strict mode."
|
318
|
+
raise MongoDBError, "Collection '#{name}' doesn't exist. (strict=true)"
|
311
319
|
else
|
312
320
|
opts = opts.dup
|
313
321
|
opts.merge!(:pk => @pk_factory) unless opts[:pk]
|
@@ -322,9 +330,12 @@ module Mongo
|
|
322
330
|
#
|
323
331
|
# @return [Boolean] +true+ on success or +false+ if the collection name doesn't exist.
|
324
332
|
def drop_collection(name)
|
325
|
-
return
|
326
|
-
|
327
|
-
|
333
|
+
return false if strict? && !collection_names.include?(name.to_s)
|
334
|
+
begin
|
335
|
+
ok?(command(:drop => name))
|
336
|
+
rescue OperationFailure => e
|
337
|
+
false
|
338
|
+
end
|
328
339
|
end
|
329
340
|
|
330
341
|
# Run the getlasterror command with the specified replication options.
|
@@ -342,7 +353,7 @@ module Mongo
|
|
342
353
|
cmd[:getlasterror] = 1
|
343
354
|
cmd.merge!(opts)
|
344
355
|
doc = command(cmd, :check_response => false)
|
345
|
-
raise MongoDBError, "
|
356
|
+
raise MongoDBError, "Error retrieving last error: #{doc.inspect}" unless ok?(doc)
|
346
357
|
doc
|
347
358
|
end
|
348
359
|
|
@@ -362,11 +373,7 @@ module Mongo
|
|
362
373
|
# @return [String, Nil] the text of the error or +nil+ if no error has occurred.
|
363
374
|
def previous_error
|
364
375
|
error = command(:getpreverror => 1)
|
365
|
-
|
366
|
-
error
|
367
|
-
else
|
368
|
-
nil
|
369
|
-
end
|
376
|
+
error["err"] ? error : nil
|
370
377
|
end
|
371
378
|
|
372
379
|
# Reset the error history of this database
|
@@ -393,19 +400,19 @@ module Mongo
|
|
393
400
|
# Evaluate a JavaScript expression in MongoDB.
|
394
401
|
#
|
395
402
|
# @param [String, Code] code a JavaScript expression to evaluate server-side.
|
396
|
-
# @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when
|
403
|
+
# @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when
|
397
404
|
# it's run on the server.
|
398
405
|
#
|
399
406
|
# @return [String] the return value of the function.
|
400
407
|
def eval(code, *args)
|
401
|
-
|
408
|
+
unless code.is_a?(BSON::Code)
|
402
409
|
code = BSON::Code.new(code)
|
403
410
|
end
|
404
411
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
doc = command(
|
412
|
+
cmd = BSON::OrderedHash.new
|
413
|
+
cmd[:$eval] = code
|
414
|
+
cmd[:args] = args
|
415
|
+
doc = command(cmd)
|
409
416
|
doc['retval']
|
410
417
|
end
|
411
418
|
|
@@ -418,10 +425,10 @@ module Mongo
|
|
418
425
|
#
|
419
426
|
# @raise MongoDBError if there's an error renaming the collection.
|
420
427
|
def rename_collection(from, to)
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
doc = DB.new('admin', @connection).command(
|
428
|
+
cmd = BSON::OrderedHash.new
|
429
|
+
cmd[:renameCollection] = "#{@name}.#{from}"
|
430
|
+
cmd[:to] = "#{@name}.#{to}"
|
431
|
+
doc = DB.new('admin', @connection).command(cmd, :check_response => false)
|
425
432
|
ok?(doc) || raise(MongoDBError, "Error renaming collection: #{doc.inspect}")
|
426
433
|
end
|
427
434
|
|
@@ -435,10 +442,10 @@ module Mongo
|
|
435
442
|
#
|
436
443
|
# @raise MongoDBError if there's an error dropping the index.
|
437
444
|
def drop_index(collection_name, index_name)
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
doc = command(
|
445
|
+
cmd = BSON::OrderedHash.new
|
446
|
+
cmd[:deleteIndexes] = collection_name
|
447
|
+
cmd[:index] = index_name.to_s
|
448
|
+
doc = command(cmd, :check_response => false)
|
442
449
|
ok?(doc) || raise(MongoDBError, "Error with drop_index command: #{doc.inspect}")
|
443
450
|
end
|
444
451
|
|
@@ -447,7 +454,7 @@ module Mongo
|
|
447
454
|
#
|
448
455
|
# @param [String] collection_name
|
449
456
|
#
|
450
|
-
# @return [Hash] keys are index names and the values are lists of [key,
|
457
|
+
# @return [Hash] keys are index names and the values are lists of [key, type] pairs
|
451
458
|
# defining the index.
|
452
459
|
def index_information(collection_name)
|
453
460
|
sel = {:ns => full_collection_name(collection_name)}
|
@@ -499,8 +506,9 @@ module Mongo
|
|
499
506
|
# @core commands command_instance-method
|
500
507
|
def command(selector, opts={})
|
501
508
|
check_response = opts.fetch(:check_response, true)
|
502
|
-
socket
|
503
|
-
raise MongoArgumentError, "
|
509
|
+
socket = opts[:socket]
|
510
|
+
raise MongoArgumentError, "Command must be given a selector" unless selector.is_a?(Hash) && !selector.empty?
|
511
|
+
|
504
512
|
if selector.keys.length > 1 && RUBY_VERSION < '1.9' && selector.class != BSON::OrderedHash
|
505
513
|
raise MongoArgumentError, "DB#command requires an OrderedHash when hash contains multiple keys"
|
506
514
|
end
|
@@ -513,19 +521,21 @@ module Mongo
|
|
513
521
|
end
|
514
522
|
|
515
523
|
begin
|
516
|
-
result = Cursor.new(
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
524
|
+
result = Cursor.new(
|
525
|
+
system_command_collection,
|
526
|
+
:limit => -1,
|
527
|
+
:selector => selector,
|
528
|
+
:socket => socket,
|
529
|
+
:read => read_pref,
|
530
|
+
:comment => opts[:comment]).next_document
|
522
531
|
rescue OperationFailure => ex
|
523
532
|
raise OperationFailure, "Database command '#{selector.keys.first}' failed: #{ex.message}"
|
524
533
|
end
|
525
534
|
|
526
|
-
|
527
|
-
|
528
|
-
|
535
|
+
raise OperationFailure,
|
536
|
+
"Database command '#{selector.keys.first}' failed: returned null." unless result
|
537
|
+
|
538
|
+
if check_response && !ok?(result)
|
529
539
|
message = "Database command '#{selector.keys.first}' failed: ("
|
530
540
|
message << result.map do |key, value|
|
531
541
|
"#{key}: '#{value}'"
|
@@ -533,9 +543,9 @@ module Mongo
|
|
533
543
|
message << ').'
|
534
544
|
code = result['code'] || result['assertionCode']
|
535
545
|
raise OperationFailure.new(message, code, result)
|
536
|
-
else
|
537
|
-
result
|
538
546
|
end
|
547
|
+
|
548
|
+
result
|
539
549
|
end
|
540
550
|
|
541
551
|
# A shortcut returning db plus dot plus collection name.
|
@@ -558,9 +568,8 @@ module Mongo
|
|
558
568
|
#
|
559
569
|
# @raise [MongoArgumentError] if the primary key factory has already been set.
|
560
570
|
def pk_factory=(pk_factory)
|
561
|
-
|
562
|
-
|
563
|
-
end
|
571
|
+
raise MongoArgumentError,
|
572
|
+
"Cannot change primary key factory once it's been set" if @pk_factory
|
564
573
|
|
565
574
|
@pk_factory = pk_factory
|
566
575
|
end
|
@@ -572,20 +581,15 @@ module Mongo
|
|
572
581
|
#
|
573
582
|
# @core profiling profiling_level-instance_method
|
574
583
|
def profiling_level
|
575
|
-
|
576
|
-
|
577
|
-
doc = command(
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
when 2
|
585
|
-
:all
|
586
|
-
else
|
587
|
-
raise "Error: illegal profiling level value #{doc['was']}"
|
588
|
-
end
|
584
|
+
cmd = BSON::OrderedHash.new
|
585
|
+
cmd[:profile] = -1
|
586
|
+
doc = command(cmd, :check_response => false)
|
587
|
+
|
588
|
+
raise "Error with profile command: #{doc.inspect}" unless ok?(doc)
|
589
|
+
|
590
|
+
level_sym = PROFILE_LEVEL.invert[doc['was'].to_i]
|
591
|
+
raise "Error: illegal profiling level value #{doc['was']}" unless level_sym
|
592
|
+
level_sym
|
589
593
|
end
|
590
594
|
|
591
595
|
# Set this database's profiling level. If profiling is enabled, you can
|
@@ -593,18 +597,9 @@ module Mongo
|
|
593
597
|
#
|
594
598
|
# @param [Symbol] level acceptable options are +:off+, +:slow_only+, or +:all+.
|
595
599
|
def profiling_level=(level)
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
0
|
600
|
-
when :slow_only
|
601
|
-
1
|
602
|
-
when :all
|
603
|
-
2
|
604
|
-
else
|
605
|
-
raise "Error: illegal profiling level value #{level}"
|
606
|
-
end
|
607
|
-
doc = command(oh, :check_response => false)
|
600
|
+
cmd = BSON::OrderedHash.new
|
601
|
+
cmd[:profile] = PROFILE_LEVEL[level]
|
602
|
+
doc = command(cmd, :check_response => false)
|
608
603
|
ok?(doc) || raise(MongoDBError, "Error with profile command: #{doc.inspect}")
|
609
604
|
end
|
610
605
|
|
@@ -628,9 +623,9 @@ module Mongo
|
|
628
623
|
cmd[:validate] = name
|
629
624
|
cmd[:full] = true
|
630
625
|
doc = command(cmd, :check_response => false)
|
631
|
-
|
632
|
-
|
633
|
-
|
626
|
+
|
627
|
+
raise MongoDBError, "Error with validate command: #{doc.inspect}" unless ok?(doc)
|
628
|
+
|
634
629
|
if (doc.has_key?('valid') && !doc['valid']) || (doc['result'] =~ /\b(exception|corrupt)\b/i)
|
635
630
|
raise MongoDBError, "Error: invalid collection #{name}: #{doc.inspect}"
|
636
631
|
end
|