/******************************************************************************* ** ** Source File Name = udfcli.c ** ** Licensed Materials - Property of IBM ** ** (C) COPYRIGHT International Business Machines Corp. 1995, 2000 ** All Rights Reserved. ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule Contract with IBM Corp. ** ** ** PURPOSE : ** Client for the UDFs from udfsrv.c . ** ** For more information about these samples see the README file. ** ** For more information on programming in CLI see the: ** - "Building CLI Applications" section of the Application Building Guide, and the ** - CLI Guide and Reference. ** ** For more information on the SQL language see the SQL Reference. ** *******************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlcli1.h> #include "utilcli.h" /* Header file for CLI sample code */ int ScalarUDFCall( SQLHANDLE) ; int SourcedUDFUse( SQLHANDLE) ; /******************************************************************* ** main *******************************************************************/ int main( int argc, char * argv[] ) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE henv; /* environment handle */ SQLHANDLE hdbc; /* connection handles */ char dbAlias[SQL_MAX_DSN_LENGTH + 1] ; char user[MAX_UID_LENGTH + 1] ; char pswd[MAX_PWD_LENGTH + 1] ; /* checks the command line arguments */ rc = CmdLineArgsCheck1( argc, argv, dbAlias, user, pswd ); if ( rc != 0 ) return( rc ) ; printf("\n\nUDFs: HOW TO CALL UDFs.\n"); /* initialize the CLI application */ rc = CLIAppInit( dbAlias, user, pswd, &henv, &hdbc, (SQLPOINTER)SQL_AUTOCOMMIT_ON); if ( rc != 0 ) return( rc ) ; rc = ScalarUDFCall( hdbc) ; rc = SourcedUDFUse( hdbc) ; /* terminate the CLI application */ rc = CLIAppTerm( &henv, &hdbc, dbAlias); return( rc ) ; } /* end main */ /****************************************************************************** ** ScalarUDFCall ******************************************************************************/ int ScalarUDFCall( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR * stmtDrop = ( SQLCHAR *) "DROP FUNCTION ScalarUDF"; SQLCHAR * stmtRegister = ( SQLCHAR *) " CREATE FUNCTION ScalarUDF (CHAR(5), float) RETURNS float " " FENCED " " EXTERNAL NAME 'udfsrv!ScalarUDF' " " NOT VARIANT NO SQL PARAMETER STYLE DB2SQL" " LANGUAGE C NO EXTERNAL ACTION "; SQLCHAR * stmtSelect = ( SQLCHAR *) "SELECT name, job, salary, ScalarUDF( job, salary)" " FROM staff WHERE name LIKE 'S%' " ; struct { SQLINTEGER ind ; SQLCHAR val[15] ; } name, job; struct { SQLINTEGER ind ; SQLDOUBLE val ; } salary, newSalary; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLExecDirect\n-SQLBindCol\n"); printf("-SQLFetch\n-SQLFreeHandle\n"); printf("TO CALL UDFs:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* execute directly the drop statement */ sqlrc = SQLExecDirect( hstmt, stmtDrop, SQL_NTS ) ; /* execute directly the register statement */ printf("\n Register the scalar UDF.\n"); sqlrc = SQLExecDirect( hstmt, stmtRegister, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* execute directly the select statement */ printf(" Use the scalar UDF performing this statement:\n"); printf(" SELECT name, job, salary, ScalarUDF( job, salary)\n"); printf(" FROM staff WHERE name LIKE 'S%%'\n"); sqlrc = SQLExecDirect( hstmt, stmtSelect, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* bind columns to variables */ sqlrc = SQLBindCol( hstmt, 1, SQL_C_CHAR, name.val, 15, &name.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); sqlrc = SQLBindCol( hstmt, 2, SQL_C_CHAR, job.val, 15, &job.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); sqlrc = SQLBindCol( hstmt, 3, SQL_C_DOUBLE, &salary.val, sizeof( salary.val), &salary.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); sqlrc = SQLBindCol( hstmt, 4, SQL_C_DOUBLE, &newSalary.val, sizeof( newSalary.val), &newSalary.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* fetch each row, and display */ printf(" Fetch each row and dispaly.\n"); printf(" NAME JOB SALARY NEW_SALARY\n"); printf(" ---------- ------ ---------- ----------\n"); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc); if (sqlrc == SQL_NO_DATA_FOUND) { printf("\n Data not found.\n"); } while (sqlrc != SQL_NO_DATA_FOUND) { printf(" %-10s %-7s %-7.2f %-7.2f\n", name.val, job.val, salary.val,newSalary.val); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc); } /* close the cursor */ sqlrc = SQLCloseCursor( hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* execute directly the drop statement */ sqlrc = SQLExecDirect( hstmt, stmtDrop, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); } /****************************************************************************** ** SourcedUDFUse ******************************************************************************/ int SourcedUDFUse( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR * stmt1 = ( SQLCHAR *) "CREATE DISTINCT TYPE CNUM AS INTEGER WITH COMPARISONS"; SQLCHAR * stmt2 = ( SQLCHAR *) "CREATE FUNCTION MAX(CNUM) RETURNS CNUM source sysibm.max(integer)"; SQLCHAR * stmt3 = ( SQLCHAR *) "CREATE TABLE CUSTOMER ( " "CustNum CNUM NOT NULL, " "CustName CHAR(30) NOT NULL)" ; SQLCHAR * stmt4 = ( SQLCHAR *) "INSERT INTO CUSTOMER VALUES " " ( CAST(1 AS CNUM), 'JOHN WALKER'), " " ( CAST(2 AS CNUM), 'BRUCE ADAMSON'), " " ( CAST(3 AS CNUM), 'SALLY KWAN')" ; SQLCHAR * stmt5 = ( SQLCHAR *) "SELECT CAST(MAX(CustNum) AS INTEGER ) FROM CUSTOMER " ; SQLCHAR * stmt6 = ( SQLCHAR *) "DROP TABLE CUSTOMER" ; SQLCHAR * stmt7 = ( SQLCHAR *) "DROP FUNCTION MAX(CNUM)" ; SQLCHAR * stmt8 = ( SQLCHAR *) "DROP DISTINCT TYPE CNUM" ; struct { SQLINTEGER ind ; SQLINTEGER val ; } maxCustNum; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLExecDirect\n-SQLBindCol\n"); printf("-SQLFetch\n-SQLFreeHandle\n"); printf("TO USE A SOURCED UDF:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* create a distinct type */ printf("\n Execute directly\n"); printf(" CREATE DISTINCT TYPE CNUM AS INTEGER\n"); printf(" WITH COMPARISONS\n"); sqlrc = SQLExecDirect( hstmt, stmt1, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* create a sourced UDF */ printf(" Execute directly\n"); printf(" CREATE FUNCTION MAX(CNUM) RETURNS CNUM\n"); printf(" source sysibm.max(integer)\n"); sqlrc = SQLExecDirect( hstmt, stmt2, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* create a table that uses the distinct type */ printf(" Execute directly\n"); printf(" CREATE TABLE CUSTOMER ( \n"); printf(" CustNum CNUM NOT NULL,\n"); printf(" CustName CHAR(30) NOT NULL)\n"); sqlrc = SQLExecDirect( hstmt, stmt3, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* insert values in table */ printf(" Execute directly\n"); printf(" INSERT INTO CUSTOMER VALUES\n"); printf(" ( CAST(1 AS CNUM), 'JOHN WALKER'),\n"); printf(" ( CAST(2 AS CNUM), 'BRUCE ADAMSON'),\n"); printf(" ( CAST(3 AS CNUM), 'SALLY KWAN')\n"); sqlrc = SQLExecDirect( hstmt, stmt4, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* execute directly the select statement */ printf(" Use the sourced UDF performing this statement:\n"); printf(" SELECT FROM CUSTOMER CAST(MAX(CUSTNUM) AS INTEGER)\n"); sqlrc = SQLExecDirect( hstmt, stmt5, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* bind columns to variables */ sqlrc = SQLBindCol( hstmt, 1, SQL_C_LONG, &maxCustNum.val, sizeof( maxCustNum.val), &maxCustNum.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* fetch the result */ printf(" Fetch the result.\n"); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc); if (sqlrc == SQL_NO_DATA_FOUND) { printf("\n Data not found.\n"); } else { printf( " Max(CustNum) is : %-8d \n", maxCustNum.val ) ; } /* close the cursor */ sqlrc = SQLCloseCursor( hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* drop the table */ printf(" Execute directly\n"); printf(" %s\n", stmt6); sqlrc = SQLExecDirect( hstmt, stmt6, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* drop the sourced UDF */ printf(" Execute directly\n"); printf(" %s\n", stmt7); sqlrc = SQLExecDirect( hstmt, stmt7, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* drop the distinct type */ printf(" Execute directly\n"); printf(" %s\n", stmt8); sqlrc = SQLExecDirect( hstmt, stmt8, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); }