Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-1112

BasicBSONObject.equals is broken for binary data.

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 2.11.4
    • Component/s: BSON
    • Labels:
      None
    • Major Change

      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.

            Assignee:
            Unassigned Unassigned
            Reporter:
            g-r-t Graham Thomson
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: