mongoid 7.2.0.rc1 → 7.3.0
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.tar.gz.sig +0 -0
- data/Rakefile +45 -10
- data/lib/config/locales/en.yml +2 -2
- data/lib/mongoid/association/accessors.rb +1 -1
- data/lib/mongoid/association/constrainable.rb +1 -1
- data/lib/mongoid/association/depending.rb +4 -4
- data/lib/mongoid/association/embedded/batchable.rb +1 -1
- data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
- data/lib/mongoid/association/nested/many.rb +1 -1
- data/lib/mongoid/association/nested/one.rb +4 -2
- data/lib/mongoid/association/proxy.rb +6 -1
- data/lib/mongoid/association/referenced/auto_save.rb +2 -2
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
- data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
- data/lib/mongoid/association/referenced/has_one/buildable.rb +8 -0
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
- data/lib/mongoid/association/referenced/has_one/proxy.rb +6 -1
- data/lib/mongoid/attributes.rb +32 -14
- data/lib/mongoid/attributes/projector.rb +120 -0
- data/lib/mongoid/cacheable.rb +2 -2
- data/lib/mongoid/clients.rb +1 -1
- data/lib/mongoid/clients/factory.rb +22 -8
- data/lib/mongoid/config.rb +19 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
- data/lib/mongoid/copyable.rb +6 -2
- data/lib/mongoid/criteria.rb +4 -5
- data/lib/mongoid/criteria/findable.rb +1 -1
- data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
- data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
- data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
- data/lib/mongoid/criteria/queryable/selector.rb +0 -4
- data/lib/mongoid/document.rb +4 -17
- data/lib/mongoid/errors/delete_restriction.rb +8 -9
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/extensions/boolean.rb +1 -2
- data/lib/mongoid/extensions/false_class.rb +1 -1
- data/lib/mongoid/extensions/hash.rb +2 -2
- data/lib/mongoid/extensions/true_class.rb +1 -1
- data/lib/mongoid/fields.rb +46 -5
- data/lib/mongoid/inspectable.rb +1 -1
- data/lib/mongoid/interceptable.rb +3 -1
- data/lib/mongoid/matcher.rb +26 -43
- data/lib/mongoid/matcher/bits.rb +41 -0
- data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_all_set.rb +20 -0
- data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_any_set.rb +20 -0
- data/lib/mongoid/matcher/elem_match.rb +2 -1
- data/lib/mongoid/matcher/expression.rb +9 -14
- data/lib/mongoid/matcher/field_expression.rb +4 -5
- data/lib/mongoid/matcher/field_operator.rb +13 -11
- data/lib/mongoid/matcher/mod.rb +17 -0
- data/lib/mongoid/matcher/type.rb +99 -0
- data/lib/mongoid/persistable/deletable.rb +1 -2
- data/lib/mongoid/persistable/destroyable.rb +8 -2
- data/lib/mongoid/persistable/updatable.rb +27 -2
- data/lib/mongoid/query_cache.rb +35 -29
- data/lib/mongoid/reloadable.rb +5 -0
- data/lib/mongoid/selectable.rb +5 -7
- data/lib/mongoid/shardable.rb +21 -5
- data/lib/mongoid/stringified_symbol.rb +53 -0
- data/lib/mongoid/touchable.rb +23 -4
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
- data/spec/README.md +19 -4
- data/spec/integration/app_spec.rb +175 -88
- data/spec/integration/associations/embeds_many_spec.rb +68 -0
- data/spec/integration/associations/embeds_one_spec.rb +24 -0
- data/spec/integration/associations/has_many_spec.rb +60 -0
- data/spec/integration/associations/has_one_spec.rb +108 -0
- data/spec/integration/callbacks_models.rb +49 -0
- data/spec/integration/callbacks_spec.rb +216 -0
- data/spec/integration/criteria/date_field_spec.rb +1 -1
- data/spec/integration/document_spec.rb +30 -0
- data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
- data/spec/integration/matcher_operator_data/comment.yml +22 -0
- data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
- data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
- data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
- data/spec/integration/matcher_operator_data/in.yml +16 -0
- data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
- data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/mod.yml +55 -0
- data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
- data/spec/integration/matcher_operator_data/type.yml +70 -0
- data/spec/integration/matcher_operator_data/type_array.yml +16 -0
- data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
- data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
- data/spec/integration/matcher_operator_data/type_code.yml +26 -0
- data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
- data/spec/integration/matcher_operator_data/type_date.yml +39 -0
- data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
- data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
- data/spec/integration/matcher_operator_data/type_double.yml +15 -0
- data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
- data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
- data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_null.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
- data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
- data/spec/integration/matcher_operator_data/type_string.yml +15 -0
- data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
- data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
- data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
- data/spec/integration/stringified_symbol_field_spec.rb +190 -0
- data/spec/lite_spec_helper.rb +9 -7
- data/spec/mongoid/association/depending_spec.rb +391 -352
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
- data/spec/mongoid/association/nested/one_spec.rb +18 -14
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many_models.rb +12 -0
- data/spec/mongoid/association/referenced/has_one_models.rb +20 -0
- data/spec/mongoid/association/referenced/has_one_spec.rb +1 -1
- data/spec/mongoid/atomic/paths_spec.rb +105 -12
- data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
- data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
- data/spec/mongoid/attributes/projector_spec.rb +41 -0
- data/spec/mongoid/attributes_spec.rb +333 -0
- data/spec/mongoid/clients/factory_spec.rb +48 -0
- data/spec/mongoid/config_spec.rb +32 -0
- data/spec/mongoid/contextual/atomic_spec.rb +17 -4
- data/spec/mongoid/contextual/mongo_spec.rb +2 -2
- data/spec/mongoid/copyable_spec.rb +44 -17
- data/spec/mongoid/copyable_spec_models.rb +14 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +265 -24
- data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
- data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
- data/spec/mongoid/criteria_projection_spec.rb +411 -0
- data/spec/mongoid/criteria_spec.rb +0 -275
- data/spec/mongoid/document_fields_spec.rb +26 -0
- data/spec/mongoid/document_spec.rb +13 -13
- data/spec/mongoid/equality_spec.rb +0 -1
- data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
- data/spec/mongoid/extensions/false_class_spec.rb +1 -1
- data/spec/mongoid/extensions/string_spec.rb +5 -5
- data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
- data/spec/mongoid/extensions/true_class_spec.rb +1 -1
- data/spec/mongoid/fields/localized_spec.rb +4 -4
- data/spec/mongoid/fields_spec.rb +4 -4
- data/spec/mongoid/inspectable_spec.rb +12 -4
- data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
- data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
- data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
- data/spec/mongoid/persistable/deletable_spec.rb +175 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
- data/spec/mongoid/persistable/savable_spec.rb +3 -5
- data/spec/mongoid/persistable/settable_spec.rb +30 -0
- data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
- data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
- data/spec/mongoid/reloadable_spec.rb +18 -1
- data/spec/mongoid/shardable_spec.rb +44 -0
- data/spec/mongoid/touchable_spec.rb +104 -16
- data/spec/mongoid/touchable_spec_models.rb +52 -0
- data/spec/mongoid/validatable_spec.rb +1 -1
- data/spec/shared/LICENSE +20 -0
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
- data/spec/shared/lib/mrss/cluster_config.rb +221 -0
- data/spec/shared/lib/mrss/constraints.rb +354 -0
- data/spec/shared/lib/mrss/docker_runner.rb +265 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +162 -0
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +231 -0
- data/spec/shared/shlib/distro.sh +73 -0
- data/spec/shared/shlib/server.sh +290 -0
- data/spec/shared/shlib/set_env.sh +128 -0
- data/spec/spec_helper.rb +7 -1
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/constraints.rb +0 -226
- data/spec/support/models/bolt.rb +8 -0
- data/spec/support/models/customer.rb +11 -0
- data/spec/support/models/customer_address.rb +12 -0
- data/spec/support/models/dictionary.rb +6 -0
- data/spec/support/models/hole.rb +13 -0
- data/spec/support/models/mop.rb +9 -0
- data/spec/support/models/nut.rb +8 -0
- data/spec/support/models/order.rb +11 -0
- data/spec/support/models/person.rb +8 -0
- data/spec/support/models/sealer.rb +8 -0
- data/spec/support/models/series.rb +1 -0
- data/spec/support/models/shirt.rb +12 -0
- data/spec/support/models/spacer.rb +8 -0
- data/spec/support/models/threadlocker.rb +8 -0
- data/spec/support/models/washer.rb +8 -0
- data/spec/support/models/wiki_page.rb +1 -0
- data/spec/support/spec_config.rb +8 -0
- metadata +655 -507
- metadata.gz.sig +0 -0
- data/spec/support/child_process_helper.rb +0 -79
- data/spec/support/cluster_config.rb +0 -158
- data/spec/support/lite_constraints.rb +0 -22
- data/spec/support/spec_organizer.rb +0 -130
data/lib/mongoid/inspectable.rb
CHANGED
|
@@ -234,9 +234,11 @@ module Mongoid
|
|
|
234
234
|
# document.halted_callback_hook(filter)
|
|
235
235
|
#
|
|
236
236
|
# @param [ Symbol ] filter The callback that halted.
|
|
237
|
+
# @param [ Symbol ] name The name of the callback that was halted
|
|
238
|
+
# (requires Rails 6.1+)
|
|
237
239
|
#
|
|
238
240
|
# @since 3.0.3
|
|
239
|
-
def halted_callback_hook(filter)
|
|
241
|
+
def halted_callback_hook(filter, name = nil)
|
|
240
242
|
@before_callback_halted = true
|
|
241
243
|
end
|
|
242
244
|
|
data/lib/mongoid/matcher.rb
CHANGED
|
@@ -43,66 +43,47 @@ module Mongoid
|
|
|
43
43
|
document = BSON::Document.new(document.send(:as_attributes))
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
expanded = false
|
|
48
|
-
exists = true
|
|
46
|
+
current = [document]
|
|
49
47
|
|
|
50
48
|
key.to_s.split('.').each do |field|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
exists = index < src.length
|
|
55
|
-
src = src[index]
|
|
56
|
-
else
|
|
57
|
-
# Trying to index something that is not an array
|
|
58
|
-
exists = false
|
|
59
|
-
src = nil
|
|
60
|
-
end
|
|
61
|
-
else
|
|
62
|
-
case src
|
|
63
|
-
when nil
|
|
64
|
-
exists = false
|
|
49
|
+
new = []
|
|
50
|
+
current.each do |doc|
|
|
51
|
+
case doc
|
|
65
52
|
when Hash
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
if doc.key?(field)
|
|
54
|
+
new << doc[field]
|
|
55
|
+
end
|
|
68
56
|
when Array
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
when Array
|
|
79
|
-
new += v
|
|
80
|
-
else
|
|
81
|
-
new += [v]
|
|
82
|
-
end
|
|
83
|
-
exists = true
|
|
57
|
+
if (index = field.to_i).to_s == field
|
|
58
|
+
if doc.length > index
|
|
59
|
+
new << doc[index]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
doc.each do |subdoc|
|
|
63
|
+
if Hash === subdoc
|
|
64
|
+
if subdoc.key?(field)
|
|
65
|
+
new << subdoc[field]
|
|
84
66
|
end
|
|
85
|
-
else
|
|
86
|
-
# Trying to hash index into a value that is not a hash
|
|
87
67
|
end
|
|
88
68
|
end
|
|
89
|
-
src = new
|
|
90
|
-
else
|
|
91
|
-
# Trying to descend into a field that is not a hash using
|
|
92
|
-
# dot notation.
|
|
93
|
-
exists = false
|
|
94
|
-
src = nil
|
|
95
69
|
end
|
|
96
70
|
end
|
|
71
|
+
current = new
|
|
72
|
+
break if current.empty?
|
|
97
73
|
end
|
|
98
74
|
|
|
99
|
-
|
|
75
|
+
current
|
|
100
76
|
end
|
|
101
77
|
end
|
|
102
78
|
end
|
|
103
79
|
|
|
104
80
|
require 'mongoid/matcher/all'
|
|
105
81
|
require 'mongoid/matcher/and'
|
|
82
|
+
require 'mongoid/matcher/bits'
|
|
83
|
+
require 'mongoid/matcher/bits_all_clear'
|
|
84
|
+
require 'mongoid/matcher/bits_all_set'
|
|
85
|
+
require 'mongoid/matcher/bits_any_clear'
|
|
86
|
+
require 'mongoid/matcher/bits_any_set'
|
|
106
87
|
require 'mongoid/matcher/elem_match'
|
|
107
88
|
require 'mongoid/matcher/elem_match_expression'
|
|
108
89
|
require 'mongoid/matcher/eq'
|
|
@@ -116,6 +97,7 @@ require 'mongoid/matcher/gte'
|
|
|
116
97
|
require 'mongoid/matcher/in'
|
|
117
98
|
require 'mongoid/matcher/lt'
|
|
118
99
|
require 'mongoid/matcher/lte'
|
|
100
|
+
require 'mongoid/matcher/mod'
|
|
119
101
|
require 'mongoid/matcher/ne'
|
|
120
102
|
require 'mongoid/matcher/nin'
|
|
121
103
|
require 'mongoid/matcher/nor'
|
|
@@ -123,5 +105,6 @@ require 'mongoid/matcher/not'
|
|
|
123
105
|
require 'mongoid/matcher/or'
|
|
124
106
|
require 'mongoid/matcher/regex'
|
|
125
107
|
require 'mongoid/matcher/size'
|
|
108
|
+
require 'mongoid/matcher/type'
|
|
126
109
|
require 'mongoid/matcher/expression_operator'
|
|
127
110
|
require 'mongoid/matcher/field_operator'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module Bits
|
|
6
|
+
def matches?(exists, value, condition)
|
|
7
|
+
case value
|
|
8
|
+
when BSON::Binary
|
|
9
|
+
value = value.data.split('').map { |n| '%02x' % n.ord }.join.to_i(16)
|
|
10
|
+
end
|
|
11
|
+
case condition
|
|
12
|
+
when Array
|
|
13
|
+
array_matches?(value, condition)
|
|
14
|
+
when BSON::Binary
|
|
15
|
+
int_cond = condition.data.split('').map { |n| '%02x' % n.ord }.join.to_i(16)
|
|
16
|
+
int_matches?(value, int_cond)
|
|
17
|
+
when Integer
|
|
18
|
+
if condition < 0
|
|
19
|
+
raise Errors::InvalidQuery, "Invalid value for $#{operator_name} argument: negative integers are not allowed: #{condition}"
|
|
20
|
+
end
|
|
21
|
+
int_matches?(value, condition)
|
|
22
|
+
when Float
|
|
23
|
+
if (int_cond = condition.to_i).to_f == condition
|
|
24
|
+
if int_cond < 0
|
|
25
|
+
raise Errors::InvalidQuery, "Invalid value for $#{operator_name} argument: negative numbers are not allowed: #{condition}"
|
|
26
|
+
end
|
|
27
|
+
int_matches?(value, int_cond)
|
|
28
|
+
else
|
|
29
|
+
raise Errors::InvalidQuery, "Invalid type for $#{operator_name} argument: not representable as an integer: #{condition}"
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
raise Errors::InvalidQuery, "Invalid type for $#{operator_name} argument: #{condition}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module_function def operator_name
|
|
37
|
+
name.sub(/.*::/, '').sub(/\A(.)/) { |l| l.downcase }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAllClear
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.all? do |c|
|
|
11
|
+
value & (1<<c) == 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition == 0
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAllSet
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.all? do |c|
|
|
11
|
+
value & (1<<c) > 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition == condition
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAnyClear
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.any? do |c|
|
|
11
|
+
value & (1<<c) == 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition < condition
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAnySet
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.any? do |c|
|
|
11
|
+
value & (1<<c) > 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition > 0
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -15,7 +15,8 @@ module Mongoid
|
|
|
15
15
|
# Validate the condition is valid, even though we will never attempt
|
|
16
16
|
# matching it.
|
|
17
17
|
condition.each do |k, v|
|
|
18
|
-
|
|
18
|
+
k = k.to_s
|
|
19
|
+
if k.start_with?('$')
|
|
19
20
|
begin
|
|
20
21
|
ExpressionOperator.get(k)
|
|
21
22
|
rescue Mongoid::Errors::InvalidExpressionOperator
|
|
@@ -12,25 +12,20 @@ module Mongoid
|
|
|
12
12
|
end
|
|
13
13
|
expr.all? do |k, expr_v|
|
|
14
14
|
k = k.to_s
|
|
15
|
+
if k == "$comment"
|
|
16
|
+
# Nothing
|
|
17
|
+
return true
|
|
18
|
+
end
|
|
15
19
|
if k.start_with?('$')
|
|
16
20
|
ExpressionOperator.get(k).matches?(document, expr_v)
|
|
17
21
|
else
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# Do not treat a hash as an array here (both are iterable).
|
|
23
|
-
if expanded && Array === value
|
|
24
|
-
if value == []
|
|
25
|
-
# Empty array is technically equivalent to exists: false.
|
|
26
|
-
FieldExpression.matches?(false, nil, expr_v)
|
|
27
|
-
else
|
|
28
|
-
value.any? do |v|
|
|
29
|
-
FieldExpression.matches?(true, v, expr_v)
|
|
30
|
-
end
|
|
22
|
+
values = Matcher.extract_attribute(document, k)
|
|
23
|
+
if values.length > 0
|
|
24
|
+
values.any? do |v|
|
|
25
|
+
FieldExpression.matches?(true, v, expr_v)
|
|
31
26
|
end
|
|
32
27
|
else
|
|
33
|
-
FieldExpression.matches?(
|
|
28
|
+
FieldExpression.matches?(false, nil, expr_v)
|
|
34
29
|
end
|
|
35
30
|
end
|
|
36
31
|
end
|
|
@@ -36,14 +36,13 @@ module Mongoid
|
|
|
36
36
|
FieldOperator.get(k).matches?(exists, value, cond_v)
|
|
37
37
|
end
|
|
38
38
|
elsif Hash === value
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
sub_value.any? do |sub_v|
|
|
39
|
+
sub_values = Matcher.extract_attribute(value, k)
|
|
40
|
+
if sub_values.length > 0
|
|
41
|
+
sub_values.any? do |sub_v|
|
|
43
42
|
Eq.matches?(true, sub_v, cond_v)
|
|
44
43
|
end
|
|
45
44
|
else
|
|
46
|
-
Eq.matches?(
|
|
45
|
+
Eq.matches?(false, nil, cond_v)
|
|
47
46
|
end
|
|
48
47
|
else
|
|
49
48
|
false
|
|
@@ -5,6 +5,10 @@ module Mongoid
|
|
|
5
5
|
module FieldOperator
|
|
6
6
|
MAP = {
|
|
7
7
|
'$all' => All,
|
|
8
|
+
'$bitsAllClear' => BitsAllClear,
|
|
9
|
+
'$bitsAllSet' => BitsAllSet,
|
|
10
|
+
'$bitsAnyClear' => BitsAnyClear,
|
|
11
|
+
'$bitsAnySet' => BitsAnySet,
|
|
8
12
|
'$elemMatch' => ElemMatch,
|
|
9
13
|
'$eq' => Eq,
|
|
10
14
|
'$exists' => Exists,
|
|
@@ -13,11 +17,13 @@ module Mongoid
|
|
|
13
17
|
'$in' => In,
|
|
14
18
|
'$lt' => Lt,
|
|
15
19
|
'$lte' => Lte,
|
|
20
|
+
'$mod' => Mod,
|
|
16
21
|
'$nin' => Nin,
|
|
17
22
|
'$ne' => Ne,
|
|
18
23
|
'$not' => Not,
|
|
19
24
|
'$regex' => Regex,
|
|
20
25
|
'$size' => Size,
|
|
26
|
+
'$type' => Type,
|
|
21
27
|
}.freeze
|
|
22
28
|
|
|
23
29
|
module_function def get(op)
|
|
@@ -35,17 +41,13 @@ module Mongoid
|
|
|
35
41
|
end
|
|
36
42
|
|
|
37
43
|
module_function def apply_comparison_operator(operator, left, right)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
false
|
|
48
|
-
end
|
|
44
|
+
left.send(operator, right)
|
|
45
|
+
rescue ArgumentError, NoMethodError, TypeError
|
|
46
|
+
# We silence bogus comparison attempts, e.g. number to string
|
|
47
|
+
# comparisons.
|
|
48
|
+
# Several different exceptions may be produced depending on the types
|
|
49
|
+
# involved.
|
|
50
|
+
false
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module Mod
|
|
6
|
+
module_function def matches?(exists, value, condition)
|
|
7
|
+
unless Array === condition
|
|
8
|
+
raise Errors::InvalidQuery, "Unknown $mod argument #{condition}"
|
|
9
|
+
end
|
|
10
|
+
if condition.length != 2
|
|
11
|
+
raise Errors::InvalidQuery, "Malformed $mod argument #{condition}, should have 2 elements"
|
|
12
|
+
end
|
|
13
|
+
condition[1] == value%condition[0]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @see https://docs.mongodb.com/manual/reference/operator/query/type/
|
|
5
|
+
#
|
|
6
|
+
# @api private
|
|
7
|
+
module Type
|
|
8
|
+
module_function def matches?(exists, value, condition)
|
|
9
|
+
conditions = case condition
|
|
10
|
+
when Array
|
|
11
|
+
condition
|
|
12
|
+
when Integer
|
|
13
|
+
[condition]
|
|
14
|
+
else
|
|
15
|
+
raise Errors::InvalidQuery, "Unknown $type argument: #{condition}"
|
|
16
|
+
end
|
|
17
|
+
conditions.each do |condition|
|
|
18
|
+
if one_matches?(exists, value, condition)
|
|
19
|
+
return true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module_function def one_matches?(exists, value, condition)
|
|
26
|
+
case condition
|
|
27
|
+
when 1
|
|
28
|
+
# Double
|
|
29
|
+
Float === value
|
|
30
|
+
when 2
|
|
31
|
+
# String
|
|
32
|
+
String === value
|
|
33
|
+
when 3
|
|
34
|
+
# Object
|
|
35
|
+
Hash === value
|
|
36
|
+
when 4
|
|
37
|
+
# Array
|
|
38
|
+
Array === value
|
|
39
|
+
when 5
|
|
40
|
+
# Binary data
|
|
41
|
+
BSON::Binary === value
|
|
42
|
+
when 6
|
|
43
|
+
# Undefined
|
|
44
|
+
BSON::Undefined === value
|
|
45
|
+
when 7
|
|
46
|
+
# ObjectId
|
|
47
|
+
BSON::ObjectId === value
|
|
48
|
+
when 8
|
|
49
|
+
# Boolean
|
|
50
|
+
TrueClass === value || FalseClass === value
|
|
51
|
+
when 9
|
|
52
|
+
# Date
|
|
53
|
+
Date === value || Time === value || DateTime === value
|
|
54
|
+
when 10
|
|
55
|
+
# Null
|
|
56
|
+
exists && NilClass === value
|
|
57
|
+
when 11
|
|
58
|
+
# Regex
|
|
59
|
+
Regexp::Raw === value || ::Regexp === value
|
|
60
|
+
when 12
|
|
61
|
+
# DBPointer deprecated
|
|
62
|
+
BSON::DbPointer === value
|
|
63
|
+
when 13
|
|
64
|
+
# JavaScript
|
|
65
|
+
BSON::Code === value
|
|
66
|
+
when 14
|
|
67
|
+
# Symbol deprecated
|
|
68
|
+
Symbol === value || BSON::Symbol::Raw === value
|
|
69
|
+
when 15
|
|
70
|
+
# Javascript with code deprecated
|
|
71
|
+
BSON::CodeWithScope === value
|
|
72
|
+
when 16
|
|
73
|
+
# 32-bit int
|
|
74
|
+
BSON::Int32 === value || Integer === value && (-2**32..2**32-1).include?(value)
|
|
75
|
+
when 17
|
|
76
|
+
# Timestamp
|
|
77
|
+
BSON::Timestamp === value
|
|
78
|
+
when 18
|
|
79
|
+
# Long
|
|
80
|
+
BSON::Int64 === value ||
|
|
81
|
+
Integer === value &&
|
|
82
|
+
(-2**64..2**64-1).include?(value) &&
|
|
83
|
+
!(-2**32..2**32-1).include?(value)
|
|
84
|
+
when 19
|
|
85
|
+
# Decimal
|
|
86
|
+
BSON::Decimal128 === value
|
|
87
|
+
when -1
|
|
88
|
+
# minKey
|
|
89
|
+
BSON::MinKey === value
|
|
90
|
+
when 127
|
|
91
|
+
# maxKey
|
|
92
|
+
BSON::MaxKey === value
|
|
93
|
+
else
|
|
94
|
+
raise Errors::InvalidQuery, "Unknown $type argument: #{condition}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|