-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MONGOID-4906 Implement bitwise operators (#4917)
- Loading branch information
Showing
11 changed files
with
766 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
module Mongoid | ||
module Matcher | ||
|
||
# @api private | ||
module Bits | ||
def matches?(exists, value, condition) | ||
case value | ||
when BSON::Binary | ||
value = value.data.split('').map { |n| '%02x' % n.ord }.join.to_i(16) | ||
end | ||
case condition | ||
when Array | ||
array_matches?(value, condition) | ||
when BSON::Binary | ||
int_cond = condition.data.split('').map { |n| '%02x' % n.ord }.join.to_i(16) | ||
int_matches?(value, int_cond) | ||
when Integer | ||
if condition < 0 | ||
raise Errors::InvalidQuery, "Invalid value for $#{operator_name} argument: negative integers are not allowed: #{condition}" | ||
end | ||
int_matches?(value, condition) | ||
when Float | ||
if (int_cond = condition.to_i).to_f == condition | ||
if int_cond < 0 | ||
raise Errors::InvalidQuery, "Invalid value for $#{operator_name} argument: negative numbers are not allowed: #{condition}" | ||
end | ||
int_matches?(value, int_cond) | ||
else | ||
raise Errors::InvalidQuery, "Invalid type for $#{operator_name} argument: not representable as an integer: #{condition}" | ||
end | ||
else | ||
raise Errors::InvalidQuery, "Invalid type for $#{operator_name} argument: #{condition}" | ||
end | ||
end | ||
|
||
module_function def operator_name | ||
name.sub(/.*::/, '').sub(/\A(.)/) { |l| l.downcase } | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Mongoid | ||
module Matcher | ||
|
||
# @api private | ||
module BitsAllClear | ||
include Bits | ||
extend self | ||
|
||
def array_matches?(value, condition) | ||
condition.all? do |c| | ||
value & (1<<c) == 0 | ||
end | ||
end | ||
|
||
def int_matches?(value, condition) | ||
value & condition == 0 | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Mongoid | ||
module Matcher | ||
|
||
# @api private | ||
module BitsAllSet | ||
include Bits | ||
extend self | ||
|
||
def array_matches?(value, condition) | ||
condition.all? do |c| | ||
value & (1<<c) > 0 | ||
end | ||
end | ||
|
||
def int_matches?(value, condition) | ||
value & condition == condition | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Mongoid | ||
module Matcher | ||
|
||
# @api private | ||
module BitsAnyClear | ||
include Bits | ||
extend self | ||
|
||
def array_matches?(value, condition) | ||
condition.any? do |c| | ||
value & (1<<c) == 0 | ||
end | ||
end | ||
|
||
def int_matches?(value, condition) | ||
value & condition < condition | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Mongoid | ||
module Matcher | ||
|
||
# @api private | ||
module BitsAnySet | ||
include Bits | ||
extend self | ||
|
||
def array_matches?(value, condition) | ||
condition.any? do |c| | ||
value & (1<<c) > 0 | ||
end | ||
end | ||
|
||
def int_matches?(value, condition) | ||
value & condition > 0 | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
spec/integration/matcher_operator_data/bits_all_clear.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
- name: existing field - matches with int | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: 35 | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: existing field - does not match with int | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: 24 | ||
matches: false | ||
min_server_version: 3.2 | ||
|
||
- name: existing field - matches with binData | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: !ruby/object:BSON::Binary | ||
data: !binary |- | ||
IW== | ||
type: :generic | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: existing field - does not match with binData | ||
document: | ||
a: 21 | ||
binaryValueofA: "00010101" | ||
query: | ||
a: | ||
$bitsAllClear: !ruby/object:BSON::Binary | ||
data: !binary |- | ||
IW== | ||
type: :generic | ||
matches: false | ||
min_server_version: 3.2 | ||
|
||
- name: existing binData field matches | ||
document: | ||
a: !ruby/object:BSON::Binary | ||
data: !binary |- | ||
IW== | ||
type: :generic | ||
query: | ||
a: | ||
$bitsAllClear: 20 | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: existing binData field does not match | ||
document: | ||
a: !ruby/object:BSON::Binary | ||
data: !binary |- | ||
IW== | ||
type: :generic | ||
query: | ||
a: | ||
$bitsAllClear: 15 | ||
matches: false | ||
min_server_version: 3.2 | ||
|
||
- name: existing field - matches with array | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: [0, 3] | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: existing field - does not match with array | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: [0, 2] | ||
matches: false | ||
min_server_version: 3.2 | ||
|
||
- name: float condition representable as an integer | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: 35.0 | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: float condition not representable as an integer | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: 35.1 | ||
error: true | ||
min_server_version: 3.2 | ||
|
||
- name: string condition | ||
document: | ||
a: 54 | ||
binaryValueofA: "00110110" | ||
query: | ||
a: | ||
$bitsAllClear: hello | ||
error: true | ||
min_server_version: 3.2 | ||
|
||
- name: empty array condition | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: [] | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: integer 0 condition | ||
document: | ||
a: 20 | ||
binaryValueofA: "00010100" | ||
query: | ||
a: | ||
$bitsAllClear: 0 | ||
matches: true | ||
min_server_version: 3.2 | ||
|
||
- name: negative integer condition | ||
document: | ||
a: 54 | ||
binaryValueofA: "00110110" | ||
query: | ||
a: | ||
$bitsAllClear: -1 | ||
error: true | ||
min_server_version: 3.2 | ||
|
||
- name: negative float condition | ||
document: | ||
a: 54 | ||
binaryValueofA: "00110110" | ||
query: | ||
a: | ||
$bitsAllClear: -1.0 | ||
error: true | ||
min_server_version: 3.2 |
Oops, something went wrong.