[JAVA-1112] BasicBSONObject.equals is broken for binary data. Created: 14/Feb/14  Updated: 14/Feb/14  Resolved: 14/Feb/14

Status: Closed
Project: Java Driver
Component/s: BSON
Affects Version/s: 2.11.4
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Graham Thomson Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JAVA-416 Using an Array to create a DBObject b... Closed
Backwards Compatibility: Major Change

 Description   

Currently, bin data is represented as a byte[] in a query result DBObject.

Further, BasicBSONObject.equals tests for object equality using Object.equals.

You can see where this is going, right?

BasicBSONObject.equals does not make a special case for bin data / byte[]'s, so documents can return false when compared against an identical copy, as the following little snippet shows:

    public static void main(String[] args) throws UnknownHostException {
        DBCollection collection = new MongoClient().getDB("aDB").getCollection("aCollection");
 
        DBObject dbo = BasicDBObjectBuilder.start().add("ba", new byte[]{1, 2, 3}).get();
 
        collection.insert(dbo);
 
        DBObject eql = collection.findOne(dbo.get("_id"));
 
        System.out.println(dbo);
        System.out.println(eql);
        System.out.println(dbo.get("_id").equals(eql.get("_id")));
        System.out.println(dbo.equals(eql));
    }

produces:

{ "ba" : <Binary Data> , "_id" : { "$oid" : "52fe5f30300481ebe569a2c0"}}
{ "_id" : { "$oid" : "52fe5f30300481ebe569a2c0"} , "ba" : <Binary Data>}
true
false

A simple patch is to update BasicBSONObject.equals to handle byte[]'s, something like:

...
            } else if (a instanceof Number && b instanceof Number) {
                Number aNumber = (Number) a;
                Number bNumber = (Number) b;
                if (aNumber instanceof Double || bNumber instanceof Double
                        || aNumber instanceof Float || bNumber instanceof Float) {
                    if (aNumber.doubleValue() != bNumber.doubleValue()) {
                        return false;
                    }
                } else if (aNumber.longValue() != bNumber.longValue()) {
                    return false;
                }
            } else if (a instanceof byte[] && b instanceof byte[]) {
                byte[] a1 = (byte[]) a;
                byte[] a2 = (byte[]) b;
                if (!Arrays.equals(a1, a2)) {
                    return false;
                }
            } else if (a instanceof Pattern && b instanceof Pattern) {
                Pattern p1 = (Pattern) a;
                Pattern p2 = (Pattern) b;
                if (!p1.pattern().equals(p2.pattern()) || p1.flags() != p2.flags())
                    return false;
            } else {
...

Cheers,

Graham.



 Comments   
Comment by Jeffrey Yemin [ 14/Feb/14 ]

Closing as a duplicate, but feel free to re-open if the fix from JAVA-416 isn't working for you.

Comment by Jeffrey Yemin [ 14/Feb/14 ]

This turns out to be a duplicate of JAVA-416, which is fixed in the upcoming 2.12.0 release. If you'd like, you can try it out by using the snapshot release at https://oss.sonatype.org/content/repositories/snapshots/org/mongodb/mongo-java-driver/2.12.0-SNAPSHOT/

Generated at Thu Feb 08 08:53:50 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.