Menu

User-Defined Types (UDTs)

Note: Cassandra 2.1+ is required.

User-defined types (UDT) can be used to create arbitrary user types with fields that can be accessed by name or position. When used with the driver they can be created from a previously defined type determined from schema or they can be created from a manually defined data type.

Creating a UDT from Schema

An CassSchemaMeta instance can be used to construct a new CassUserType. The CassSchemaMeta instance returns a CassDataType object which is used to describe Cassandra types including UDTs, tuples, collections and all basic types (int, bigint, uuid, etc.).

void get_user_type_from_schema(CassSession* session) {
  const CassSchemaMeta* schema_meta = cass_session_get_schema_meta(session);

  const CassKeyspaceMeta* keyspace_meta =
    cass_schema_meta_keyspace_by_name(schema_meta, "keyspace");

  const CassDataType* data_type =
    cass_keyspace_meta_user_type_by_name(keyspace_meta, "typename");

  CassUserType* user_type = cass_user_type_new_from_data_type(data_type);

  /* Bind values to user type fields and bind user type to a statement */

}

Manually Constructing a UDT Data Type

If schema metadata updates are disabled it is still possible to create UDTs from a manually construct CassDataType.

CassDataType* data_type = cass_data_type_new_udt(3);

cass_data_type_add_sub_value_type_by_name(data_type, "field1",
CASS_VALUE_TYPE_INT);
cass_data_type_add_sub_value_type_by_name(data_type, "field2",
CASS_VALUE_TYPE_UUID);
cass_data_type_add_sub_value_type_by_name(data_type, "field3",
CASS_VALUE_TYPE_TEXT);

CassUserType* user_type = cass_user_type_new_from_data_type(data_type);

/* Bind values to user type fields */

cass_data_type_free(data_type);

The preceding code is equivalent to defining the following schema and using cass_session_get_schema() obtain the data type.

CREATE TYPE IF NOT EXISTS udt (field1 int, field2 uuid, field3 text);

Consuming values from a UDT result

A UDT returned from Cassandra is consumed by iterating over its fields similar to the way collections or tuples are consumed.

void iterate_udt(const CassRow* row) {
  /* Retrieve UDT value from column */
  const CassValue* udt_value = cass_row_get_column_by_name(row, "value1");

  /* Create an iterator for the UDT value */
  CassIterator* udt_iterator = cass_iterator_fields_from_user_type(udt_value);

  /* Iterate over the UDT fields */
  while (cass_iterator_next(udt_iterator)) {
    const char* field_name;
    size_t field_name_length;
    /* Get UDT field name */
    cass_iterator_get_user_type_field_name(udt_iterator,
                                           &field_name, &field_name_length);

    /* Get UDT field value */
    const CassValue* field_value =
      cass_iterator_get_user_type_field_value(udt_iterator);

    /* ... */
  }

  /* The UDT iterator needs to be freed */
  cass_iterator_free(udt_iterator);
}