需要ApachePhoenix UDFs指南吗
我是apache phoenix的新手。我们需要编写phoenix UDF。但我在博客上找到的文档非常有限: 上面的链接只提供了非常简单的函数,它只有单一的i/p和o/p类型。需要ApachePhoenix UDFs指南吗,apache,phoenix,Apache,Phoenix,我是apache phoenix的新手。我们需要编写phoenix UDF。但我在博客上找到的文档非常有限: 上面的链接只提供了非常简单的函数,它只有单一的i/p和o/p类型。 我从一个星期开始搜索,但找不到任何文档解释如何编写包含多个参数的求值函数,该函数可以根据输入返回不同的数据类型。目前我只了解phoenix内置函数的源代码。这很麻烦。是否有关于phoenix UDF的全面文档。我也在试用phoenix,需要编写UDF。到目前为止,我学到了一些东西 您可以通过以下方式创建接受多个输入的自定
我从一个星期开始搜索,但找不到任何文档解释如何编写包含多个参数的求值函数,该函数可以根据输入返回不同的数据类型。目前我只了解phoenix内置函数的源代码。这很麻烦。是否有关于phoenix UDF的全面文档。我也在试用phoenix,需要编写UDF。到目前为止,我学到了一些东西 您可以通过以下方式创建接受多个输入的自定义项: 1) 为类定义两个参数,如so
@FunctionParseNode.BuiltInFunction(
name=BitmapUnionUDF.name,
args={
@FunctionParseNode.Argument(allowedTypes={PBinary.class}),
@FunctionParseNode.Argument(allowedTypes={PBinary.class})
}
)
公共类BitmapIntersectionLengthUDF扩展了ScalarFunction{
2) 访问评估函数中的参数表达式arg1=getChildren().get(0); 表达式arg2=getChildren().get(1); 3) 要从每个参数的表达式中实际获取字节值,请执行以下操作:
if(!arg1.evaluate(tuple,ptr)){
返回false;
}
--这将ptr设置为指向arg1的值4) 检索arg1值的字节
ptr.copyBytes()
--这将返回一个字节数组,您可以将其转换为适当的类型
5) 注册jar和函数
CREATE FUNCTION BITMAP\u INTERSECTION\u LENGTH(varbinary,varbinary)使用jar'/path/to/jar'将整数返回为'com.xxx.yyyy.zzz.BitmapIntersectionLengthUDF';
6) 有更多关于如何/在何处放置jar以及如何设置配置的提示。我也在尝试Phoenix,需要编写UDF。以下是我到目前为止学到的一些东西
package com.mohitgarg.hadoop.phoenixudf;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.compile.KeyPart;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.function.ScalarFunction;
import org.apache.phoenix.parse.FunctionParseNode.Argument;
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.types.PDecimal;
import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PVarchar;
/**
*
* @author mohit.garg
*
*/
@BuiltInFunction(name = PaymentAmountUDF.FUNC_NAME, args = { @Argument(allowedTypes = {PVarchar.class}),
@Argument(allowedTypes = {PInteger.class}),
@Argument(allowedTypes = {PDecimal.class}),
@Argument(allowedTypes = {PDecimal.class}),
@Argument(allowedTypes = {PDecimal.class})
})
public class PaymentAmountUDF extends ScalarFunction {
public static final String FUNC_NAME = "PaymentAmount";
public PaymentAmountUDF() {
}
public PaymentAmountUDF(List<Expression> children) throws SQLException {
super(children);
}
@Override
public String getName() {
return FUNC_NAME;
}
/**
* Determines whether or not a function may be used to form the start/stop
* key of a scan
*
* @return the zero-based position of the argument to traverse into to look
* for a primary key column reference, or {@value #NO_TRAVERSAL} if
* the function cannot be used to form the scan key.
*/
public int getKeyFormationTraversalIndex() {
return NO_TRAVERSAL;
}
/**
* Manufactures a KeyPart used to construct the KeyRange given a constant
* and a comparison operator.
*
* @param childPart
* the KeyPart formulated for the child expression at the
* {@link #getKeyFormationTraversalIndex()} position.
* @return the KeyPart for constructing the KeyRange for this function.
*/
public KeyPart newKeyPart(KeyPart childPart) {
return null;
}
/**
* Determines whether or not the result of the function invocation will be
* ordered in the same way as the input to the function. Returning YES
* enables an optimization to occur when a GROUP BY contains function
* invocations using the leading PK column(s).
*
* @return YES if the function invocation will always preserve order for the
* inputs versus the outputs and false otherwise, YES_IF_LAST if the
* function preserves order, but any further column reference would
* not continue to preserve order, and NO if the function does not
* preserve order.
*/
public OrderPreserving preservesOrder() {
return OrderPreserving.NO;
}
/**
* is the method to be implemented which provides access to the Tuple
*
* @param tuple
* Single row result during scan iteration
* @param ptr
* Pointer to byte value being accessed
* @return
*/
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
String frequency = null;
Integer term = null;
BigDecimal interestRate = null;
BigDecimal loanAmount = null;
BigDecimal fee = null;
for (int i = 0; i <= 4; i++) {
Expression arg = getChildren().get(i);
if (!arg.evaluate(tuple, ptr)) {
return false;
}
switch (i) {
case 0:
frequency = new String( ptr.copyBytes());
break;
case 1:
term = (Integer) PInteger.INSTANCE.toObject(ptr);
break;
case 2:
interestRate = (BigDecimal)PDecimal.INSTANCE.toObject(ptr, PDecimal.INSTANCE);
break;
case 3:
loanAmount = (BigDecimal)PDecimal.INSTANCE.toObject(ptr, PDecimal.INSTANCE);
break;
case 4:
fee = (BigDecimal)PDecimal.INSTANCE.toObject(ptr, PDecimal.INSTANCE);
break;
default:
return true;
}
}
int tp = 0;
String upcaseFrequency = frequency.toUpperCase();
if(upcaseFrequency.equals("M")) {
tp = 12;
} else if(upcaseFrequency.equals("T")) {
tp = 13;
} else if(upcaseFrequency.equals("B")) {
tp = 26;
} else if(upcaseFrequency.equals("S")) {
tp = 24;
} else if(upcaseFrequency.equals("W")) {
tp = 52;
}
int inst = (int) (Math.ceil((term / 12) * tp));
double r = interestRate.doubleValue() / tp;
double po = 1 - Math.pow(r + 1, -1 * inst);
double por = r / po;
double paymentAmount = ((por) * (loanAmount.doubleValue() + fee.doubleValue() ));
BigDecimal decimalPaymentAmount = BigDecimal.valueOf(paymentAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
ptr.set(PDecimal.INSTANCE.toBytes(decimalPaymentAmount));
return true;
}
public PDataType getDataType() {
return PDecimal.INSTANCE;
}
}
您可以通过以下方式创建接受多个输入的自定义项:
1) 为类定义两个参数,如so@FunctionParseNode.BuiltInFunction(
name=BitmapUnionUDF.name,
args={
@FunctionParseNode.Argument(allowedTypes={PBinary.class}),
@FunctionParseNode.Argument(allowedTypes={PBinary.class})
}
)
公共类BitmapIntersectionLengthUDF扩展了ScalarFunction{
2) 访问评估函数中的参数表达式arg1=getChildren().get(0); 表达式arg2=getChildren().get(1); 3) 要从每个参数的表达式中实际获取字节值,请执行以下操作:
if(!arg1.evaluate(tuple,ptr)){
返回false;
}
--这将ptr设置为指向arg1的值4) 检索arg1值的字节
ptr.copyBytes()
--这将返回一个字节数组,您可以将其转换为适当的类型
5) 注册jar和函数
CREATE FUNCTION BITMAP\u INTERSECTION\u LENGTH(varbinary,varbinary)使用jar'/path/to/jar'将整数返回为'com.xxx.yyyy.zzz.BitmapIntersectionLengthUDF';
6) 有更多关于如何/在何处放置jar以及设置配置的提示。package com.mohitgarg.hadoop.phoenixudf;
package com.mohitgarg.hadoop.phoenixudf;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.compile.KeyPart;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.function.ScalarFunction;
import org.apache.phoenix.parse.FunctionParseNode.Argument;
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.types.PDecimal;
import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PVarchar;
/**
*
* @author mohit.garg
*
*/
@BuiltInFunction(name = PaymentAmountUDF.FUNC_NAME, args = { @Argument(allowedTypes = {PVarchar.class}),
@Argument(allowedTypes = {PInteger.class}),
@Argument(allowedTypes = {PDecimal.class}),
@Argument(allowedTypes = {PDecimal.class}),
@Argument(allowedTypes = {PDecimal.class})
})
public class PaymentAmountUDF extends ScalarFunction {
public static final String FUNC_NAME = "PaymentAmount";
public PaymentAmountUDF() {
}
public PaymentAmountUDF(List<Expression> children) throws SQLException {
super(children);
}
@Override
public String getName() {
return FUNC_NAME;
}
/**
* Determines whether or not a function may be used to form the start/stop
* key of a scan
*
* @return the zero-based position of the argument to traverse into to look
* for a primary key column reference, or {@value #NO_TRAVERSAL} if
* the function cannot be used to form the scan key.
*/
public int getKeyFormationTraversalIndex() {
return NO_TRAVERSAL;
}
/**
* Manufactures a KeyPart used to construct the KeyRange given a constant
* and a comparison operator.
*
* @param childPart
* the KeyPart formulated for the child expression at the
* {@link #getKeyFormationTraversalIndex()} position.
* @return the KeyPart for constructing the KeyRange for this function.
*/
public KeyPart newKeyPart(KeyPart childPart) {
return null;
}
/**
* Determines whether or not the result of the function invocation will be
* ordered in the same way as the input to the function. Returning YES
* enables an optimization to occur when a GROUP BY contains function
* invocations using the leading PK column(s).
*
* @return YES if the function invocation will always preserve order for the
* inputs versus the outputs and false otherwise, YES_IF_LAST if the
* function preserves order, but any further column reference would
* not continue to preserve order, and NO if the function does not
* preserve order.
*/
public OrderPreserving preservesOrder() {
return OrderPreserving.NO;
}
/**
* is the method to be implemented which provides access to the Tuple
*
* @param tuple
* Single row result during scan iteration
* @param ptr
* Pointer to byte value being accessed
* @return
*/
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
String frequency = null;
Integer term = null;
BigDecimal interestRate = null;
BigDecimal loanAmount = null;
BigDecimal fee = null;
for (int i = 0; i <= 4; i++) {
Expression arg = getChildren().get(i);
if (!arg.evaluate(tuple, ptr)) {
return false;
}
switch (i) {
case 0:
frequency = new String( ptr.copyBytes());
break;
case 1:
term = (Integer) PInteger.INSTANCE.toObject(ptr);
break;
case 2:
interestRate = (BigDecimal)PDecimal.INSTANCE.toObject(ptr, PDecimal.INSTANCE);
break;
case 3:
loanAmount = (BigDecimal)PDecimal.INSTANCE.toObject(ptr, PDecimal.INSTANCE);
break;
case 4:
fee = (BigDecimal)PDecimal.INSTANCE.toObject(ptr, PDecimal.INSTANCE);
break;
default:
return true;
}
}
int tp = 0;
String upcaseFrequency = frequency.toUpperCase();
if(upcaseFrequency.equals("M")) {
tp = 12;
} else if(upcaseFrequency.equals("T")) {
tp = 13;
} else if(upcaseFrequency.equals("B")) {
tp = 26;
} else if(upcaseFrequency.equals("S")) {
tp = 24;
} else if(upcaseFrequency.equals("W")) {
tp = 52;
}
int inst = (int) (Math.ceil((term / 12) * tp));
double r = interestRate.doubleValue() / tp;
double po = 1 - Math.pow(r + 1, -1 * inst);
double por = r / po;
double paymentAmount = ((por) * (loanAmount.doubleValue() + fee.doubleValue() ));
BigDecimal decimalPaymentAmount = BigDecimal.valueOf(paymentAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
ptr.set(PDecimal.INSTANCE.toBytes(decimalPaymentAmount));
return true;
}
public PDataType getDataType() {
return PDecimal.INSTANCE;
}
}
导入java.math.BigDecimal;
导入java.sql.SQLException;
导入java.util.List;
导入org.apache.hadoop.hbase.io.ImmutableBytesWritable;
导入org.apache.phoenix.compile.KeyPart;
导入org.apache.phoenix.expression.expression;
导入org.apache.phoenix.expression.function.ScalarFunction;
导入org.apache.phoenix.parse.FunctionParseNode.Argument;
导入org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
导入org.apache.phoenix.schema.tuple.tuple;
导入org.apache.phoenix.schema.types.PDataType;
导入org.apache.phoenix.schema.types.PDecimal;
导入org.apache.phoenix.schema.types.PInteger;
导入org.apache.phoenix.schema.types.PVarchar;
/**
*
*@author mohit.garg
*
*/
@内置函数(name=PaymentAmountUDF.FUNC_name,args={@Argument(allowedTypes={PVarchar.class}),
@参数(allowedTypes={PInteger.class}),
@参数(allowedTypes={PDecimal.class}),
@参数(allowedTypes={PDecimal.class}),
@参数(allowedTypes={PDecimal.class})
})
公共类PaymentAmountUDF扩展了ScalarFunction{
公共静态最终字符串FUNC_NAME=“PaymentAmount”;
公共支付金额UDF(){
}
public PaymentAmountUDF(列出子项)引发SQLException{
超级(儿童);
}
@凌驾
公共字符串getName(){
返回函数名;
}
/**
*确定是否可以使用函数来形成启动/停止
*扫描键
*
*@返回要遍历以查看的参数的从零开始的位置
*对于主键列引用,或{@value#NO_TRAVERSAL}如果
*该功能不能用于形成扫描键。
*/
public int getKeyFormationTraversalIndex(){
返回NO_遍历;
}
/**
*制造用于构造给定常数的KeyRange的KeyPart
*和一个比较运算符。
*
*@param childPart
*关键部分是为儿童表达在
*{@link#getKeyFormationTraversalIndex()}位置。
*@返回用于构造此函数的KeyRange的KeyPart。
*/
公钥部分newKeyPart(KeyPart-childPart){
返回null;
}
/**
*确定函数调用的结果是否为
*按与函数输入相同的方式排序。返回“是”
*允许在GROUP BY包含函数时进行优化
*使用前导PK列的调用。