C++ 示例:从检查约束调用 UDSF
此示例显示了创建可由检查约束调用的 UDSF 所需的 C++ 代码。示例函数的名称是 LargestSquareBelow
。此示例函数确定其平方小于主题列中的数字的最大数字。例如,如果该列中的数字是 1000,则其平方 (961) 小于 1000 的最大数字是 31。
重要
在检查约束中使用的 UDSF 必须是不可变的,并且该约束必须能够正确处理 null 值。否则,检查约束可能无法按预期工作。此外,Vertica 还会评估在已加载或更新的每个行上启用的检查约束的谓词,因此请考虑编写函数时的性能。有关检查约束的信息,请参阅检查约束。
加载和使用示例
以下示例显示了如何使用 CREATE LIBRARY 创建和加载名为 MySqLib 的库。将此示例中的库路径调整为绝对路径,并将文件名调整为共享对象 LargestSquareBelow
保存到的位置。
创建库:
=> CREATE OR REPLACE LIBRARY MySqLib AS '/home/dbadmin/LargestSquareBelow.so';
- 创建并加载库之后,使用 CREATE FUNCTION(标量) 语句将函数添加到编录中:
=> CREATE OR REPLACE FUNCTION largestSqBelow AS LANGUAGE 'C++' NAME 'LargestSquareBelowInfo' LIBRARY MySqLib;
- 下一步,将 UDSF 包含到检查约束中。
=> CREATE TABLE squaretest(
ceiling INTEGER UNIQUE,
CONSTRAINT chk_sq CHECK (largestSqBelow(ceiling) < ceiling*ceiling)
);
- 将数据添加到表
squaretest
中:
=> COPY squaretest FROM stdin DELIMITER ','NULL'null';
-1
null
0
1
1000
1000000
1000001
\.
根据所使用的数据,输出应类似于以下示例:
SELECT ceiling, largestSqBelow(ceiling)
FROM squaretest ORDER BY ceiling;
ceiling | largestSqBelow
---------+----------------
|
-1 |
0 |
1 | 0
1000 | 31
1000000 | 999
1000001 | 1000
(7 rows)
ScalarFunction 实施
此 ScalarFunction
实施为 UDSF 执行处理工作,即确定其平方小于数字输入的最大数字。
#include "Vertica.h"
/*
* ScalarFunction implementation for a UDSF that
* determines the largest number whose square is less than
* the number input.
*/
class LargestSquareBelow : public Vertica::ScalarFunction
{
public:
/*
* This function does all of the actual processing for the UDSF.
* The inputs are retrieved via arg_reader
* The outputs are returned via arg_writer
*
*/
virtual void processBlock(Vertica::ServerInterface &srvInterface,
Vertica::BlockReader &arg_reader,
Vertica::BlockWriter &res_writer)
{
if (arg_reader.getNumCols() != 1)
vt_report_error(0, "Function only accept 1 argument, but %zu provided", arg_reader.getNumCols());
// While we have input to process
do {
// Read the input parameter by calling the
// BlockReader.getIntRef class function
const Vertica::vint a = arg_reader.getIntRef(0);
Vertica::vint res;
//Determine the largest square below the number
if ((a != Vertica::vint_null) && (a > 0))
{
res = (Vertica::vint)sqrt(a - 1);
}
else
res = Vertica::vint_null;
//Call BlockWriter.setInt to store the output value,
//which is the largest square
res_writer.setInt(res);
//Write the row and advance to the next output row
res_writer.next();
//Continue looping until there are no more input rows
} while (arg_reader.next());
}
};
ScalarFunctionFactory 实施
此 ScalarFunctionFactory
实施执行对输入和输出的处理工作,并将函数标记为不可变(如果计划在检查约束中使用 UDSF,则必须满足此要求)。
class LargestSquareBelowInfo : public Vertica::ScalarFunctionFactory
{
//return an instance of LargestSquareBelow to perform the computation.
virtual Vertica::ScalarFunction *createScalarFunction(Vertica::ServerInterface &srvInterface)
//Call the vt_createFuncObj to create the new LargestSquareBelow class instance.
{ return Vertica::vt_createFuncObject<LargestSquareBelow>(srvInterface.allocator); }
/*
* This function returns the description of the input and outputs of the
* LargestSquareBelow class's processBlock function. It stores this information in
* two ColumnTypes objects, one for the input parameter, and one for
* the return value.
*/
virtual void getPrototype(Vertica::ServerInterface &srvInterface,
Vertica::ColumnTypes &argTypes,
Vertica::ColumnTypes &returnType)
{
// Takes one int as input, so adds int to the argTypes object
argTypes.addInt();
// Returns a single int, so add a single int to the returnType object.
// ScalarFunctions always return a single value.
returnType.addInt();
}
public:
// the function cannot be called within a check constraint unless the UDx author
// certifies that the function is immutable:
LargestSquareBelowInfo() { vol = Vertica::IMMUTABLE; }
};
RegisterFactory 宏
使用 RegisterFactory
宏注册一个 ScalarFunctionFactory
子类。该宏将对工厂类进行实例化并将其包含的元数据供 Vertica 访问。要调用该宏,请将您的工厂类的名称传递给它。
RegisterFactory(LargestSquareBelowInfo);