Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MONGOID-4918 Test embedded matchers with unusual document value types #4822

Merged
merged 6 commits into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/mongoid/matcher/all.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module All
raise Errors::InvalidQuery, "$all argument must be an array: #{Errors::InvalidQuery.truncate_expr(condition)}"
end

condition.any? && condition.all? do |c|
!condition.empty? && condition.all? do |c|
case c
when ::Regexp, BSON::Regexp::Raw
Regex.matches_array_or_scalar?(value, c)
Expand Down
16 changes: 12 additions & 4 deletions lib/mongoid/matcher/field_operator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,18 @@ module FieldOperator
end
end

module_function def soft_apply_operator(operator, left, right)
left&.send(operator, right)
rescue ArgumentError
false
module_function def apply_comparison_operator(operator, left, right)
case left
when Numeric
case right
when Numeric
left.send(operator, right)
else
false
end
else
false
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/matcher/gt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Matcher
module Gt
module_function def matches?(exists, value, condition)
FieldOperator.apply_array_field_operator(exists, value, condition) do |v|
FieldOperator.soft_apply_operator(:>, v, condition)
FieldOperator.apply_comparison_operator(:>, v, condition)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/matcher/gte.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Matcher
module Gte
module_function def matches?(exists, value, condition)
FieldOperator.apply_array_field_operator(exists, value, condition) do |v|
FieldOperator.soft_apply_operator(:>=, v, condition)
FieldOperator.apply_comparison_operator(:>=, v, condition)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/matcher/lt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Matcher
module Lt
module_function def matches?(exists, value, condition)
FieldOperator.apply_array_field_operator(exists, value, condition) do |v|
FieldOperator.soft_apply_operator(:<, v, condition)
FieldOperator.apply_comparison_operator(:<, v, condition)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/matcher/lte.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Matcher
module Lte
module_function def matches?(exists, value, condition)
FieldOperator.apply_array_field_operator(exists, value, condition) do |v|
FieldOperator.soft_apply_operator(:<=, v, condition)
FieldOperator.apply_comparison_operator(:<=, v, condition)
end
end
end
Expand Down
23 changes: 16 additions & 7 deletions lib/mongoid/matcher/regex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@ module Matcher
# @api private
module Regex
module_function def matches?(exists, value, condition)
if condition.respond_to?(:compile)
# BSON::Regexp::Raw
condition = condition.compile
end
case condition
condition = case condition
when Regexp
value =~ condition
condition
when BSON::Regexp::Raw
condition.compile
when String
value =~ Regexp.new(condition)
Regexp.new(condition)
else
raise Errors::InvalidQuery, "$regex requires a regular expression or a string argument: #{Errors::InvalidQuery.truncate_expr(condition)}"
end

case value
when Array
value.any? do |v|
v =~ condition
end
when String
value =~ condition
else
false
end
end

module_function def matches_array_or_scalar?(value, condition)
Expand Down
24 changes: 24 additions & 0 deletions spec/integration/matcher_operator_data/all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,27 @@
$all:
ceo
error: true

- name: field value is null
document:
products: ~
query:
products:
$all: [1, 2]
matches: false

- name: field value is numeric
document:
products: 42
query:
products:
$all: [42]
matches: true

- name: field value is null and query is for null value
document:
products: ~
query:
products:
$all: [~]
matches: true
10 changes: 10 additions & 0 deletions spec/integration/matcher_operator_data/and.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,13 @@
$and:
foo: bar
error: true

- name: field value is null
document:
products: ~
query:
$and:
-
products:
$ne: a
matches: true
39 changes: 39 additions & 0 deletions spec/integration/matcher_operator_data/elem_match.yml
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,42 @@
positions:
$elemMatch: []
error: true

- name: field value is a number
document:
tags: 12
query:
tags:
$elemMatch:
$eq: 12
matches: false

- name: field value is an empty array
document:
tags: []
query:
tags:
$elemMatch:
$not:
$eq: y
matches: false

- name: field value is an empty hash
document:
tags: {}
query:
tags:
$elemMatch:
$not:
$eq: y
matches: false

- name: field value is null
document:
tags: ~
query:
tags:
$elemMatch:
$not:
$eq: y
matches: false
8 changes: 8 additions & 0 deletions spec/integration/matcher_operator_data/eq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,11 @@
positions:
$eq: ~
matches: false

- name: null field value vs nil argument
document:
positions: ~
query:
positions:
$eq: ~
matches: true
8 changes: 8 additions & 0 deletions spec/integration/matcher_operator_data/gt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@
count:
$gt: []
matches: false

- name: field value is an empty hash
document:
counts: {}
query:
counts:
$gt: 11
matches: false
8 changes: 8 additions & 0 deletions spec/integration/matcher_operator_data/gte.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@
count:
$gte: []
matches: false

- name: field value is an empty hash
document:
counts: {}
query:
counts:
$gte: 11
matches: false
8 changes: 8 additions & 0 deletions spec/integration/matcher_operator_data/lt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@
count:
$lt: []
matches: false

- name: field value is an empty hash
document:
counts: {}
query:
counts:
$lt: 11
matches: false
8 changes: 8 additions & 0 deletions spec/integration/matcher_operator_data/lte.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@
count:
$lte: []
matches: false

- name: field value is an empty hash
document:
counts: {}
query:
counts:
$lte: 11
matches: false
10 changes: 10 additions & 0 deletions spec/integration/matcher_operator_data/nor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,13 @@
$nor:
foo: bar
error: true

- name: field value is null
document:
products: ~
query:
$nor:
-
products:
$eq: a
matches: true
10 changes: 10 additions & 0 deletions spec/integration/matcher_operator_data/or.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,13 @@
$or:
foo: bar
error: true

- name: field value is null
document:
products: ~
query:
$or:
-
products:
$ne: a
matches: true
62 changes: 62 additions & 0 deletions spec/integration/matcher_operator_data/regex.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,65 @@
position:
$regex: 42
error: true

- name: numeric field value - matches if stringified
document:
title: 42
query:
title:
$regex:
'42'
matches: false

- name: array field value - matches an element
document:
title:
- foo
query:
title:
$regex: foo
matches: true

- name: array field value - does not match an element
document:
title:
- foo
query:
title:
$regex: bar
matches: false

- name: empty array field value
document:
title: []
query:
title:
$regex: bar
matches: false

- name: true field value
document:
title: true
query:
title:
$regex:
'true'
matches: false

- name: false field value
document:
title: false
query:
title:
$regex:
'false'
matches: false

- name: nil field value
document:
title: ~
query:
title:
$regex:
''
matches: false