В Java переменная UDT представлена классом com.datastax.driver.core. UDTValue. Этот класс имеет методы get и set. Существуют методы, использующие индекс (0 ...) для идентификации полей (в порядке их определения в UDT) и методов, которые используют имя поля.
См. API Doc.
Вот некоторые примеры, используя тип, определенный в вопросе:
TupleValue accumState = state.getTupleValue("accum");
String prevSource = accumState.getString(0);
Map<String,Double> avgMap = state.getMap("avg_map", String.class, Double.class);
Первая строка получает Accum поля от состояния функции. Вместо имени можно использовать индекс 0 (ноль, это первое поле).
Вторая строка получает первый элемент кортежа. Можно использовать только индексную версию, так как элементы кортежа не называются.
Третья строка получает поле avg_map.
accumState.setDouble(2, value);
state.setTupleValue("accum", accumState);
Приведенный выше пример устанавливает третий элемент кортежа, а затем помещает кортеж обратно в переменной состояния функции. Обратите внимание, что вы должны вернуть кортеж в переменную состояния. Следующая работа не работает.
// does not work
state.getTupleValue("accum").setDouble(2, value);
Ниже приведен полный пример UDF.
// sums up until the source changes, then adds the avg to the map
// IMPORTANT: table must be ordered by source
CREATE OR REPLACE FUNCTION average_by_source_1(state avg_type_1, source text, value double)
CALLED ON NULL INPUT
RETURNS avg_type_1
LANGUAGE java
AS $$
TupleValue accumState = state.getTupleValue("accum");
String prevSource = accumState.getString(0);
// when no source yet, save the first source, set the count to 1, and set the value
if (prevSource == null) {
accumState.setString(0, source);
accumState.setInt(1, 1);
accumState.setDouble(2, value);
state.setTupleValue("accum", accumState);
}
// when same source, increment the count and add the value
else if (prevSource.equals(source)) {
accumState.setInt(1, accumState.getInt(1) + 1);
accumState.setDouble(2, accumState.getDouble(2) + value);
state.setTupleValue("accum", accumState);
}
// when different source, calc average and copy to map, then re-init accumulation
else if (accumState.getInt(1) > 0) {
double avgVal = accumState.getDouble(2)/accumState.getInt(1);
Map<String,Double> mapState = state.getMap("avg_map", String.class, Double.class);
mapState.put(prevSource, avgVal);
state.setMap("avg_map", mapState, String.class, Double.class);
accumState.setString(0, source);
accumState.setInt(1, 1);
accumState.setDouble(2, value);
state.setTupleValue("accum", accumState);
}
// should not happen - prev case uses "if" to avoid division by zero
else {
Map<String,Double> mapState = state.getMap("avg_map", String.class, Double.class);
mapState.put("ERROR: div by zero", null);
accumState.setString(0, source);
accumState.setInt(1, 1);
accumState.setDouble(2, value);
state.setTupleValue("accum", accumState);
}
// IMPROTANT: final function must calculate the average for the last source and
// add it to the map.
return state;
$$
;
Я думаю, что getMap() из класса UDTValue является решением. Он компилируется. Я отправлю ответ, когда у меня будет полный рабочий пример. – rwfbc