C++ language simple table function

This example uses the following file name: split.cpp

Code

The code in this example creates a function that splits a string into multiple strings based on the delimiter. This example may return more rows of output than input. Because of this, it cannot use the handler model and requires additional error handling logic. Note the try catch block in the main and the loop logic in run. Also note that code must be supplied to retrieve the record objects, output the object, and delete the record objects.
#include <nzaefactory.hpp>
using namespace nz::ae;
using namespace std;
static int run(nz::ae::NzaeFunction *aeFunc);
int main(int argc, char * argv[])
{
NzaeApiGenerator helper;
// The following line is only needed if a launcher is not used
helper.setName("testcapi");
for (int i=0; i < 2; i++) {
nz::ae::NzaeApi &api = helper.getApi(nz::ae::NzaeApi::FUNCTION);
try {
run(api.aeFunction);
}
catch (nz::ae::NzaeException &ex) {
if (api.aeFunction) {
api.aeFunction->userError(ex.what());
}
break;
}
if (!helper.isRemote())
break;
}
return 0;
}
static void split_string(string text,char delim, vector<string>& words)
{
int i=0;
char ch;
string word;
while((ch=text[i++]))
{
if (ch == delim)
{
if (!word.empty())
{
words.push_back(word);
}
word = "";
}
else
{
word += ch;
}
}
if (!word.empty())
{
words.push_back(word);
}
}
static int run(NzaeFunction *aeFunc)
{
const NzaeMetadata& meta = aeFunc->getMetadata();
if (meta.getOutputColumnCount() != 1 ||
meta.getOutputType(0) != NzaeDataTypes::NZUDSUDX_VARIABLE) {
throw NzaeException("expecting one output column of type string");
}
if (meta.getInputColumnCount() != 1) {
throw NzaeException("expecting one input column");
}
if (meta.getInputType(0) != NzaeDataTypes::NZUDSUDX_FIXED &&
meta.getInputType(0) != NzaeDataTypes::NZUDSUDX_VARIABLE) {
throw NzaeException("first input column expected to be a string type");
}
for (;;)
{
nz::ae::NzaeRecord *input = aeFunc->next();
if (!input)
break;
nz::ae::NzaeRecord *output = aeFunc->createOutputRecord();
NzaeField &field = input->get(0);
if (field.isNull())
throw NzaeException("first input column may not be null");
NzaeStringField &sf = (NzaeStringField&) input->get(0);
std::string str = (std::string)sf;
vector<string> words;
split_string(str,',', words);
for (int i=0; i < (int)words.size(); i++) {
string tip = words[i];
NzaeStringField &sf = (NzaeStringField&) output->get(0);
sf = tip;
aeFunc->outputResult(*output);
}
delete input;
delete output;
}
aeFunc->done();
return 0;
}

Compilation

Use the standard compile:
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language cpp --template compile \
--exe splitae --compargs "-g -Wall" --linkargs "-g" split.cpp --version 3

Registration

Register the newly created "splitae" executable:
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "splitae(VARCHAR(ANY))" \
--return "table(val varchar(2000))" --language cpp --template udtf \
--exe splitae --version 3

Running

Run the query in nzsql:
SELECT * FROM TABLE WITH FINAL(splitae('12:30:15'));
VAL
----------
12:30:15
(1 row)
SELECT * FROM TABLE WITH FINAL(splitae('12:30:15,two,three'));
VAL
----------
12:30:15
two
three
(3 rows)
SELECT * FROM TABLE WITH FINAL(splitae(NULL));
ERROR: first input COLUMN may NOT be NULL