Home Page for the TeradataForum
 

 

UDF Library: 'nthValue'

Component: 'nthValue.c'


 
<< readme.txt install_from_server.txt >>

/*
   Function: nthValue
   Author: Robert D. Meunier - Database Fusion
   Version: 1.0

   Purpose: To extract the Nth value from a delimited list of values.

   Syntax: nthValue( InputString, Delimiter[*], NthPosition)
   Where:  InputString:  A SQL VarChar datatype containing the list of
                         delimited values.
   Delimiter:  The character that is used to delimit the list.
               The delimiter must be a single character followed
               by an optional asterisk. The asterisk says to treat
               multiple back to back delimiters as a single
               delimiter.
   NthPosition:  The value from within the delimited list that
                 is to be returned.
   Returns: A SQL VarChar datatype containing the requested postitional
            value from the list of values. If a NULL InputString is
            Supplied NULL will be returned. If NthPosition is out of range
            a zero length string will be returned.
*/

/* How to create this function through BTEQ:
REPLACE FUNCTION syslib.nthValue( InputString VARCHAR(32767), Delimiter VARCHAR(2), NthPosition INTEGER )
           RETURNS VARCHAR(1024)
           LANGUAGE C
           NO SQL
           PARAMETER STYLE SQL
           CALLED ON NULL INPUT
           EXTERNAL NAME 'SS!nthValue!nthValue.c!F!nthValue'
;
*/

#define SQL_TEXT Latin_Text
#include "sqltypes_td.h"
#include <string.h>
#define EOS '\0'
#define IsNULL -1
#define IsNotNULL 0
#define NoSQLError "00000"
#define NoSQLErrorStr ""
/* MAX_RESULT needs to be set to the VARCHAR lenght of the RETURNS parameter */
/* in the REPOLACE FUNCTION statement. */
#define MAX_RESULT 1024

void nthValue(  VARCHAR_LATIN *inputStr
              , VARCHAR_LATIN *delim
              , INTEGER *nthPos
              , VARCHAR_LATIN *nthValue
              , int *inputStrInd
              , int *delimInd
              , int *nthPosInd
              , int *nthValueInd
              , char SQLState[6]
              , SQL_TEXT extName[129]
              , SQL_TEXT specificName[129]
              , SQL_TEXT errorMessage[257]
              )
{
  /* Define variables */
  int delimLen;
  int curPos=1;
  int resultLen=0;

  /* Initialize some stuff... */
  *nthValue = '\0';
  *nthValueInd = IsNotNULL;
  strcpy(SQLState, NoSQLError);
  strcpy((char *) errorMessage, NoSQLErrorStr);

  /* If input is NULL return NULL */
  if ( *inputStrInd == IsNULL ) {
       *nthValueInd = IsNULL;
       return;
  }

  /* Validate the parameter "Delimiter" */
  if ( *delimInd == IsNULL ) {
       strcpy(SQLState, "U0011");
       strcpy((char *) errorMessage, "Parameter \"Delimiter\" can not be null.");
       return;
  }
  else {
         delimLen = (int) strlen((const char *)delim);
         if ( delimLen != 1 ) {
              if ( delimLen == 2 && delim[1] == '*') {
                   /* No-op */
                 }
              else {
                     strcpy(SQLState, "U0012");
                     strcpy((char *) errorMessage,
                          "Parameter \"Delimiter\" should by one character followed by an optional asterisk.");
                     return;
                   }
            }
  }

  /* Validate the parameter "nth Position" */
  if ( *nthPosInd == IsNULL ) {
       strcpy(SQLState, "U0021");
       strcpy((char *) errorMessage, "Parameter \"Nth Position\" can not be null.");
       return;
  }

  /* Loop throught the input string until:
       1) reach end-of-string
       2) get past the requested value */
  for (; *inputStr != EOS && curPos <= *nthPos && resultLen < MAX_RESULT ; inputStr++) {
         /* Look for the delimiter */
         if ( *inputStr == *delim ) {
              curPos++;
              if ( delim[1] == '*' ) {
                   /* If "*" is specified, loop throught the input string until:
                         1) reach end-of-string
                         2) get past the requested value
                         3) the current value is no longer the delimiter */
                   while ( *inputStr != EOS && curPos <= *nthPos && *inputStr == *delim ) {
                           inputStr++;
                         }
                   inputStr--; /* back up to the last delimiter character */
                 }
            }
         /* If this is the Nth value in the list, building the return string */
            else if ( curPos == *nthPos ) {
                      strncat((char *)nthValue, (const char *)inputStr, (size_t )1);
                      resultLen++;
                    }
  }
  return;
}


<< readme.txt install_from_server.txt >>





 
  Top Home Privacy Feedback  
 
Copyright for the TeradataForum (TDATA-L), Manta BlueSky
Copyright 2016 - All Rights Reserved
Last Modified: 28 Jun 2020