Search code examples
node.jscassandradatastax-node-driver

Duration column type is returned as custom type


I have the following table in cassandra:

create table duration_table
(
    id           int primary key,
    duration_col duration
);

Cassandra DB version is 4.0.5, cassandra nodejs driver version is 4.6.4. When I request table metadata via

client.metadata.getTable(keyspaceName, "duration_table")

the result is:

...,
{
  ...,
  columns: [
    ...,
    {
      "name": "duration_col",
      "type": {
        "code": 21,
        "info": null,
        "options": {
          "frozen": false
        }
      },
      "isStatic": false
    }
  ]
}

The returned type code of duration_col is 21 which corresponds to types.dataTypes.duration enum in cassandra-driver. However, when i send the following request via cassandra driver client:

client.execute("SELECT * FROM duration_table");

the result is the following:

{
  ...,
  columns: [
    ...,
    {
      "name": "duration_col",
      "type": {
        "code": 0,
        "type": null,
        "info": "org.apache.cassandra.db.marshal.DurationType"
      }
    }
  ]
}

The returned type here is 0 which corresponds to types.dataTypes.custom enum in the driver. So, my questions are:

  • why do the types differ on the same table and the same column?
  • is there a guarantee that the returned info field in ResultSet with value org.apache.cassandra.db.marshal.DurationType will always be present in such scenario? I mean, can I consider this field as a constant for duration column type?
  • are there any other cassandra types that are returned as custom type but actually they are not custom types?

Solution

  • thanks for the question!

    You're seeing the column metadata in your result set report the duration type as a custom type because you're using protocol version 4 with your connection. The duration type was added to the CQL protocol as a fully supported type with protocol version 5 (v5) but unfortunately the nodejs driver currently only supports protocol version 4 (v4) or less. You can see the nodejs driver connecting with v4 by looking for something like the following near the top of your log:

    info - Connection:  Protocol version 5 not supported by this driver, downgrading (undefined)
    

    When you connect to a Cassandra server which supports the duration type using something less than v5 the server will automatically convert duration types to custom types in order to give you something your driver can understand. You can confirm this by adding a row of data to your test table and printing the result set you get from querying it:

    ResultSet {
    ...
    rows: [
     Row {
       id: 1,
       duration_col: Duration {
         months: 0,
         days: 0,
         nanoseconds: Long { low: -129542144, high: 13, unsigned: false }
       }
     }
    ],
    rowLength: 1,
    columns: [
     { name: 'id', type: { code: 9, type: null } },
     {
       name: 'duration_col',
       type: {
         code: 0,
         type: null,
         info: 'org.apache.cassandra.db.marshal.DurationType'
       }
     }
    ],
    ...
    

    Note that in this example the returned value in the duration column is correctly rendered as a three-fold value consisting of some number of months, days and nanoseconds. This matches exactly the value of a duration defined in the specification of v5, so clearly what's stored in this column is duration data.

    A quick note here on how the nodejs driver is able to identify duration types if it doesn't support v5. The driver added support for the duration type from other work. Support for this type is necessary to implement v5 but it is certainly not sufficient; there's a lot more to v5 than just a new data type.

    Note that we hit exactly this problem when we added support for the duration type to the Ruby driver; that's exactly what this comment is referring to.