C language simple table function
This example uses the following file name: sstring.c
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. Note the additional loop
logic in run.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nzaeapis.h"
static int run(NZAE_HANDLE h);
int main(int argc, char * argv[])
{
if (nzaeIsLocal())
{
NzaeInitialization arg;
memset(&arg, 0, sizeof(arg));
arg.ldkVersion = NZAE_LDK_VERSION;
if (nzaeInitialize(&arg))
{
fprintf(stderr, "initialization failed\n");
return -1;
}
run(arg.handle);
nzaeClose(arg.handle);
}
else {
NZAECONPT_HANDLE hConpt = nzaeconptCreate();
if (!hConpt)
{
fprintf(stderr, "error creating connection point\n");
fflush(stderr);
return -1;
}
const char * conPtName = nzaeRemprotGetRemoteName();
if (!conPtName)
{
fprintf(stderr, "error getting connection point name\n");
fflush(stderr);
exit(-1);
}
if (nzaeconptSetName(hConpt, conPtName))
{
fprintf(stderr, "error setting connection point name\n");
fflush(stderr);
nzaeconptClose(hConpt);
return -1;
}
NzaeremprotInitialization args;
memset(&args, 0, sizeof(args));
args.ldkVersion = NZAE_LDK_VERSION;
args.hConpt = hConpt;
if (nzaeRemprotCreateListener(&args))
{
fprintf(stderr, "unable to create listener - %s\n", \
args.errorMessage);
fflush(stderr);
nzaeconptClose(hConpt);
return -1;
}
NZAEREMPROT_HANDLE hRemprot = args.handle;
NzaeApi api;
int i;
for (i = 0; i < 5; i++)
{
if (nzaeRemprotAcceptApi(hRemprot, &api))
{
fprintf(stderr, "unable to accept API - %s\n", \
nzaeRemprotGetLastErrorText(hRemprot));
fflush(stderr);
nzaeconptClose(hConpt);
nzaeRemprotClose(hRemprot);
return -1;
}
if (api.apiType != NZAE_API_FUNCTION)
{
fprintf(stderr, "unexpected API returned\n");
fflush(stderr);
nzaeconptClose(hConpt);
nzaeRemprotClose(hRemprot);
return -1;
}
printf("testcapi: accepted a remote request\n");
fflush(stdout);
run(api.handle.function);
}
nzaeRemprotClose(hRemprot);
nzaeconptClose(hConpt);
}
return 0;
}
static int run(NZAE_HANDLE h)
{
NzaeMetadata metadata;
if (nzaeGetMetadata(h, &metadata))
{
fprintf(stderr, "get metadata failed\n");
return -1;
}
#define CHECK(value) \
{ \
NzaeRcCode rc = value; \
if (rc) \
{ \
const char * format = "%s in %s at %d"; \
fprintf(stderr, format, \
nzaeGetLastErrorText(h), __FILE__, __LINE__); \
nzaeUserError(h, format, \
nzaeGetLastErrorText(h), __FILE__, __LINE__); \
exit(-1); \
} \
}
if (metadata.outputColumnCount != 1 ||
metadata.outputTypes[0] != NZUDSUDX_VARIABLE)
{
nzaeUserError(h, "expecting one output column of type string");
nzaeDone(h);
return -1;
}
if (metadata.inputColumnCount != 1)
{
nzaeUserError(h, "expecting one input column");
nzaeDone(h);
return -1;
}
if (metadata.inputTypes[0] != NZUDSUDX_FIXED
&& metadata.inputTypes[0] != NZUDSUDX_VARIABLE)
{
nzaeUserError(h, "first input column expected to be a string type");
nzaeDone(h);
return -1;
}
for (;;)
{
int i;
double result = 0;
NzaeRcCode rc = nzaeGetNext(h);
if (rc == NZAE_RC_END)
{
break;
}
NzudsData * input = NULL;
CHECK(nzaeGetInputColumn(h, 0, &input));
const char * opString;
if (input->isNull)
{
nzaeUserError(h, "first input column may not be null");
nzaeDone(h);
return -1;
}
if (input->type == NZUDSUDX_FIXED)
{
opString = input->data.pFixedString;
} else if (input->type == NZUDSUDX_VARIABLE)
{
opString = input->data.pVariableString;
} else
{
nzaeUserError(h, "first input column expected to be a string \
type");
nzaeDone(h);
return -1;
}
const char *ptr = opString;
char *token;
while ((token = strtok(ptr, ",")) != NULL) {
ptr = NULL;
CHECK(nzaeSetOutputString(h, 0, token));
CHECK(nzaeOutputResult(h));
}
}
nzaeDone(h);
return 0;
}
Compilation
Use the standard
compile:
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language system --version 3 \
--template compile sstring.c --exe sstringRegistration
Register the newly created
"sstring"
executable:$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --language system --version 3 \
--template udtf --exe sstring --sig "sstring_c(VARCHAR(ANY))" \
--return "TABLE (val varchar(2000))"Running
Run the query in nzsql:
SELECT * FROM TABLE WITH FINAL(sstring_c('12:30:15'));
VAL
----------
12:30:15
(1 row)
SELECT * FROM TABLE WITH FINAL(sstring_c('12:30:15,two,three'));
VAL
----------
12:30:15
two
three
(3 rows)
SELECT * FROM TABLE WITH FINAL(sstring_c(NULL));
ERROR: first input COLUMN may NOT be NULL