[JAVA-946] DBObject.equals can fail when binary data exists Created: 12/Sep/13  Updated: 05/Dec/13  Resolved: 05/Dec/13

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

Type: Bug Priority: Minor - P4
Reporter: Daniel Gottlieb (Inactive) Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

My understanding of the cause:

While the Binary type implements an `equals` method that compares byte arrays, the decoder conveniently replaces the binary type with the native java byte array. In `BasicBSONObject.equals`, byte arrays are compared with `a.equals(b)` which I believe is a pointer equality check and not a data equality check. The following code/output sample illustrates a case where I feel the equality check on `DBObjects` should return true.

    public static void main(String[] jargs) throws Exception {
        Mongo mongo = new MongoClient();
        DBCollection coll = mongo.getDB("test").getCollection("binary");
        coll.drop();
 
        DBObject item = new BasicDBObject();
        item.put("_id", 1);
        item.put("data", new byte[10]);
 
        // Insert a single item
        coll.insert(item);
 
        // Retrieve the same item twice
        DBObject first = coll.findOne(new BasicDBObject("_id", 1));
        DBObject second = coll.findOne(new BasicDBObject("_id", 1));
 
        System.out.println("First: " + first + " data: " + Arrays.toString((byte[])first.get("data")));
        System.out.println("Second: " + second + " data: " + Arrays.toString((byte[])second.get("data")));
        // Not true :(
        System.out.println("Equals? " + (first.equals(second)));
    }

First: { "_id" : 1 , "data" : <Binary Data>} data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Second: { "_id" : 1 , "data" : <Binary Data>} data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Equals? false



 Comments   
Comment by Jeffrey Yemin [ 05/Dec/13 ]

After considering this and other similar issues, we're decided that we're not going to fix it. While we could fix this specific issue, relying on equality testing for DBObject just can't be made to work reliably for all cases. It comes down to the fact that DBObject presents an open type system: any object can be the value of a field, at any level, and we can't guarantee that every object implements equality the way we want. In this case, if the byte arrays were not at the top level but were instead embedded in an ArrayList, ArrayList.equals is not going to do deep equality testing of the byte arrays.

What we will likely do instead is to support a new type, probably called BsonDocument, that presents a closed type system where every allowed type implements equality predictably. It will look something like this:

 
public class BsonDocument extends BsonValue implements Map<String, BsonValue>

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