mongo 2.13.3 → 2.14.0.rc1
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +1 -1
- data/lib/mongo/address.rb +1 -1
- data/lib/mongo/bulk_write.rb +17 -0
- data/lib/mongo/caching_cursor.rb +74 -0
- data/lib/mongo/client.rb +47 -8
- data/lib/mongo/cluster/topology/single.rb +1 -1
- data/lib/mongo/cluster.rb +3 -3
- data/lib/mongo/collection/view/aggregation.rb +25 -4
- data/lib/mongo/collection/view/builder/find_command.rb +38 -18
- data/lib/mongo/collection/view/explainable.rb +27 -8
- data/lib/mongo/collection/view/iterable.rb +72 -12
- data/lib/mongo/collection/view/readable.rb +12 -2
- data/lib/mongo/collection/view/writable.rb +15 -1
- data/lib/mongo/collection/view.rb +24 -20
- data/lib/mongo/collection.rb +26 -2
- data/lib/mongo/crypt/encryption_io.rb +6 -6
- data/lib/mongo/cursor.rb +1 -0
- data/lib/mongo/database/view.rb +1 -1
- data/lib/mongo/database.rb +8 -14
- data/lib/mongo/error/invalid_read_concern.rb +28 -0
- data/lib/mongo/error/server_certificate_revoked.rb +22 -0
- data/lib/mongo/error/unsupported_option.rb +14 -12
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +37 -37
- data/lib/mongo/lint.rb +2 -1
- data/lib/mongo/logger.rb +3 -3
- data/lib/mongo/operation/aggregate/result.rb +9 -8
- data/lib/mongo/operation/collections_info/command.rb +0 -5
- data/lib/mongo/operation/collections_info/result.rb +3 -16
- data/lib/mongo/operation/delete/bulk_result.rb +2 -0
- data/lib/mongo/operation/delete/result.rb +3 -0
- data/lib/mongo/operation/explain/command.rb +4 -0
- data/lib/mongo/operation/explain/legacy.rb +4 -0
- data/lib/mongo/operation/explain/op_msg.rb +6 -0
- data/lib/mongo/operation/explain/result.rb +3 -0
- data/lib/mongo/operation/find/legacy/result.rb +2 -0
- data/lib/mongo/operation/find/result.rb +3 -0
- data/lib/mongo/operation/get_more/result.rb +3 -0
- data/lib/mongo/operation/indexes/result.rb +5 -0
- data/lib/mongo/operation/insert/bulk_result.rb +5 -0
- data/lib/mongo/operation/insert/result.rb +5 -0
- data/lib/mongo/operation/list_collections/result.rb +5 -0
- data/lib/mongo/operation/map_reduce/result.rb +10 -0
- data/lib/mongo/operation/parallel_scan/command.rb +2 -1
- data/lib/mongo/operation/parallel_scan/result.rb +4 -0
- data/lib/mongo/operation/result.rb +35 -6
- data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
- data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
- data/lib/mongo/operation/shared/executable.rb +1 -0
- data/lib/mongo/operation/shared/idable.rb +2 -1
- data/lib/mongo/operation/shared/limited.rb +1 -0
- data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
- data/lib/mongo/operation/shared/read_preference_supported.rb +36 -38
- data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +3 -3
- data/lib/mongo/operation/shared/specifiable.rb +1 -0
- data/lib/mongo/operation/shared/write.rb +1 -0
- data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
- data/lib/mongo/operation/update/legacy/result.rb +7 -0
- data/lib/mongo/operation/update/result.rb +8 -0
- data/lib/mongo/operation/users_info/result.rb +3 -0
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/protocol/query.rb +11 -11
- data/lib/mongo/query_cache.rb +242 -0
- data/lib/mongo/retryable.rb +8 -1
- data/lib/mongo/server/connection_common.rb +2 -2
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/monitor/connection.rb +3 -3
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/pending_connection.rb +2 -2
- data/lib/mongo/server/push_monitor.rb +1 -1
- data/lib/mongo/server.rb +5 -1
- data/lib/mongo/server_selector/base.rb +5 -1
- data/lib/mongo/server_selector/secondary_preferred.rb +7 -2
- data/lib/mongo/session.rb +3 -0
- data/lib/mongo/socket/ocsp_cache.rb +97 -0
- data/lib/mongo/socket/ocsp_verifier.rb +368 -0
- data/lib/mongo/socket/ssl.rb +45 -24
- data/lib/mongo/socket.rb +6 -4
- data/lib/mongo/srv/monitor.rb +7 -13
- data/lib/mongo/srv/resolver.rb +14 -10
- data/lib/mongo/timeout.rb +2 -0
- data/lib/mongo/uri/options_mapper.rb +582 -0
- data/lib/mongo/uri/srv_protocol.rb +3 -2
- data/lib/mongo/uri.rb +21 -390
- data/lib/mongo/utils.rb +12 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +9 -0
- data/spec/NOTES.aws-auth.md +12 -7
- data/spec/README.md +56 -1
- data/spec/integration/bson_symbol_spec.rb +2 -4
- data/spec/integration/bulk_write_spec.rb +48 -0
- data/spec/integration/client_authentication_options_spec.rb +55 -28
- data/spec/integration/connection_pool_populator_spec.rb +3 -1
- data/spec/integration/cursor_reaping_spec.rb +53 -17
- data/spec/integration/ocsp_connectivity_spec.rb +26 -0
- data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
- data/spec/integration/ocsp_verifier_spec.rb +334 -0
- data/spec/integration/query_cache_spec.rb +1045 -0
- data/spec/integration/query_cache_transactions_spec.rb +179 -0
- data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
- data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
- data/spec/integration/sdam_error_handling_spec.rb +69 -18
- data/spec/integration/sdam_events_spec.rb +7 -8
- data/spec/integration/server_selection_spec.rb +36 -0
- data/spec/integration/srv_monitoring_spec.rb +38 -3
- data/spec/integration/srv_spec.rb +56 -0
- data/spec/lite_spec_helper.rb +4 -2
- data/spec/mongo/address_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +70 -0
- data/spec/mongo/client_construction_spec.rb +54 -1
- data/spec/mongo/client_encryption_spec.rb +10 -16
- data/spec/mongo/client_spec.rb +40 -0
- data/spec/mongo/cluster/topology/single_spec.rb +14 -5
- data/spec/mongo/cluster_spec.rb +3 -0
- data/spec/mongo/collection/view/explainable_spec.rb +87 -4
- data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
- data/spec/mongo/collection_spec.rb +60 -0
- data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
- data/spec/mongo/database_spec.rb +44 -64
- data/spec/mongo/error/no_server_available_spec.rb +1 -1
- data/spec/mongo/index/view_spec.rb +2 -4
- data/spec/mongo/logger_spec.rb +13 -11
- data/spec/mongo/operation/read_preference_legacy_spec.rb +19 -9
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
- data/spec/mongo/query_cache_spec.rb +279 -0
- data/spec/mongo/server/app_metadata_shared.rb +7 -33
- data/spec/mongo/server/connection_pool_spec.rb +7 -3
- data/spec/mongo/server/connection_spec.rb +14 -7
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/socket_spec.rb +1 -1
- data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
- data/spec/mongo/uri_option_parsing_spec.rb +11 -11
- data/spec/mongo/uri_spec.rb +68 -41
- data/spec/mongo/utils_spec.rb +39 -0
- data/spec/runners/auth.rb +3 -0
- data/spec/runners/connection_string.rb +35 -124
- data/spec/runners/transactions/operation.rb +2 -13
- data/spec/spec_tests/cmap_spec.rb +7 -3
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
- data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
- data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
- data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
- data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
- data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
- data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
- data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
- data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
- data/spec/spec_tests/uri_options_spec.rb +31 -33
- data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
- data/spec/support/certificates/atlas-ocsp.crt +41 -0
- data/spec/support/client_registry.rb +4 -8
- data/spec/support/client_registry_macros.rb +4 -4
- data/spec/support/common_shortcuts.rb +45 -0
- data/spec/support/constraints.rb +23 -0
- data/spec/support/lite_constraints.rb +24 -0
- data/spec/support/matchers.rb +16 -0
- data/spec/support/ocsp +1 -0
- data/spec/support/session_registry.rb +52 -0
- data/spec/support/spec_config.rb +22 -12
- data/spec/support/spec_setup.rb +38 -48
- data/spec/support/utils.rb +19 -1
- data.tar.gz.sig +1 -3
- metadata +938 -933
- metadata.gz.sig +0 -0
- data/spec/integration/secondary_reads_spec.rb +0 -102
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -221
- data/spec/shared/lib/mrss/constraints.rb +0 -346
- data/spec/shared/lib/mrss/docker_runner.rb +0 -265
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -191
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -115
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -152
- data/spec/shared/lib/mrss/utils.rb +0 -15
- data/spec/shared/share/Dockerfile.erb +0 -231
- data/spec/shared/shlib/distro.sh +0 -73
- data/spec/shared/shlib/server.sh +0 -290
- data/spec/shared/shlib/set_env.sh +0 -128
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 493d0cb29d48d80c7fe4c87691500c078b6667bd214dcc021e0074938229be83
|
4
|
+
data.tar.gz: 44507b68e42abadad6987f50c3b3ae1b8ae70f046812607755ffbe292013ccc4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea39c71265e24349b018a8e5f5699b556d1ed43107135da46790ad8496c4bcd8a3917ca6fd0c7b405c5e6cff968d6e18cedf35ac33fe660f19f2869f663cdf64
|
7
|
+
data.tar.gz: 30ca549b30bec1889f622f7002658c918b6686e417bd9a636777bbc7f321d06094278b5a7ff4b04a9395f61bf90e28f99f26ff9ec404b0e3687dbc1b4a77ec1f
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/mongo/address/ipv4.rb
CHANGED
@@ -81,7 +81,7 @@ module Mongo
|
|
81
81
|
# @param [ Hash ] options The options.
|
82
82
|
#
|
83
83
|
# @option options [ Float ] :connect_timeout Connect timeout.
|
84
|
-
# @option options [ true | false ] :ssl Whether to use
|
84
|
+
# @option options [ true | false ] :ssl Whether to use TLS.
|
85
85
|
# @option options [ String ] :ssl_ca_cert
|
86
86
|
# Same as the corresponding Client/Socket::SSL option.
|
87
87
|
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
|
data/lib/mongo/address/ipv6.rb
CHANGED
@@ -95,7 +95,7 @@ module Mongo
|
|
95
95
|
# @param [ Hash ] options The options.
|
96
96
|
#
|
97
97
|
# @option options [ Float ] :connect_timeout Connect timeout.
|
98
|
-
# @option options [ true | false ] :ssl Whether to use
|
98
|
+
# @option options [ true | false ] :ssl Whether to use TLS.
|
99
99
|
# @option options [ String ] :ssl_ca_cert
|
100
100
|
# Same as the corresponding Client/Socket::SSL option.
|
101
101
|
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
|
data/lib/mongo/address.rb
CHANGED
@@ -286,7 +286,7 @@ module Mongo
|
|
286
286
|
rescue IOError, SystemCallError => e
|
287
287
|
raise Error::SocketError, "#{e.class}: #{e} (for #{self})"
|
288
288
|
rescue OpenSSL::SSL::SSLError => e
|
289
|
-
raise Error::SocketError, "#{e.class}: #{e} (for #{self})"
|
289
|
+
raise Error::SocketError, "#{e.class}: #{e} (for #{self}) (#{SSL_ERROR})"
|
290
290
|
end
|
291
291
|
end
|
292
292
|
end
|
data/lib/mongo/bulk_write.rb
CHANGED
@@ -195,6 +195,13 @@ module Mongo
|
|
195
195
|
end
|
196
196
|
end
|
197
197
|
end
|
198
|
+
# With OP_MSG (3.6+ servers), the size of each section in the message
|
199
|
+
# is independently capped at 16m and each bulk operation becomes
|
200
|
+
# its own section. The size of the entire bulk write is limited to 48m.
|
201
|
+
# With OP_QUERY (pre-3.6 servers), the entire bulk write is sent as a
|
202
|
+
# single document and is thus subject to the 16m document size limit.
|
203
|
+
# This means the splits differ between pre-3.6 and 3.6+ servers, with
|
204
|
+
# 3.6+ servers being able to split less.
|
198
205
|
rescue Error::MaxBSONSize, Error::MaxMessageSize => e
|
199
206
|
raise e if values.size <= 1
|
200
207
|
unpin_maybe(session) do
|
@@ -214,27 +221,37 @@ module Mongo
|
|
214
221
|
end
|
215
222
|
|
216
223
|
def delete_one(documents, connection, operation_id, session, txn_num)
|
224
|
+
QueryCache.clear_namespace(collection.namespace)
|
225
|
+
|
217
226
|
spec = base_spec(operation_id, session).merge(:deletes => documents, :txn_num => txn_num)
|
218
227
|
Operation::Delete.new(spec).bulk_execute(connection, client: client)
|
219
228
|
end
|
220
229
|
|
221
230
|
def delete_many(documents, connection, operation_id, session, txn_num)
|
231
|
+
QueryCache.clear_namespace(collection.namespace)
|
232
|
+
|
222
233
|
spec = base_spec(operation_id, session).merge(:deletes => documents)
|
223
234
|
Operation::Delete.new(spec).bulk_execute(connection, client: client)
|
224
235
|
end
|
225
236
|
|
226
237
|
def insert_one(documents, connection, operation_id, session, txn_num)
|
238
|
+
QueryCache.clear_namespace(collection.namespace)
|
239
|
+
|
227
240
|
spec = base_spec(operation_id, session).merge(:documents => documents, :txn_num => txn_num)
|
228
241
|
Operation::Insert.new(spec).bulk_execute(connection, client: client)
|
229
242
|
end
|
230
243
|
|
231
244
|
def update_one(documents, connection, operation_id, session, txn_num)
|
245
|
+
QueryCache.clear_namespace(collection.namespace)
|
246
|
+
|
232
247
|
spec = base_spec(operation_id, session).merge(:updates => documents, :txn_num => txn_num)
|
233
248
|
Operation::Update.new(spec).bulk_execute(connection, client: client)
|
234
249
|
end
|
235
250
|
alias :replace_one :update_one
|
236
251
|
|
237
252
|
def update_many(documents, connection, operation_id, session, txn_num)
|
253
|
+
QueryCache.clear_namespace(collection.namespace)
|
254
|
+
|
238
255
|
spec = base_spec(operation_id, session).merge(:updates => documents)
|
239
256
|
Operation::Update.new(spec).bulk_execute(connection, client: client)
|
240
257
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright (C) 2020 MongoDB Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Mongo
|
16
|
+
|
17
|
+
# A Cursor that attempts to load documents from memory first before hitting
|
18
|
+
# the database if the same query has already been executed.
|
19
|
+
#
|
20
|
+
# @api semiprivate
|
21
|
+
class CachingCursor < Cursor
|
22
|
+
|
23
|
+
# @return [ Array <BSON::Document> ] The cursor's cached documents.
|
24
|
+
# @api private
|
25
|
+
attr_reader :cached_docs
|
26
|
+
|
27
|
+
# We iterate over the cached documents if they exist already in the
|
28
|
+
# cursor otherwise proceed as normal.
|
29
|
+
#
|
30
|
+
# @example Iterate over the documents.
|
31
|
+
# cursor.each do |doc|
|
32
|
+
# # ...
|
33
|
+
# end
|
34
|
+
def each
|
35
|
+
if @cached_docs
|
36
|
+
@cached_docs.each do |doc|
|
37
|
+
yield doc
|
38
|
+
end
|
39
|
+
|
40
|
+
unless closed?
|
41
|
+
# StopIteration raised by try_next ends this loop.
|
42
|
+
loop do
|
43
|
+
document = try_next
|
44
|
+
yield document if document
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get a human-readable string representation of +Cursor+.
|
53
|
+
#
|
54
|
+
# @example Inspect the cursor.
|
55
|
+
# cursor.inspect
|
56
|
+
#
|
57
|
+
# @return [ String ] A string representation of a +Cursor+ instance.
|
58
|
+
def inspect
|
59
|
+
"#<Mongo::CachingCursor:0x#{object_id} @view=#{@view.inspect}>"
|
60
|
+
end
|
61
|
+
|
62
|
+
# Acquires the next document for cursor iteration and then
|
63
|
+
# inserts that document in the @cached_docs array.
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
def try_next
|
67
|
+
@cached_docs ||= []
|
68
|
+
document = super
|
69
|
+
@cached_docs << document if document
|
70
|
+
|
71
|
+
document
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/mongo/client.rb
CHANGED
@@ -101,6 +101,7 @@ module Mongo
|
|
101
101
|
:ssl_verify,
|
102
102
|
:ssl_verify_certificate,
|
103
103
|
:ssl_verify_hostname,
|
104
|
+
:ssl_verify_ocsp_endpoint,
|
104
105
|
:truncate_logs,
|
105
106
|
:user,
|
106
107
|
:wait_queue_timeout,
|
@@ -315,7 +316,7 @@ module Mongo
|
|
315
316
|
# for selecting a server for an operation.
|
316
317
|
# @option options [ Float ] :socket_timeout The timeout, in seconds, to
|
317
318
|
# execute operations on a socket.
|
318
|
-
# @option options [ true, false ] :ssl Whether to use
|
319
|
+
# @option options [ true, false ] :ssl Whether to use TLS.
|
319
320
|
# @option options [ String ] :ssl_ca_cert The file containing concatenated
|
320
321
|
# certificate authority certificates used to validate certs passed from the
|
321
322
|
# other end of the connection. Intermediate certificates should NOT be
|
@@ -462,6 +463,8 @@ module Mongo
|
|
462
463
|
@srv_records = nil
|
463
464
|
end
|
464
465
|
|
466
|
+
options = self.class.canonicalize_ruby_options(options)
|
467
|
+
|
465
468
|
# Special handling for sdam_proc as it is only used during client
|
466
469
|
# construction
|
467
470
|
sdam_proc = options.delete(:sdam_proc)
|
@@ -478,6 +481,12 @@ module Mongo
|
|
478
481
|
end
|
479
482
|
options = merged_options
|
480
483
|
|
484
|
+
options.keys.each do |k|
|
485
|
+
if options[k].nil?
|
486
|
+
options.delete(k)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
481
490
|
@options = validate_new_options!(options)
|
482
491
|
=begin WriteConcern object support
|
483
492
|
if @options[:write_concern].is_a?(WriteConcern::Base)
|
@@ -605,15 +614,12 @@ module Mongo
|
|
605
614
|
|
606
615
|
# Get a summary of the client state.
|
607
616
|
#
|
608
|
-
# @note
|
617
|
+
# @note The exact format and layout of the returned summary string is
|
618
|
+
# not part of the driver's public API and may be changed at any time.
|
609
619
|
#
|
610
|
-
# @
|
611
|
-
# client.summary
|
612
|
-
#
|
613
|
-
# @return [ String ] Summary string.
|
620
|
+
# @return [ String ] The summary string.
|
614
621
|
#
|
615
622
|
# @since 2.7.0
|
616
|
-
# @api experimental
|
617
623
|
def summary
|
618
624
|
"#<Client cluster=#{cluster.summary}>"
|
619
625
|
end
|
@@ -769,7 +775,6 @@ module Mongo
|
|
769
775
|
options[:read_concern]
|
770
776
|
end
|
771
777
|
|
772
|
-
|
773
778
|
# Get the write concern for this client. If no option was provided, then a
|
774
779
|
# default single server acknowledgement will be used.
|
775
780
|
#
|
@@ -1022,6 +1027,23 @@ module Mongo
|
|
1022
1027
|
end
|
1023
1028
|
end
|
1024
1029
|
|
1030
|
+
class << self
|
1031
|
+
# Lowercases auth mechanism properties, if given, in the specified
|
1032
|
+
# options, then converts the options to an instance of Options::Redacted.
|
1033
|
+
#
|
1034
|
+
# @api private
|
1035
|
+
def canonicalize_ruby_options(options)
|
1036
|
+
Options::Redacted.new(Hash[options.map do |k, v|
|
1037
|
+
if k == :auth_mech_properties || k == 'auth_mech_properties'
|
1038
|
+
if v
|
1039
|
+
v = Hash[v.map { |pk, pv| [pk.downcase, pv] }]
|
1040
|
+
end
|
1041
|
+
end
|
1042
|
+
[k, v]
|
1043
|
+
end])
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
|
1025
1047
|
private
|
1026
1048
|
|
1027
1049
|
# Create a new encrypter object using the client's auto encryption options
|
@@ -1107,6 +1129,23 @@ module Mongo
|
|
1107
1129
|
# but does not check for interactions between combinations of options.
|
1108
1130
|
def validate_new_options!(opts = Options::Redacted.new)
|
1109
1131
|
return Options::Redacted.new unless opts
|
1132
|
+
if opts[:read_concern]
|
1133
|
+
# Raise an error for non user-settable options
|
1134
|
+
if opts[:read_concern][:after_cluster_time]
|
1135
|
+
raise Mongo::Error::InvalidReadConcern.new(
|
1136
|
+
'The after_cluster_time read_concern option cannot be specified by the user'
|
1137
|
+
)
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
given_keys = opts[:read_concern].keys.map(&:to_s)
|
1141
|
+
allowed_keys = ['level']
|
1142
|
+
invalid_keys = given_keys - allowed_keys
|
1143
|
+
# Warn that options are invalid but keep it and forward to the server
|
1144
|
+
unless invalid_keys.empty?
|
1145
|
+
log_warn("Read concern has invalid keys: #{invalid_keys.join(',')}.")
|
1146
|
+
end
|
1147
|
+
end
|
1148
|
+
|
1110
1149
|
Lint.validate_underscore_read_preference(opts[:read])
|
1111
1150
|
Lint.validate_read_concern_option(opts[:read_concern])
|
1112
1151
|
opts.each.inject(Options::Redacted.new) do |_options, (k, v)|
|
@@ -133,7 +133,7 @@ module Mongo
|
|
133
133
|
|
134
134
|
def validate_options(options, cluster)
|
135
135
|
if cluster.servers_list.length > 1
|
136
|
-
raise ArgumentError,
|
136
|
+
raise ArgumentError, "Cannot instantiate a single topology with more than one server in the cluster: #{cluster.servers_list.map(&:address).map(&:seed).join(', ')}"
|
137
137
|
end
|
138
138
|
|
139
139
|
super(options, cluster)
|
data/lib/mongo/cluster.rb
CHANGED
@@ -950,9 +950,9 @@ module Mongo
|
|
950
950
|
# Start SRV monitor
|
951
951
|
@srv_monitor_lock.synchronize do
|
952
952
|
unless @srv_monitor
|
953
|
-
monitor_options = options.merge(
|
954
|
-
timeout: options[:connect_timeout] || Server::CONNECT_TIMEOUT)
|
955
|
-
@srv_monitor = _srv_monitor = Srv::Monitor.new(self, monitor_options)
|
953
|
+
monitor_options = Utils.shallow_symbolize_keys(options.merge(
|
954
|
+
timeout: options[:connect_timeout] || Server::CONNECT_TIMEOUT))
|
955
|
+
@srv_monitor = _srv_monitor = Srv::Monitor.new(self, **monitor_options)
|
956
956
|
finalizer = lambda do
|
957
957
|
_srv_monitor.stop!
|
958
958
|
end
|
@@ -89,6 +89,16 @@ module Mongo
|
|
89
89
|
self.class.new(view, pipeline, options.merge(explain: true)).first
|
90
90
|
end
|
91
91
|
|
92
|
+
# Whether this aggregation will write its result to a database collection.
|
93
|
+
#
|
94
|
+
# @return [ Boolean ] Whether the aggregation will write its result
|
95
|
+
# to a collection.
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def write?
|
99
|
+
pipeline.any? { |op| op.key?('$out') || op.key?(:$out) || op.key?('$merge') || op.key?(:$merge) }
|
100
|
+
end
|
101
|
+
|
92
102
|
private
|
93
103
|
|
94
104
|
def server_selector
|
@@ -114,10 +124,6 @@ module Mongo
|
|
114
124
|
description.standalone? || description.mongos? || description.primary? || secondary_ok?
|
115
125
|
end
|
116
126
|
|
117
|
-
def write?
|
118
|
-
pipeline.any? { |op| op.key?('$out') || op.key?(:$out) || op.key?('$merge') || op.key?(:$merge) }
|
119
|
-
end
|
120
|
-
|
121
127
|
def secondary_ok?
|
122
128
|
!write?
|
123
129
|
end
|
@@ -136,6 +142,21 @@ module Mongo
|
|
136
142
|
raise Error::UnsupportedCollation.new
|
137
143
|
end
|
138
144
|
end
|
145
|
+
|
146
|
+
# Skip, sort, limit, projection are specified as pipeline stages
|
147
|
+
# rather than as options.
|
148
|
+
def cache_options
|
149
|
+
{
|
150
|
+
namespace: collection.namespace,
|
151
|
+
selector: pipeline,
|
152
|
+
read_concern: view.read_concern,
|
153
|
+
read_preference: view.read_preference,
|
154
|
+
collation: options[:collation],
|
155
|
+
# Aggregations can read documents from more than one collection,
|
156
|
+
# so they will be cleared on every write operation.
|
157
|
+
multi_collection: true,
|
158
|
+
}
|
159
|
+
end
|
139
160
|
end
|
140
161
|
end
|
141
162
|
end
|
@@ -52,21 +52,6 @@ module Mongo
|
|
52
52
|
collation: 'collation'
|
53
53
|
).freeze
|
54
54
|
|
55
|
-
def_delegators :@view, :collection, :database, :filter, :options, :read
|
56
|
-
|
57
|
-
# Get the specification for an explain command that wraps the find
|
58
|
-
# command.
|
59
|
-
#
|
60
|
-
# @example Get the explain spec.
|
61
|
-
# builder.explain_specification
|
62
|
-
#
|
63
|
-
# @return [ Hash ] The specification.
|
64
|
-
#
|
65
|
-
# @since 2.2.0
|
66
|
-
def explain_specification
|
67
|
-
{ selector: { explain: find_command }, db_name: database.name, read: read, session: @session }
|
68
|
-
end
|
69
|
-
|
70
55
|
# Create the find command builder.
|
71
56
|
#
|
72
57
|
# @example Create the find command builder.
|
@@ -81,6 +66,8 @@ module Mongo
|
|
81
66
|
@session = session
|
82
67
|
end
|
83
68
|
|
69
|
+
def_delegators :@view, :collection, :database, :filter, :options, :read
|
70
|
+
|
84
71
|
# Get the specification to pass to the find command operation.
|
85
72
|
#
|
86
73
|
# @example Get the specification.
|
@@ -90,18 +77,51 @@ module Mongo
|
|
90
77
|
#
|
91
78
|
# @since 2.2.0
|
92
79
|
def specification
|
93
|
-
{
|
80
|
+
{
|
81
|
+
selector: find_command,
|
82
|
+
db_name: database.name,
|
83
|
+
read: read,
|
84
|
+
session: @session,
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Get the specification for an explain command that wraps the find
|
89
|
+
# command.
|
90
|
+
#
|
91
|
+
# @example Get the explain spec.
|
92
|
+
# builder.explain_specification
|
93
|
+
#
|
94
|
+
# @return [ Hash ] The specification.
|
95
|
+
#
|
96
|
+
# @since 2.2.0
|
97
|
+
def explain_specification
|
98
|
+
{
|
99
|
+
selector: {
|
100
|
+
explain: find_command,
|
101
|
+
},
|
102
|
+
db_name: database.name,
|
103
|
+
read: read,
|
104
|
+
session: @session,
|
105
|
+
# We should always have options{:explain] set if we are explaining.
|
106
|
+
# The explain field is not sent to the server, it will be
|
107
|
+
# processed in the operation layer.
|
108
|
+
explain: options[:explain],
|
109
|
+
}
|
94
110
|
end
|
95
111
|
|
96
112
|
private
|
97
113
|
|
98
114
|
def find_command
|
99
|
-
document = BSON::Document.new(
|
115
|
+
document = BSON::Document.new(
|
116
|
+
find: collection.name,
|
117
|
+
filter: filter,
|
118
|
+
)
|
100
119
|
if collection.read_concern
|
101
120
|
document[:readConcern] = Options::Mapper.transform_values_to_strings(
|
102
121
|
collection.read_concern)
|
103
122
|
end
|
104
|
-
command = Options::Mapper.transform_documents(
|
123
|
+
command = Options::Mapper.transform_documents(
|
124
|
+
convert_flags(options), MAPPINGS, document)
|
105
125
|
if command['oplogReplay']
|
106
126
|
log_warn("oplogReplay is deprecated and ignored by MongoDB 4.4 and later")
|
107
127
|
end
|
@@ -36,16 +36,25 @@ module Mongo
|
|
36
36
|
# @since 2.2.0
|
37
37
|
ALL_PLANS_EXECUTION = 'allPlansExecution'.freeze
|
38
38
|
|
39
|
-
# Get the
|
39
|
+
# Get the query plan for the query.
|
40
40
|
#
|
41
|
-
# @example Get the
|
42
|
-
# view.explain
|
41
|
+
# @example Get the query plan for the query with execution statistics.
|
42
|
+
# view.explain(verbosity: :execution_stats)
|
43
43
|
#
|
44
|
-
# @
|
44
|
+
# @option opts [ true | false ] :verbose The level of detail
|
45
|
+
# to return for MongoDB 2.6 servers.
|
46
|
+
# @option opts [ String | Symbol ] :verbosity The type of information
|
47
|
+
# to return for MongoDB 3.0 and newer servers. If the value is a
|
48
|
+
# symbol, it will be stringified and converted from underscore
|
49
|
+
# style to camel case style (e.g. :query_planner => "queryPlanner").
|
50
|
+
#
|
51
|
+
# @return [ Hash ] A single document with the query plan.
|
52
|
+
#
|
53
|
+
# @see https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain
|
45
54
|
#
|
46
55
|
# @since 2.0.0
|
47
|
-
def explain
|
48
|
-
self.class.new(collection, selector, options.merge(explain_options)).first
|
56
|
+
def explain(**opts)
|
57
|
+
self.class.new(collection, selector, options.merge(explain_options(**opts))).first
|
49
58
|
end
|
50
59
|
|
51
60
|
private
|
@@ -54,9 +63,19 @@ module Mongo
|
|
54
63
|
!!options[:explain]
|
55
64
|
end
|
56
65
|
|
57
|
-
|
66
|
+
# @option opts [ true | false ] :verbose The level of detail
|
67
|
+
# to return for MongoDB 2.6 servers.
|
68
|
+
# @option opts [ String | Symbol ] :verbosity The type of information
|
69
|
+
# to return for MongoDB 3.0 and newer servers. If the value is a
|
70
|
+
# symbol, it will be stringified and converted from underscore
|
71
|
+
# style to camel case style (e.g. :query_planner => "queryPlanner").
|
72
|
+
def explain_options(**opts)
|
58
73
|
explain_limit = limit || 0
|
59
|
-
|
74
|
+
# Note: opts will never be nil here.
|
75
|
+
if Symbol === opts[:verbosity]
|
76
|
+
opts[:verbosity] = Utils.camelize(opts[:verbosity])
|
77
|
+
end
|
78
|
+
{ limit: -explain_limit.abs, explain: opts }
|
60
79
|
end
|
61
80
|
end
|
62
81
|
end
|
@@ -35,19 +35,34 @@ module Mongo
|
|
35
35
|
#
|
36
36
|
# @yieldparam [ Hash ] Each matching document.
|
37
37
|
def each
|
38
|
-
@cursor =
|
39
|
-
|
40
|
-
@cursor = if respond_to?(:write?, true) && write?
|
41
|
-
server = server_selector.select_server(cluster, nil, session)
|
42
|
-
result = send_initial_query(server, session)
|
43
|
-
Cursor.new(view, result, server, session: session)
|
38
|
+
@cursor = if use_query_cache? && cached_cursor
|
39
|
+
cached_cursor
|
44
40
|
else
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
session = client.send(:get_session, @options)
|
42
|
+
select_cursor(session)
|
43
|
+
end
|
44
|
+
|
45
|
+
if use_query_cache?
|
46
|
+
# No need to store the cursor in the query cache if there is
|
47
|
+
# already a cached cursor stored at this key.
|
48
|
+
QueryCache.set(@cursor, **cache_options) unless cached_cursor
|
49
|
+
|
50
|
+
# If a query with a limit is performed, the query cache will
|
51
|
+
# re-use results from an earlier query with the same or larger
|
52
|
+
# limit, and then impose the lower limit during iteration.
|
53
|
+
limit_for_cached_query = respond_to?(:limit) ? limit : nil
|
48
54
|
end
|
55
|
+
|
49
56
|
if block_given?
|
50
|
-
|
57
|
+
# Ruby versions 2.5 and older do not support arr[0..nil] syntax, so
|
58
|
+
# this must be a separate conditional.
|
59
|
+
cursor_to_iterate = if limit_for_cached_query
|
60
|
+
@cursor.to_a[0...limit_for_cached_query]
|
61
|
+
else
|
62
|
+
@cursor
|
63
|
+
end
|
64
|
+
|
65
|
+
cursor_to_iterate.each do |doc|
|
51
66
|
yield doc
|
52
67
|
end
|
53
68
|
else
|
@@ -77,6 +92,46 @@ module Mongo
|
|
77
92
|
|
78
93
|
private
|
79
94
|
|
95
|
+
def select_cursor(session)
|
96
|
+
if respond_to?(:write?, true) && write?
|
97
|
+
server = server_selector.select_server(cluster, nil, session)
|
98
|
+
result = send_initial_query(server, session)
|
99
|
+
|
100
|
+
# RUBY-2367: This will be updated to allow the query cache to
|
101
|
+
# cache cursors with multi-batch results.
|
102
|
+
if use_query_cache?
|
103
|
+
CachingCursor.new(view, result, server, session: session)
|
104
|
+
else
|
105
|
+
Cursor.new(view, result, server, session: session)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
read_with_retry_cursor(session, server_selector, view) do |server|
|
109
|
+
send_initial_query(server, session)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def cached_cursor
|
115
|
+
QueryCache.get(**cache_options)
|
116
|
+
end
|
117
|
+
|
118
|
+
def cache_options
|
119
|
+
# NB: this hash is passed as keyword argument and must have symbol
|
120
|
+
# keys.
|
121
|
+
{
|
122
|
+
namespace: collection.namespace,
|
123
|
+
selector: selector,
|
124
|
+
skip: skip,
|
125
|
+
sort: sort,
|
126
|
+
limit: limit,
|
127
|
+
projection: projection,
|
128
|
+
collation: collation,
|
129
|
+
read_concern: read_concern,
|
130
|
+
read_preference: read_preference
|
131
|
+
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
80
135
|
def initial_query_op(server, session)
|
81
136
|
if server.with_connection { |connection| connection.features }.find_command_enabled?
|
82
137
|
initial_command_op(session)
|
@@ -92,10 +147,11 @@ module Mongo
|
|
92
147
|
end
|
93
148
|
|
94
149
|
def initial_command_op(session)
|
150
|
+
builder = Builder::FindCommand.new(self, session)
|
95
151
|
if explained?
|
96
|
-
Operation::Explain.new(
|
152
|
+
Operation::Explain.new(builder.explain_specification)
|
97
153
|
else
|
98
|
-
Operation::Find.new(
|
154
|
+
Operation::Find.new(builder.specification)
|
99
155
|
end
|
100
156
|
end
|
101
157
|
|
@@ -103,6 +159,10 @@ module Mongo
|
|
103
159
|
validate_collation!(server, collation)
|
104
160
|
initial_query_op(server, session).execute(server, client: client)
|
105
161
|
end
|
162
|
+
|
163
|
+
def use_query_cache?
|
164
|
+
QueryCache.enabled? && !collection.system_collection?
|
165
|
+
end
|
106
166
|
end
|
107
167
|
end
|
108
168
|
end
|
@@ -45,7 +45,17 @@ module Mongo
|
|
45
45
|
#
|
46
46
|
# @since 2.0.0
|
47
47
|
def aggregate(pipeline, options = {})
|
48
|
-
Aggregation.new(self, pipeline, options)
|
48
|
+
aggregation = Aggregation.new(self, pipeline, options)
|
49
|
+
|
50
|
+
# Because the $merge and $out pipeline stages write documents to the
|
51
|
+
# collection, it is necessary to clear the cache when they are performed.
|
52
|
+
#
|
53
|
+
# Opt to clear the entire cache rather than one namespace because
|
54
|
+
# the $out and $merge stages do not have to write to the same namespace
|
55
|
+
# on which the aggregation is performed.
|
56
|
+
QueryCache.clear if aggregation.write?
|
57
|
+
|
58
|
+
aggregation
|
49
59
|
end
|
50
60
|
|
51
61
|
# Allows the server to write temporary data to disk while executing
|
@@ -90,7 +100,7 @@ module Mongo
|
|
90
100
|
# @param [ Integer ] batch_size The size of each batch of results.
|
91
101
|
#
|
92
102
|
# @return [ Integer, View ] Either the batch_size value or a
|
93
|
-
#
|
103
|
+
# new +View+.
|
94
104
|
#
|
95
105
|
# @since 2.0.0
|
96
106
|
def batch_size(batch_size = nil)
|