Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Just can't figure out how to link to an anchor on a wiki page...

Table of Contents

Value Generating Functions


ADD2

Add two integers

MMA5

Return the min, max, and average of five integers
NULL values are treated the same as a zero

REVERSE

Reverse a string
Input string must be VARCHAR and can be up to 32 characters

Note: If you are looking for table-valued functions, see here.

Trafodion UDFs are "trusted" at this point in time. See "Security" below.

C source

cat > udf.c <<EOF
#include "sqludr.h"

SQLUDR_LIBFUNC SQLUDR_INT32 add2(SQLUDR_INT32 *in1,
                                 SQLUDR_INT32 *in2,
                                 SQLUDR_INT32 *out1,
                                 SQLUDR_INT16 *inInd1,
                                 SQLUDR_INT16 *inInd2,
                                 SQLUDR_INT16 *outInd1,
                                 SQLUDR_TRAIL_ARGS)
{
  if (calltype == SQLUDR_CALLTYPE_FINAL)
    return SQLUDR_SUCCESS;
  if (SQLUDR_GETNULLIND(inInd1) == SQLUDR_NULL ||
      SQLUDR_GETNULLIND(inInd2) == SQLUDR_NULL)
    SQLUDR_SETNULLIND(outInd1);
  else
    (*out1) = (*in1) + (*in2);
  return SQLUDR_SUCCESS;
}

SQLUDR_LIBFUNC SQLUDR_INT32 mma5(SQLUDR_INT32 *in1,
                                 SQLUDR_INT32 *in2,
                                 SQLUDR_INT32 *in3,
                                 SQLUDR_INT32 *in4,
                                 SQLUDR_INT32 *in5,
                                 SQLUDR_INT32 *out1,
                                 SQLUDR_INT32 *out2,
                                 SQLUDR_INT32 *out3,
                                 SQLUDR_INT16 *inInd1,
                                 SQLUDR_INT16 *inInd2,
                                 SQLUDR_INT16 *inInd3,
                                 SQLUDR_INT16 *inInd4,
                                 SQLUDR_INT16 *inInd5,
                                 SQLUDR_INT16 *outInd1,
                                 SQLUDR_INT16 *outInd2,
                                 SQLUDR_INT16 *outInd3,
                                 SQLUDR_TRAIL_ARGS)
{
  int sum = 0, min = 0, max = 0, avg = 0;
  int args[5];
  int i;
  if (calltype == SQLUDR_CALLTYPE_FINAL)
    return SQLUDR_SUCCESS;
  args[0] = (SQLUDR_GETNULLIND(inInd1) == SQLUDR_NULL ? 0 : *in1);
  args[1] = (SQLUDR_GETNULLIND(inInd2) == SQLUDR_NULL ? 0 : *in2);
  args[2] = (SQLUDR_GETNULLIND(inInd3) == SQLUDR_NULL ? 0 : *in3);
  args[3] = (SQLUDR_GETNULLIND(inInd4) == SQLUDR_NULL ? 0 : *in4);
  args[4] = (SQLUDR_GETNULLIND(inInd5) == SQLUDR_NULL ? 0 : *in5);
  sum = min = max = args[0];
  for (i = 1; i < 5; i++)
    {
      sum += args[i];
      min = (args[i] < min ? args[i] : min);
      max = (args[i] > max ? args[i] : max);
    }
  avg = sum / 5;
  *out1 = min;
  *out2 = max;
  *out3 = avg;
  return SQLUDR_SUCCESS;
}

/* Helper function to reverse a string */
static void reverseBytes(void *out, void *in, unsigned int numBytes)
{
  int i;
  char *pOut = (char *) out;
  char *pIn = (char *) in;
  for (i = 0; i < numBytes; i++)
    pOut[i] = pIn[numBytes - (i + 1)];
}

SQLUDR_LIBFUNC SQLUDR_INT32 reverse(SQLUDR_VC_STRUCT *in1,
                                    SQLUDR_VC_STRUCT *out1,
                                    SQLUDR_INT16 *inInd1,
                                    SQLUDR_INT16 *outInd1,
                                    SQLUDR_TRAIL_ARGS)
{
  if (calltype == SQLUDR_CALLTYPE_FINAL)
    return SQLUDR_SUCCESS;
  if (SQLUDR_GETNULLIND(inInd1) == SQLUDR_NULL)
    {
      SQLUDR_SETNULLIND(outInd1);
      return SQLUDR_SUCCESS;
    }
  reverseBytes(out1->data, in1->data, in1->length);
  out1->length = in1->length;
  return SQLUDR_SUCCESS;
}
EOF

Compile

gcc -g -Wall -I$TRAF_HOME/export/include/sql -shared -o udf.so udf.c

Register

Do this from the directory containing udf.so

UDFLIB="'$(pwd)/udf.so'"

sqlci <<EOF

create library myudfs file $UDFLIB;
-- ADD2
drop function add2;
create function add2(int,int) returns (add2 int)
  external name 'add2' library myudfs
  deterministic no sql no transaction required;

-- MMA5
drop function mma5;
create function mma5(int,int,int,int,int)
  returns (mma_min int, mma_max int, mma_avg int)
  external name 'mma5' library myudfs
  deterministic no sql no transaction required;

-- REVERSE
drop function reverse;
create function reverse(varchar(32)) returns (reverse varchar(32))
  external name 'reverse' library myudfs
  deterministic no sql no transaction required;

EOF

Invoke

sqlci <<EOF

-- CREATE A TABLE
drop table t;
create table t (a int primary key not null, b int, c int, d int, e int, f varchar(32));
insert into t values (1,2,3,4,5,'abc'), (6,7,8,9,10,'def'), (11,12,13,14,15,'ghi');

-- ADD2
select a, b, add2(a,b) from t;

-- MMA5
select mma5(a,b,c,d,e) from t;

-- REVERSE
select * from t where reverse(f) > 'g';

EOF

SHOWDDL

sqlci <<EOF
showddl function add2;
showddl function mma5;
showddl function reverse;
EOF

Security

Trafodion UDFs are "trusted" at this point in time. A "trusted" UDF has full access to any resources of the Trafodion engine. That means that a malicious UDF writer could compromise the privacy and consistency of the data. Therefore, only trusted users can be allowed to write UDFs. See the "Security Considerations" section in the TMUDF wiki article for how to grant users the privileges needed to create UDFs.