C Function Definition - Analytics Database - Teradata Vantage

SQL External Routine Programming

Deployment
VantageCloud
VantageCore
Edition
Enterprise
IntelliFlex
VMware
Product
Analytics Database
Teradata Vantage
Release Number
17.20
Published
June 2022
Language
English (United States)
Last Update
2023-07-11
dita:mapPath
iiv1628111441820.ditamap
dita:ditavalPath
qkf1628213546010.ditaval
dita:id
B035-1147
lifecycle
latest
Product Category
Teradata Vantage™
/*****  C source file name: sqlxspexample.c  *****/

#define SQL_TEXT Latin_Text
#include <sqltypes_td.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <coptypes.h>
#include <coperr.h>
#include <parcel.h>
#include <dbcarea.h>
#include <dbchqep.h>

typedef struct
{
    Word            StatementNo;
    Word            Info;
    Word            Code;
    Word            Length;
    char            Msg[1];         /* 1 to 255 bytes    */
 } PclErrorFailBody, *PclErrorFailBody_pt;

struct DBCAREA DBCArea;
char * pContext;
DBCAREA *pDBCArea;
DBCAREAX *pDbcAreaX;

/******************************************************************
     Initialize()  Initialize DBCAREA.
******************************************************************/
Int32 Initialize()
{
    Int32 Result;

    pDBCArea = &DBCArea;
    pDBCArea->total_len = sizeof(struct DBCAREA);

    DBCHINI(&Result, pContext, &DBCArea);

    pDBCArea->change_opts        = 'Y'  ;
    pDBCArea->req_buf_len        = 1024;
    pDBCArea->resp_buf_len       = 1024;
    pDBCArea->use_presence_bits  = 'N'  ;
    pDBCArea->keep_resp          = 'N'  ;
    pDBCArea->loc_mode           = 'Y'  ;
    pDBCArea->var_len_req        = 'N'  ;
    pDBCArea->save_resp_buf      = 'N'  ;
    pDBCArea->two_resp_bufs      = 'N'  ;
    pDBCArea->ret_time           = 'N'  ;
    pDBCArea->wait_for_resp      = 'Y'  ;
    pDBCArea->req_proc_opt       = 'E'  ;
    pDBCArea->maximum_parcel     = 'H';
    pDBCArea->resp_mode          = 'I';
    pDBCArea->dynamic_result_sets_allowed = 'Y';

    return Result;
}

/******************************************************************
     Logon()  Establish a default connection.
******************************************************************/
Int32 Logon(char *LogonStr)
{
    Int32                   Result;
    pDBCArea->func=DBFCON;
    if (LogonStr == NULL)
    {
       pDBCArea->create_default_connection = 'Y';
    }
    else
    {
        pDBCArea->logon_len = (Int32) strlen(LogonStr);
        pDBCArea->logon_ptr = LogonStr;
    }

    DBCHCL(&Result, pContext, pDBCArea);
    if (Result != EM_OK)
        return Result;

    /* Fetch the response  */
    pDBCArea->i_sess_id = pDBCArea->o_sess_id;
    pDBCArea->i_req_id  = pDBCArea->o_req_id;
    pDBCArea->func      = DBFFET;
    DBCHCL(&Result,pContext,pDBCArea);
    if (Result != EM_OK)
        return Result;

    if ( pDBCArea->fet_parcel_flavor != PclSUCCESS )
    {
        if (   pDBCArea->fet_parcel_flavor == PclFAILURE
            || pDBCArea->fet_parcel_flavor == PclERROR )
        {
            return pDBCArea->fet_parcel_flavor;
        }
    }

    /* End the logon request */
    pDBCArea->i_sess_id = pDBCArea->o_sess_id;
    pDBCArea->i_req_id  = pDBCArea->o_req_id;
    pDBCArea->func      = DBFERQ;
    DBCHCL(&Result, pContext, pDBCArea);
    return Result;
}

/******************************************************************
     Logoff()  Disconnect.
******************************************************************/
Int32 Logoff()
{
    Int32 Result;

    pDBCArea->func = DBFDSC;
    DBCHCL(&Result, pContext, pDBCArea);
    return Result;
}

/******************************************************************
     Execute() Execute the specified request.
******************************************************************/
Int32 Execute(char *ReqStr)
{
    Int32 Result;

    /* Issue the request */
    pDBCArea->func           = DBFIRQ;
    pDBCArea->change_opts    = 'Y';
    pDBCArea->req_ptr        = ReqStr;
    pDBCArea->req_len        = (Int32) strlen(pDBCArea->req_ptr);
    DBCHCL(&Result, pContext, pDBCArea);
    if (Result != EM_OK) return Result;

    /* Fetch the result parcels */
    pDBCArea->func = DBFFET;
    pDBCArea->change_opts    = 'Y';
    pDBCArea->i_req_id  = pDBCArea->o_req_id;

    while (Result == EM_OK)
       DBCHCL(&Result, pContext, pDBCArea);

    /* End the request */
    pDBCArea->func = DBFERQ;
    DBCHCL(&Result, pContext, pDBCArea);
    return Result;
}

/******************************************************************
     DoTheWork()  Create the tables, call the stored procedure.
******************************************************************/
void DoTheWork()
{
    Int32       Result;
    Int32       a;
    Int32       CallReqNo;
    Int32       Flavor;
    char        ReqStr[255];
    Int32*      pInt32;
    char*       pChar;

    /* Create a trace table */
    Result = Execute("DROP TABLE TraceTable;");
    if (Result != EM_OK) return;

    Result = Execute("CREATE TABLE TraceTable(SeqNo INT GENERATED BY 
DEFAULT AS IDENTITY, Flavor INT, Text VARCHAR(100));");
    if (Result != EM_OK) return;

    /* Create a table to insert and select rows */
    Result = Execute("DROP TABLE tab1;");
    if (Result != EM_OK) return;

    Result = Execute("CREATE TABLE tab1(a INT, b INT);");
    if (Result != EM_OK) return;

    /* Insert the rows */
    for (a=1;a<=10;a++)
    {
        pDBCArea->using_data_ptr        = (char *) &a;
        pDBCArea->using_data_len        = sizeof(a);
        Result = Execute("USING(a INT) INSERT tab1(:a, :a);");
        if (Result != EM_OK) return;
    }

    /* Call a procedure which will return a result set */
    pDBCArea->func           = DBFIRQ;
    pDBCArea->change_opts    = 'Y';
    pDBCArea->req_ptr        = "CALL p1('SEL * FROM tab1 ORDER BY 1');";
    pDBCArea->req_len        = (Int32) strlen(pDBCArea->req_ptr);
    DBCHCL(&Result, pContext, pDBCArea);
    if (Result != EM_OK) return;

    /* Remember the request number */
    CallReqNo = pDBCArea->o_req_id;

    /* Fetch the result parcels and insert into the trace table */
    while (Result == EM_OK)
    {
        /* Fetch a parcel from the CALL */
        pDBCArea->func = DBFFET;
        pDBCArea->change_opts    = 'Y';
        pDBCArea->i_req_id  = CallReqNo;

        DBCHCL(&Result, pContext, pDBCArea);
        if (Result != EM_OK) return;
        Flavor = pDBCArea->fet_parcel_flavor;

        /* Put this parcel into the trace table */
        pDBCArea->func           = DBFIRQ;
        pDBCArea->change_opts    = 'Y';
        pDBCArea->using_data_ptr = (char *) &Flavor;
        pDBCArea->using_data_len = sizeof(Flavor);

        if (pDBCArea->fet_parcel_flavor == PclSUCCESS)
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'Success')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclDATAINFO)
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'DataInfo')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclXDIX)
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'DataInfoX')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclRECORD)
        {
            /* Point to the integer in the record parcel, */
            /* skip past the indicator byte               */
            pChar = pDBCArea->fet_data_ptr;
            pChar++;
            pInt32 = (Int32 *) pChar;
            sprintf(ReqStr, 
               "USING (a INT) INSERT tracetable(,:a,'Record %d ')",
               *pInt32);
            pDBCArea->req_ptr = ReqStr;
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclENDSTATEMENT)
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'EndStatement')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclENDREQUEST)
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'EndRequest')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclRESULTSET)
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'ResultSet')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else if (pDBCArea->fet_parcel_flavor == PclFAILURE)
        {
            pChar = pDBCArea->fet_data_ptr;
            pChar += 4;
            pInt32 = (Int32 *) pChar;
            pChar += 4;
            for(a=0;a<strlen(pChar);a++)
               if(pChar[a]==0x27) pChar[a]=' ';
            sprintf(ReqStr,
               "USING (a INT) INSERT tracetable(,:a,'Failure %d %s')",
               (*pInt32)&0x0000ffff, pChar);
            pDBCArea->req_ptr = ReqStr;
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        else
        {
            pDBCArea->req_ptr = 
               "USING (a INT) INSERT tracetable(,:a,'')";
            pDBCArea->req_len = (Int32) strlen(pDBCArea->req_ptr);
        }
        DBCHCL(&Result, pContext, pDBCArea);
        if (Result != EM_OK) return;

        /* Fetch the success etc from the insert into the trace table */
        pDBCArea->func = DBFFET;
        pDBCArea->change_opts = 'Y';
        pDBCArea->i_req_id = pDBCArea->o_req_id;
        while (Result == EM_OK)
            DBCHCL(&Result, pContext, pDBCArea);

        /* End the insert request */
        pDBCArea->func = DBFERQ;
        DBCHCL(&Result, pContext, pDBCArea);

        /* Go and fetch the next parcel from the CALL */
    }
}

/******************************************************************
     Entry point for the external stored procedure.
******************************************************************/
void sqlxspex(
           char      sqlstate[6],
           SQL_TEXT  extname[129],
           SQL_TEXT  specific_name[129],
           SQL_TEXT  error_message[257])
{
    Initialize();

    Logon(NULL);

    DoTheWork();

    Logoff();

}