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:
void push(object[, object]*): adds the given object(s) to the end of the list
boolean remove(object[, object]*): removes one or more object from the list. Returns true if at least one object was actually found and removed.
boolean includes(object[, object]*): returns true if all specified objects are present in the list
int indexOf(object): returns the index of the specified object in the list, or -1 if not present in the list
void insert(idx, object[, object]*): inserts one or more object at the specified index
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:
void add(object[, object]*): adds the specified object(s) to the set.
boolean remove(object[, object]*): removes the specified object(s) from the set, returns true if at least one object was found and removed.
boolean includes(object[, object]*): returns true if all the specified objects are present in the set.
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.