Creating the C++ file for a UDSF
To implement a UDSF, you create a class object that is derived
from the Udf base class. Continuing the
customername
example:#include "udxinc.h"
#include <string.h>
using namespace nz::udx_ver2;
class CCustomerName: public nz::udx_ver2::Udf
{
public:
};
Each UDSF must implement the following methods:
-
instantiate()
- This method is called by the runtime engine to create the object
dynamically. The static implementation must be outside the class definition.
The instantiate method takes one argument (UdxInit *pInit). The constructor
must take a UdxInit object as well and pass it to the base class constructor.
The instantiate method creates an object of the derived class type
by using the new operator and returns it (as base class type Udf)
to the runtime engine. The runtime engine deletes the object when
it is no longer needed. An example of the instantiate method follows:
#include "udxinc.h" #include <string.h> using namespace nz::udx_ver2; class CCustomerName: public nz::udx_ver2::Udf { public: CCustomerName(UdxInit *pInit) : Udf(pInit) { } static nz::udx_ver2::Udf* instantiate(UdxInit *pInit); }; nz::udx_ver2::Udf* CCustomerName::instantiate(UdxInit *pInit) { return new CCustomerName(pInit); }
evaluate()
- This method is called once for each row of data during execution.
#include "udxinc.h" #include <string.h> using namespace nz::udx_ver2; class CCustomerName: public nz::udx_ver2::Udf { public: CCustomerName(UdxInit *pInit) : Udf(pInit) { } static nz::udx_ver2::Udf* instantiate(UdxInit *pInit); virtual nz::udx_ver2::ReturnValue evaluate() { // Code to be inserted here } }; nz::udx_ver2::Udf* CCustomerName::instantiate(UdxInit *pInit) { return new CCustomerName(pInit); }
You can implement constructors and destructors as necessary. Constructors are required; you must specify a constructor even if it only invokes the base class constructor, as in the previous example. Within the constructor, you can set up any structures that are needed for computation (for example, setting up a matrix for encryption routines).
For the
customername
example, the UDSF evaluates
a string and returns the integer 1 if the string starts with Customer
A
; otherwise, it returns the integer 0. The code for the
evaluate method follows:virtual nz::udx_ver2::ReturnValue evaluate()
{
StringArg *str;
str = stringArg(0); // line 4
int lengths = str->length; // line 5
char *datas = str->data; // line 6
int32 retval = 0;
if (lengths >= 10)
if (memcmp("Customer A",datas,10) == 0) // line 9
retval = 1;
NZ_UDX_RETURN_INT32(retval); // line 11
}
In the sample program:
- Line 4 declares and uses a StringArg structure to pass the argument to the UDSF. Arguments to UDSFs are retrieved by using functions such as StringArg. See UDX arguments for a list of functions you can use to retrieve the input arguments for a UDSF. If this UDSF took a second string argument, the second argument would be referenced by StringArg(1).
- Lines 5 and 6 extract the length and character pointer (char*) from the StringArg structure.
- Line 9 uses memcmp (not strcmp) because StringArg structures are not null-terminated (\0) in UDXs. Therefore, strcmp, strcpy, strlen, atol, and other functions that depend on the presence of a null terminator do not work. If you need to use those functions, you must copy the string into a buffer and manually append the null terminator.
- Line 11 uses a macro to return the computed value to the Db2® database engine. The NZ_UDX_RETURN_INT32 macro helps to confirm that the return value is of the expected type. For a list of the available return macros, see UDX return value macros.