UDFs: Packing and Unpacking Parameter Values

In addition to writing the UDF that does the work that you want, you must also write code to pack and unpack values and to detect NULL values.

As we saw in the code sample earlier:

INSERT INTO OutputStream
SELECT foo(InputStream.MyIntegerColumn)
FROM InputStream... ;

the server can call the UDF with zero or more parameters. Those parameters must be a data type that CCL supports (INTEGER, FLOAT, STRING, TIMESTAMP, and so on). Although the function is called with (and returns) a CCL data type, your C-language UDF must pass (and receive) a C data type (int, double, char *, and so on).

To ensure proper conversion between CCL data types and C data types, and to identify NULL values, CCL data types are processed and then stored in a single variable-size parameter that is passed to your UDF. This parameter is called the context parameter. Your UDF then calls library functions that extract the data and return it to you in a C-compatible format. This is called Unpacking. When you return a value to the caller, you go through the reverse process: Pack the return value by calling a special function that stores the value in a CCL-compatible format, and set a NULL flag if appropriate.

The UDF does the following:

  1. Declares appropriate C-language variables.

  2. Checks for NULL values and handles them appropriately.

  3. Unpacks the input parameters (reads context parameter and converts the data from the CCL data types to the C data types).

  4. Does the "real work" (for example, calculates pi).

  5. Packs the return value (converts the output value from a C-language data type to a CCL data type and copies that data into the output portion of the context parameter).

  6. Returns to the caller.

The context variable contains a copy of all the individual parameters that are intended for your UDF. The context variable also stores values that indicate whether each of the input parameters is NULL.

The context variable is declared as type C8UDF. Thus your function will declare a single parameter of type C8UDF. For example:

int foo(C8Udf ctx)
{
/* "Unpack" parameters from foo and store them 
 * in local variables. 
 */
...
}

An example call to this function looks like:

INSERT INTO OutStream
SELECT WAvg3(var1, weight1, var2, weight2, var3, weight3)... 

Note that we used the CCL name (WAvg3), not the C name (weightedAverage3). In the CCL code, the name is not case-sensitive.