User-Defined Function
At Timeplus, we leverage SQL to make powerful streaming analytics more accessible to a broad range of users. Without SQL, you have to learn and call low-level programming API, then compile/package/deploy them to get analytics results. This is a repetitive and tedious process, even for small changes.
But some developers have concerns that complex logic or systems integrations are hard to express using SQL.
That's why we add User-Defined Functions (UDF) support in Proton. This enables users to leverage existing programming libraries, integrate with external systems, or just make SQL easier to maintain.
Proton supports Local UDF in JavaScript. You can develop User-defined scalar functions (UDFs) or User-defined aggregate functions (UDAFs) with modern JavaScript (powered by V8). No need to deploy extra server/service for the UDF. More languages will be supported.
CREATE OR REPLACE FUNCTION
You can create or replace a JavaScript UDF, by specifying the function name, input and output data types. Please check the mapping of data types for input and output.
The following example defines a new function test_add_five_5
:
CREATE OR REPLACE FUNCTION test_add_five_5(value float32)
RETURNS float32
LANGUAGE JAVASCRIPT AS $$
function test_add_five_5(values) {
for(let i=0;i<values.length;i++) {
values[i]=values[i]+5;
}
return values;
}
$$;
Note:
- Line 1: the function is to be created with name
test_add_five_5
, taking a singlefloat32
parameter. - Line 2: the function is to return a
float32
- Line 4: the same function name is defined in the code block. To improve performance, multiple UDF calls will be batched. The
values
is an array offloat
- Line 5 and 6: iterating the input array and add 5 to each value
- Line 8: return an array of new values
- Line 10: close the code block.
CREATE AGGREGATE FUNCTION
Creating a user-defined-aggregation function (UDAF) requires a bit more effort. Please check this documentation for the 3 required and 3 optional functions.
CREATE AGGREGATE FUNCTION test_sec_large(value float32)
RETURNS float32
LANGUAGE JAVASCRIPT AS $$
{
initialize: function() {
this.max = -1.0;
this.sec = -1.0
},
process: function(values) {
for (let i = 0; i < values.length; i++) {
if (values[i] > this.max) {
this.sec = this.max;
this.max = values[i]
}
if (values[i] < this.max && values[i] > this.sec)
this.sec = values[i];
}
},
finalize: function() {
return this.sec
},
serialize: function() {
let s = {
'max': this.max,
'sec': this.sec
};
return JSON.stringify(s)
},
deserialize: function(state_str) {
let s = JSON.parse(state_str);
this.max = s['max'];
this.sec = s['sec']
},
merge: function(state_str) {
let s = JSON.parse(state_str);
if (s['sec'] >= this.max) {
this.max = s['max'];
this.sec = s['sec']
} else if (s['max'] >= this.max) {
this.sec = this.max;
this.max = s['max']
} else if (s['max'] > this.sec) {
this.sec = s['max']
}
}
}
$$;
DROP FUNCTION
No matter UDF or UDAF, you can remove the function via DROP FUNCTION
Example:
DROP FUNCTION test_add_five_5;