Sample UDTF with generic return value
The following program creates a UDTF that returns a table size of ANY. It uses the calculateShape method to create table shape that is based on the input.
/*
This UDTF takes in a string (CHAR or VARCHAR) and returns
three columns:
- UPPER_CASE: the upper case of the string
- lower_case: the lower case of the string
- Title_Case: the title case of the string
The function is VARARGS, so it will determine the types
of the columns based on the type of the input argument.
The output strings will have the same data type as the
input string (CHAR(x) or VARCHAR(x)).
Compile:
=======
nzudxcompile --sig "UcLcTc()" --varargs --return "TABLE(ANY)" --class
"UcLcTc" --version 2 --unfenced --db test UcLcTc.cpp
Example SQL:
===========
CREATE TABLE words (key VARCHAR(20), text VARCHAR(600));
INSERT INTO words VALUES ('1','Hello World');
INSERT INTO words VALUES ('2','Hello dave goodbye dave');
INSERT INTO words VALUES ('2','Hello Dave Hello World');
INSERT INTO words VALUES ('3','goodbye world');
CREATE TABLE words_uclctc AS SELECT * FROM words, TABLE ( UcLcTc(text)
);
*/
#include "udxinc.h"
using namespace nz::udx_ver2;
class UcLcTc : public Udtf {
private:
bool output;
public:
UcLcTc(UdxInit *pInit) : Udtf(pInit) { }
static Udtf* instantiate(UdxInit *pInit);
void newInputRow() {
output = true;
}
DataAvailable nextOutputRow() {
if (!output) {
output = true;
return Done;
}
StringArg *str = stringArg(0);
bool strNull = isArgNull(0);
if (strNull) {
return Done;
}
StringReturn *uc = stringReturnColumn(0);
StringReturn *lc = stringReturnColumn(1);
StringReturn *tc = stringReturnColumn(2);
if ((uc->size < str->length)
|| (lc->size < str->length)
|| (tc->size < str->length))
throwUdxException("Input too long for output");
memcpy(uc->data, str->data, str->length);
uc->size = str->length;
memcpy(lc->data, str->data, str->length);
lc->size = str->length;
memcpy(tc->data, str->data, str->length);
tc->size = str->length;
for (int i = 0; i < str->length; i++) {
if ((uc->data[i] >= 'a') && (uc->data[i] <= 'z'))
uc->data[i] = uc->data[i] - 'a' + 'A';
if ((lc->data[i] >= 'A') && (lc->data[i] <= 'Z'))
lc->data[i] = lc->data[i] - 'A' + 'a';
if (((0 == i) || (' ' == tc->data[i-1]))
&& ((tc->data[i] >= 'a') && (tc->data[i] <= 'z')))
tc->data[i] = tc->data[i] - 'a' + 'A';
}
output = false;
return MoreData;
}
void calculateShape(UdxOutputShaper *shaper) {
if (shaper->numArgs() != 1)
throwUdxException("Expecting only one argument");
int nType = shaper->argType(0);
if ((UDX_FIXED == nType) || (UDX_VARIABLE == nType)) {
int len = shaper->stringArgSize(0);
char ucstr[] = "UPPER_CASE"; // For column names on systems that
char lcstr[] = "lower_case"; // use lowercase naming
char tcstr[] = "Title_Case";
char ucstrU[] = "UPPER_CASE"; // For column names on systems
char lcstrU[] = "LOWER_CASE"; // that use uppercase naming
char tcstrU[] = "TITLE_CASE";
if (shaper->isSystemCaseUpper()) {
shaper->addOutputColumn(nType, ucstrU, len);
shaper->addOutputColumn(nType, lcstrU, len);
shaper->addOutputColumn(nType, tcstrU, len);
}
else {
shaper->addOutputColumn(nType, ucstr, len);
shaper->addOutputColumn(nType, lcstr, len);
shaper->addOutputColumn(nType, tcstr, len);
}
}
else {
throwUdxException("Only CHAR and VARCHAR types are supported");
}
}
};
Udtf* UcLcTc::instantiate(UdxInit *pInit) {
return new UcLcTc(pInit);
}