Uploaded image for project: 'Node.js Driver'
  1. Node.js Driver
  2. NODE-3222

Node.js driver drops numeric types Long and Int32 and erronously returns them as Number

    • Type: Icon: Bug Bug
    • Resolution: Works as Designed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Labels:
    • Needed

      Node.js driver drops some numeric types, such as Long when reading them from the database. For example, inserting this document to the database:

        let doc_orig = {
          _id: new ObjectId(),
          long_value: new Long(123, 456),
          int_value: new Int32(123),
          decimal_value: Decimal128.fromString("12345678")
        }; 

      , and reading it later causes long_value and int_value to be returned as Number and not as Long and Int32.

      You can run a working example in the attached test, which will produce this output for new'ed document:

      doc_orig:
        ObjectID method    : 6081c05fe520b453f579a0df
        long_value ctor    : Long
        long_value method  : 456
        int_value ctor     : Int32
        decimal_value ctor : Decimal128  JSON: {
        "_id": "6081c05fe520b453f579a0df",
        "long_value": {
          "low": 123,
          "high": 456,
          "unsigned": false
        },
        "int_value": 123,
        "decimal_value": {
          "$numberDecimal": "12345678"
        }
      } 

      For a document it reads from the database, it will produce this output:

      doc_db:
        ObjectID method    : 6081c05fe520b453f579a0df
        long_value ctor    : Number
        int_value ctor     : Number
        decimal_value ctor : Decimal128  JSON: {
        "_id": "6081c05fe520b453f579a0df",
        "long_value": 1958505087099,
        "int_value": 123,
        "decimal_value": {
          "$numberDecimal": "12345678"
        }
      } 

      It retains some types, like ObjectId and Decimal129, but drops Long and Int32.

      Mongo Shell produces correctly-typed results, except for Int32, but that's quite acceptable for shell, even though it could do better:

      {
              "_id" : ObjectId("6081bdff3ae672809ee0906c"),
              "long_value" : NumberLong("1958505087099"),
              "int_value" : 123,
              "decimal_value" : NumberDecimal("12345678")
      } 

      Compass correctly identifies all types, including Int32 and Int64.

      Mongo C correctly identifies field types in BSON and returns appropriate values mapped to C++ types int32_t and int64_t from bson_as_json:

      {
        "_id" : { "$oid" : "6081bdff3ae672809ee0906c" },
        "long_value" : 1958505087099,
        "int_value" : 123,
        "decimal_value" : { "$numberDecimal" : "12345678" }
      }
      key: _id type: 7
      key: long_value type: 0x12 (BSON_TYPE_INT64)
      key: int_value type: 0x10 (BSON_TYPE_INT32)
      key: decimal_value type: 0x13 (BSON_TYPE_DECIMAL128)

      This makes it impossible to reference Long values via its methods after documents are read from the database. Before inserting the document, I can call both of these and it works as expected:

      console.log(`ObjectID method  : ${doc_orig._id.toHexString()}`);
      console.log(`long_value method: ${doc_orig.long_value.getHighBits()}`);
      

      After reading the document from the database the second one would crash because the field is constructed as Number.

      Node.js driver shall evaluate the BSON field type and if it finds BSON_TYPE_INT64, it shall allocate Long and initialize the resulting object with the value coming from BSON.

       

            Assignee:
            eric.adum@mongodb.com Eric Adum (Inactive)
            Reporter:
            cis74633@bell.net Andre M
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: