/******************************************************************************* ** ** Source File Name = udfcli.sqc ** ** 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 : ** To demonstrate how to use User-Defined Funtions, It includes scalar UDF ** and sourced UDF in embedded SQL. ** This is a client for the UDFs from CLI udfsrv.c . ** ** For more information about these samples see the README file. ** ** For more information on the SQL language see the SQL Reference. ** *******************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlenv.h> #include "utilemb.h" EXEC SQL INCLUDE SQLCA; int ScalarUDFCall( ) ; int SourcedUDFUse( ) ; int main(int argc, char *argv[]) { EXEC SQL BEGIN DECLARE SECTION; char userid[9]; char passwd[19]; EXEC SQL END DECLARE SECTION; int rc; printf( "\nSample C program: udfcli \n"); if (argc == 1) { EXEC SQL CONNECT TO sample; EMB_SQL_CHECK ("CONNECT TO SAMPLE"); } else if (argc == 3) { strcpy (userid, argv[1]); strcpy (passwd, argv[2]); EXEC SQL CONNECT TO sample USER :userid USING :passwd; EMB_SQL_CHECK ("CONNECT TO SAMPLE"); } else { printf ("\nUSAGE: %s [userid passwd]\n\n",argv[0]); return 1; } rc = ScalarUDFCall( ) ; rc = SourcedUDFUse( ) ; EXEC SQL ROLLBACK; EMB_SQL_CHECK ("ROLLBACK"); EXEC SQL CONNECT RESET; EMB_SQL_CHECK ("CONNECT RESET"); return 0; } /****************************************************************************** ** SourcedUDFUse ******************************************************************************/ int SourcedUDFUse() { int rc = 0; char * stmt1 = "CREATE DISTINCT TYPE CNUM AS INTEGER WITH COMPARISONS"; char * stmt2 = "CREATE FUNCTION MAX(CNUM) RETURNS CNUM source sysibm.max(integer)"; char * stmt3 = "CREATE TABLE CUSTOMER ( " "CustNum CNUM NOT NULL, " "CustName CHAR(30) NOT NULL)" ; char * stmt4 = "INSERT INTO CUSTOMER VALUES " " ( CAST(1 AS CNUM), 'JOHN WALKER'), " " ( CAST(2 AS CNUM), 'BRUCE ADAMSON'), " " ( CAST(3 AS CNUM), 'SALLY KWAN')" ; char * stmt5 = "SELECT CAST(MAX(CustNum) AS INTEGER ) FROM customer " ; char * stmt6 = "DROP TABLE CUSTOMER" ; char * stmt7 = "DROP FUNCTION MAX(CNUM)" ; char * stmt8 = "DROP DISTINCT TYPE CNUM" ; EXEC SQL BEGIN DECLARE SECTION; char prep_str[200]; sqlint32 maxCustNum_val; EXEC SQL END DECLARE SECTION; printf("%sCREATE DISTINCT TYPE CNUM AS INTEGER\n",sp5); printf("%sWITH COMPARISONS\n",sp5); EXEC SQL CREATE DISTINCT TYPE CNUM AS INTEGER WITH COMPARISONS; EMB_SQL_CHECK ("Create DISTINCT"); /* create a sourced UDF */ printf(" CREATE FUNCTION MAX(CNUM) RETURNS CNUM\n"); printf(" source sysibm.max(integer)\n"); EXEC SQL CREATE FUNCTION MAX(CNUM) RETURNS CNUM source sysibm.max(integer); EMB_SQL_CHECK ("Create FUNCTION"); /* create a table that uses the distinct type */ printf("%sCREATE TABLE CUSTOMER ( \n",sp5); printf("%sCustNum CNUM NOT NULL,\n",sp8); printf("%sCustName CHAR(30) NOT NULL)\n",sp8); EXEC SQL CREATE TABLE customer (CustNum CNUM NOT NULL, CustName CHAR(30) NOT NULL); EMB_SQL_CHECK ("Create TABLE"); /* insert values in table */ printf("%sINSERT INTO CUSTOMER VALUES\n",sp5); printf("%s( CAST(1 AS CNUM), 'JOHN WALKER'),\n",sp8); printf("%s( CAST(2 AS CNUM), 'BRUCE ADAMSON'),\n",sp8); printf("%s( CAST(3 AS CNUM), 'SALLY KWAN')\n",sp8); strcpy(prep_str,stmt4); EXEC SQL PREPARE statement1 from :prep_str; EMB_SQL_CHECK ("PREPARE"); EXEC SQL EXECUTE statement1; EMB_SQL_CHECK ("Insert TABLE"); /* execute directly the select statement */ printf("%sUse the sourced UDF performing this statement:\n",sp5); printf("%sSELECT FROM CUSTOMER CAST(MAX(CUSTNUM) AS INTEGER)\n",sp8); strcpy(prep_str,stmt5); EXEC SQL PREPARE statement1 from :prep_str; EMB_SQL_CHECK ("PREPARE"); EXEC SQL DECLARE c1 CURSOR FOR statement1; EXEC SQL OPEN c1 ; EMB_SQL_CHECK ("OPEN"); EXEC SQL FETCH c1 INTO :maxCustNum_val ; EMB_SQL_CHECK ("SELECT TABLE"); if (SQLCODE ==0 ){ printf( "%sMax(CustNum) is : %-8d \n", sp8,maxCustNum_val ) ; } EXEC SQL CLOSE c1; /* drop the table */ printf("%s%s\n",sp5,stmt6); EXEC SQL DROP TABLE customer ; EMB_SQL_CHECK ("DROP TABLE"); /* drop the sourced UDF */ printf("%s%s\n", sp5,stmt7); strcpy(prep_str,stmt7); EXEC SQL PREPARE statement1 from :prep_str; EMB_SQL_CHECK ("PREPARE"); EXEC SQL EXECUTE statement1; EMB_SQL_CHECK ("DROP FUNCTION"); /* drop the distinct type */ printf("%s%s\n",sp5,stmt8); EXEC SQL DROP DISTINCT TYPE CNUM ; EMB_SQL_CHECK ("DROP TYPE"); return(rc); error: EXEC SQL WHENEVER SQLERROR continue; printf("Error occured SQLCODE =%d \n SQLERRMES=%s\n", SQLCODE,sqlca.sqlerrmc); return(rc); } /****************************************************************************** ** ScalarUDFCall ******************************************************************************/ int ScalarUDFCall( ) { int rc = 0; char * stmtDrop = "DROP FUNCTION ScalarUDF"; char * stmtRegister = " 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 "; EXEC SQL BEGIN DECLARE SECTION; char * stmtSelect = "SELECT name, job, salary, ScalarUDF( job, salary)" " FROM staff WHERE name LIKE 'S%' " ; char name_val[10]; char job_val[6]; double salary_val,newsalary_val; EXEC SQL END DECLARE SECTION; printf("\nUSE THE EMBEDDED SQL \n"); printf("-Scalar UDF\n"); printf("TO CALL UDFs:\n"); EXEC SQL DROP FUNCTION ScalarUDF; if (SQLCODE !=0) { printf("%sNo function dropped\n",sp5); } printf("%sRegister the scalar UDF.\n",sp5); EXEC SQL 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 ; EMB_SQL_CHECK ("Create Function"); printf("%sUse the scalar UDF performing this statement:\n",sp5); printf("%sSELECT name, job, salary, ScalarUDF( job, salary)\n",sp8); printf("%sFROM staff WHERE name LIKE 'S%%'\n",sp8); EXEC SQL PREPARE statement2 from :stmtSelect; EMB_SQL_CHECK ("PREPARE"); EXEC SQL DECLARE c2 CURSOR FOR statement2; EXEC SQL OPEN c2 ; EMB_SQL_CHECK ("OPEN"); /* fetch each row, and display */ printf("%sFetch each row and display.\n",sp5); printf("%sNAME JOB SALARY NEW_SALARY\n",sp8); printf("%s---------- ------ ---------- ----------\n",sp8); EXEC SQL FETCH c2 INTO :name_val,:job_val,:salary_val, :newsalary_val; EMB_SQL_CHECK ("Fetch"); if (SQLCODE == 100) { printf("%sData not found.\n",sp5); } while (SQLCODE == 0 ) { printf("%s%-10s %-7s %-7.2f %-7.2f\n", sp8,name_val, job_val, salary_val,newsalary_val); EXEC SQL FETCH c2 INTO :name_val,:job_val,:salary_val, :newsalary_val; } EMB_SQL_CHECK ("Fetch"); /* close the cursor */ EXEC SQL CLOSE c2; EXEC SQL DROP FUNCTION ScalarUDF; return(rc); error: EXEC SQL WHENEVER SQLERROR continue; printf("Error occured SQLCODE =%d \n SQLERRMES=%s\n", SQLCODE,sqlca.sqlerrmc); return(rc); }