publicclassSum{//Need an inner class to store data/*required*/publicstaticclassState{/*some variables if you need */publicBigDecimal sum;}/*required*/publicStatecreate(){/* here could do some init work if needed */State state =newState();
state.sum =newBigDecimal(0);return state;}/*required*/publicvoiddestroy(State state){/* here could do some destroy work if needed */}/*Not Required*/publicvoidreset(State state){/*if you want this udaf function can work with window function.*//*Must impl this, it will be reset to init state after calculate every window frame*//**
state.sum = new BigDecimal(0);
**/}/*required*///first argument is State, then other types your inputpublicvoidadd(State state,String value)throwsException{try{/* here doing update work when input data*/if(null!= value &&!"".equals(value)){
state.sum = state.sum.add(newBigDecimal(value));}}catch(Exception e){
log.info(e.getMessage());}}/*required*/publicvoidserialize(State state,DataOutputStream out){/* serialize some data into buffer */try{
out.writeUTF(state.sum.toString());}catch(Exception e){/* Do not throw exceptions */
log.info(e.getMessage());}}/*required*/publicvoiddeserialize(State state,DataInputStream in){/* deserialize get data from buffer before you put */String value ="0";try{
value = in.readUTF();}catch(Exception e){/* Do not throw exceptions */
log.info(e.getMessage());}
state.sum =newBigDecimal(value);}/*required*/publicvoidmerge(State state,State rhs)throwsException{/* merge data from state */if(null== rhs ||null== rhs.sum ||null== state){return;}try{BigDecimal sum = state.sum;if(null== sum){
sum =newBigDecimal(0);}
state.sum = sum.add(rhs.sum);}catch(Exception e){
log.info(e.getMessage());}}/*required*///return Type you definedpublicStringgetValue(State state)throwsException{/* return finally result */returnnull== state ||null== state.sum ?"0": state.sum.toString();}}
AVG平均数运算函数
publicclassAvg{//Need an inner class to store data/*required*/publicstaticclassState{/*some variables if you need */publicBigDecimal sum;publicInteger count;}/*required*/publicStatecreate(){/* here could do some init work if needed */State state =newState();
state.sum =newBigDecimal(0);
state.count =0;return state;}/*required*/publicvoiddestroy(State state){/* here could do some destroy work if needed */}/*Not Required*/publicvoidreset(State state){/*if you want this udaf function can work with window function.*//*Must impl this, it will be reset to init state after calculate every window frame*//**
state.sum = new BigDecimal(0);
**/}/*required*///first argument is State, then other types your inputpublicvoidadd(State state,String value)throwsException{try{/* here doing update work when input data*/if(null!= value &&!"".equals(value)){
state.sum = state.sum.add(newBigDecimal(value));
state.count +=1;}}catch(Exception e){
log.info(e.getMessage());}}/*required*/publicvoidserialize(State state,DataOutputStream out){/* serialize some data into buffer */try{
out.writeUTF(state.sum.toString());
out.writeInt(state.count);}catch(Exception e){/* Do not throw exceptions */
log.info(e.getMessage());}}/*required*/publicvoiddeserialize(State state,DataInputStream in){/* deserialize get data from buffer before you put */String value ="0";Integer count =0;try{
value = in.readUTF();
count = in.readInt();}catch(Exception e){/* Do not throw exceptions */
log.info(e.getMessage());}
state.sum =newBigDecimal(value);
state.count = count;}/*required*/publicvoidmerge(State state,State rhs)throwsException{/* merge data from state */if(null== rhs ||null== rhs.sum ||null== state){return;}try{BigDecimal sum = state.sum;
sum =null== sum ?newBigDecimal(0): sum;
state.sum = sum.add(rhs.sum);Integer count = state.count;
count =null== count ?0: count;
state.count = count + rhs.count;}catch(Exception e){
log.info(e.getMessage());}}/*required*///return Type you definedpublicStringgetValue(State state)throwsException{/* return finally result */returnnull== state ||null== state.sum ||null== state.count ?"0":
state.sum.divide(newBigDecimal(state.count)).toString();}}
MAX最大值运算函数
publicclassMax{//Need an inner class to store data/*required*/publicstaticclassState{/*some variables if you need */publicBigDecimal max;}/*required*/publicStatecreate(){/* here could do some init work if needed */State state =newState();
state.max =newBigDecimal(0);return state;}/*required*/publicvoiddestroy(State state){/* here could do some destroy work if needed */}/*Not Required*/publicvoidreset(State state){/*if you want this udaf function can work with window function.*//*Must impl this, it will be reset to init state after calculate every window frame*//**
state.sum = new BigDecimal(0);
**/}/*required*///first argument is State, then other types your inputpublicvoidadd(State state,String value)throwsException{try{/* here doing update work when input data*/if(null!= value &&!"".equals(value)){BigDecimal valueBd =newBigDecimal(value);
state.max = state.max.compareTo(valueBd)==-1? valueBd : state.max;}}catch(Exception e){
log.info(e.getMessage());}}/*required*/publicvoidserialize(State state,DataOutputStream out){/* serialize some data into buffer */try{
out.writeUTF(state.max.toString());}catch(Exception e){/* Do not throw exceptions */
log.info(e.getMessage());}}/*required*/publicvoiddeserialize(State state,DataInputStream in){/* deserialize get data from buffer before you put */String value ="0";try{
value = in.readUTF();}catch(Exception e){/* Do not throw exceptions */
log.info(e.getMessage());}
state.max =newBigDecimal(value);}/*required*/publicvoidmerge(State state,State rhs)throwsException{/* merge data from state */if(null== rhs ||null== rhs.max ||null== state){return;}try{BigDecimal sum = state.max;if(null== sum){
sum =newBigDecimal(0);}
state.max = state.max.compareTo(rhs.max)==-1? rhs.max : state.max;}catch(Exception e){
log.info(e.getMessage());}}/*required*///return Type you definedpublicStringgetValue(State state)throwsException{/* return finally result */returnnull== state ||null== state.max ?"0": state.max.toString();}}
项目打成jar包,上传至每个FE、BE节点。
创建函数命令
CREATE FUNCTION
name ([,...])[RETURNS] rettype
PROPERTIES (["key"="value"][,...])
CREATE AGGREGATE FUNCTION
name ([,...])[RETURNS] rettype
PROPERTIES (["key"="value"][,...])
PROPERTIES中symbol表示的是包含UDF类的类名,这个参数是必须设定的。
PROPERTIES中file表示的包含用户UDF的jar包,这个参数是必须设定的。
PROPERTIES中type表示的 UDF 调用类型,默认为 Native,使用 Java UDF时传 JAVA_UDF。
PROPERTIES中always_nullable表示的 UDF 返回结果中是否有可能出现NULL值,是可选参数,默认值为true。
name: 一个function是要归属于某个DB的,name的形式为dbName.funcName。当dbName没有明确指定的时候,就是使用当前session所在的db作为dbName。
CREATE GLOBAL AGGREGATE FUNCTION udaf_sum(string) RETURNS string PROPERTIES ("file"="file:///home/doris/udf/doris-udaf-1.0.0.jar","symbol"="com.doris.udaf.func.Sum","always_nullable"="true","type"="JAVA_UDF");"file"="http://ip:port/xxxxxx.jar", 当在多机环境时也可以使用http的方式下载jar包。必须让每个BE节点都能获取到jar包; 否则将会返回错误状态信息"Couldn't open file ......"。
"always_nullable"可选属性, 如果在计算中对出现的NULL值有特殊处理,确定结果中不会返回NULL,可以设为false,这样在整个查询计算过程中性能可能更好些。
DROP GLOBAL FUNCTION udaf_sum(string);
SHOW CREATE FUNCTION udaf_sum(string);