Cassandra data types

Gallium Data fully supports all data types supported by Cassandra, but JavaScript does not always handle all values properly out of the box. This page describes these details for all data types.

Very large and very precise numbers

JavaScript numbers have some limitations, so when dealing with unusually large or precise numbers, you have the option to retrieve these numbers as objects, thereby preserving the exact value.

For instance, if your Cassandra database has a column of type bigint, which is a 64-bit signed integer, JavaScript will be unable to properly handle values greater than 2^52: values greater than that will be rounded, thus leading to loss of precision.

In this example, if the value is 987,654,321,987,654,321, the following code will cause some loss of precision:

context.row.numberofmolecules += 1;  // Result: 987,654,321,987,654,300

Similar loss of precision will happen if the number is a decimal number, and the precision exceeds what JavaScript is capable of.

When dealing with such numbers, you can avoid any loss of precision by retrieving the value as an object rather than a number:

let nbrMolecules = context.row.getValue("numberofmolecules");

Assuming the column is of type bigint in Cassandra, this would return a Java object of type BigInteger, which can then be used without any loss of precision:

let BigInteger = Java.type("java.math.BigInteger");

let nbrMolecules = context.row.getValue("numberofmolecules");

let newMols = noMolecules.add(new BigInteger("1"));

context.row.numberofmolecules = newMols;  // Correct result, no precision loss

ascii

Treated as a string. Non-ASCII characters will be converted to ASCII.

context.row.asciiname = "Jane Doe";

bigint

Treated as a JavaScript number, unless retrieved using getValue(), in which case the returned value will be a Java object of type BigInteger.

context.row.phone_number.country_code = 44;

context.row.totalprice = context.row.price + context.row.tax;

For unusually large numbers:

let noMolecules = context.row.getValue("numberofmolecules"); // huge number

let BigInteger = Java.type("java.math.BigInteger");

let newMols = noMolecules.add(new BigInteger("10"));

context.row.numberofmolecules = newMols;  // Correct result, no precision loss

blob

Treated as an array of numbers. The range of the numbers is -128 to 127, any values outside of that range will be truncated.

context.row.myblob = [1,2,3,4,5,6,7,8,9,10];

boolean

Treated as a boolean in JavaScript. The value can also be set to true with a case-insensitive string, whose value can be "true", "t", "yes", or "y". Any other string will evaluate to false. A boolean value can also be set with a number: any non-zero value will evaluate to true.

The following calls are equivalent:

context.row.ispreferred = true;

context.row.ispreferred = "Yes";

context.row.ispreferred = 42;

date

Treated as a string of format YYYY-MM-DD.

let d = context.row.purchasedate;  // d is now a string: "2023-05-29"

context.row.purchasedate = "1999-12-31";

If you want to do some date calculations, you can retrieve the value as a Java object of type LocalDate:

let d = context.row.getValue("purchasedate");

context.row.purchasedate = d.plusDays(100);

decimal

Treated as a normal JavaScript floating-point number, unless retrieved using getValue(), in which case the returned value will be a Java object of type BigDecimal.

context.row.distanceinmiles = context.row.distance * 0.621371;

For unusually large or precise numbers:

let largeNum = context.row.getValue("largenum");

let BigDecimal = Java.type("java.math.BigDecimal");

let newNum = largeNum.add(new BigDecimal("0.000000000000000000000123"));

context.row.largenum = newNum;  // Correct result, no precision loss

double

Treated as a normal JavaScript floating-point number.

context.row.parsecs = context.row.lightyears * 0.306601;

duration

Treated as a string. The format is specified using the number of months, the number of days, and the number of nanoseconds using the format XXmo YYd ZZns. Any of these can be omitted if the value is zero.

 context.row.elapsedtime = "88mo 24d 3600000000000ns";

context.row.responsetime = "2000000ns";

float

Treated as a normal JavaScript floating-point number.

context.row.parsecs = context.row.lightyears * 0.306601;

inet

Treated as a string, the format that can be either IP4 or IP6.

context.row.clientaddr = "12.34.56.78";

context.row.serveraddr = "2600:1709:6920:69f1:e97a:6c82:6a80:107";

int

Treated as a normal JavaScript number. Any value outside of -2,147,483,648 to 2,147,483,647 will be truncated.

context.row.numitems = 5000;

context.row.numitems -= 5;

list

Treated as a JavaScript array.

let thirdItem = context.row.items[2];

context.row.colors = ["blue", "red", "fuschia"];

The members of the list must of course be of a type that is compatible with the type defined in Cassandra, e.g.:

context.row.holidays = ["2023-01-01", "2023-04-15", "2023-08-29];

Lists are not actually JavaScript arrays, and they offer only the following methods:

Examples

let colors = context.row.colors;  // ["blue", "red", "green"]

colors.push("yellow", "orange");  // ["blue", "red", "green", "yellow", "orange"]

colors.remove("green");  // ["blue", "red", "yellow", "orange"]

let found = colors.includes("blue", "green"); // false: blue is found, but green is not

let indexOfYellow = colors.indexOf("yellow");  // 2

colors.insert(2, "pink", "mauve");  //  ["blue", "pink", "mauve", "red", "yellow", "orange"]

map

Treated as objects if the key is a string or number. 

let cellPhone = context.row.phones.cell;

context.row.phones.home = {country_code: 44, phone_number: "555-1212"};

If the key is not a string or number, maps must be accessed and manipulated using the get, set and remove methods, e.g.:

context.row.phoneDates.set({country_code: 44, phone_number: "555-1212"}, ["2021-01-01", "2023-04-06"]);

set

Treated as an object with the following methods:

Examples

let colorSet = context.row.colors;   // ["blue", "red", "green"]

colorSet.add("orange", "mauve");  // ["blue", "red", "green", "orange", "mauve"]

colorSet.remove("red");  // ["blue", "green", "orange", "mauve"]

let found = colorSet.includes("orange");  // true: orange is in the set

smallint

Treated as a normal JavaScript number. Any value outside of -32,768 to +32,767 will be truncated.

context.row.numitems = 5000;

context.row.count -= 5;

text

Treated as a normal string.

context.row.mytext = "Jane Doe";

time

Treated as a string with format HH:MM:SS[.SSSSSSSSS]. Up to nine digits can be specified for the fractional seconds.

let thetime = context.row.exectime;  // "23:12:07.008799"

context.row.exectime = "04:55:17.000000064";

If you want to do some time calculations, you can retrieve the value as a Java object of type LocalTime:

let t = context.row.getValue("eventtime");

context.row.eventtime = t.plusMinutes(15);

timestamp

Treated as a string with format YYYY-MM-DDTHH:MM:SS[.sss]. Up to three digits can be specified for the fractional seconds.

let ts = context.row.exects;  // "2023-05-05T21:00:01.882Z"

context.row.exects = "2023-05-05T00:55:00Z";

You can also retrieve a timestamp value as a Java object of type Instant:

let Instant = Java.type("java.time.Instant");

let limit = Instant.parse("2020-01-01T00:00:00Z");

if (context.row.ts.compareTo(limit) > 0) {

    context.row.price += 9.99;

}

timeuuid

Treated as a string.

let uuid = context.row.someid;  // "d2177dd0-eaa2-11de-a572-001b779c76e3"

context.row.someid = "d2177dd0-eaa2-11de-a572-001b779c76e4";

This can also be retrieved as a Java object of type UUID:

let uuid = context.row.getValue("timeId");

let ts = uuid.timestamp();

tinyint

Treated as a normal JavaScript number. Any value outside of -128 to +127 will be truncated.

context.row.numitems = -99;

context.row.numitems += 33;

tuple

Treated as a JavaScript array. Each member must be of a type compatible with the definition of the tuple in Cassandra.

// Given a table defined as follows:

// CREATE TABLE GalliumTest.TypesTuple (

//    ....

//    mytuple       TUPLE<INT, SET<FLOAT>, DATE, TUPLE<TINYINT, TEXT, BOOLEAN>>

// );

let tupleDate = context.row.mytuple[2];

let tupleSubBool = context.row.mytuple[3][2];

context.row.mytuple = [99, [2.2, 3.3, 4.4], "2023-05-05", [-8, "Some text", false]];

uuid

Treated as a string.

let uuid = context.row.someuuid;  //

context.row.someuuid = "12345678-1234-5678-1234-123456789012";

This can also be retrieved as a Java object of type UUID:

let uuid = context.row.getValue("someuuid");

let variant = uuid.variant();

varchar

This is an alias of the text type.

varint

Treated as a number, unless retrieved using getValue(), in which case the returned value will be a Java object of type BigInteger.

context.row.phone_number.country_code = 44;

context.row.totalprice = context.row.price + context.row.tax;

For unusually large numbers:

let noMolecules = context.row.getValue("numberofmolecules"); // huge number

let BigInteger = Java.type("java.math.BigInteger");

let newMols = noMolecules.add(new BigInteger("123456789123456789"));

context.row.numberofmolecules = newMols;  // Correct result, no precision loss

User-defined types (UDT)

Treated as JavaScript objects, with each member being a property of the UDT.

Given the following table definition:

CREATE TYPE Test.TypePhone (

    country_code INT,

    phone_number TEXT,

);

CREATE TABLE TestPhone.

(

    id          INT PRIMARY KEY,

    phone       Test.TypePhone

);

data using this schema could be accessed with:

let ccode = context.row.phone.country_code;

context.row.phone.phone_number = "555-1212";

Custom data types

Custom data types are supported, their value is available as a byte array. It is up to the implementer to interpret this byte array as appropriate.