1 Informix C UDR
This section explains how to create Informix Functions in C Language.
1.1 Creating a basic C UDR function
Informix C UDR use the MI interface to interact with the engine. To create a callable C function, write the c code into a file (e.g. myproc.c):
#include <mi.h> void myproc(user, fparam) mi_lvarchar *user; MI_FPARAM *fparam; { MI_CONNECTION *conn; MI_DATABASE_INFO *dbInfo; mi_string *strptr; conn = mi_open(NULL, NULL, NULL); /* If connection descriptor is NULL, there was an error connecting to the session context. */ if ( conn == NULL ) { mi_db_error_raise(conn, MI_EXCEPTION, "myproc: cannot establish connection", NULL); } else { fprintf(stderr,"connected to db, getting dbInfo"); mi_get_database_info(conn,dbInfo); strptr = mi_lvarchar_to_string(user); fprintf(stderr,"\nPassed user: %s DB User is %s\n", strptr, dbInfo->user_name); mi_free(strptr); mi_close(conn); } }
Compile the C code using Standard Informix IDS Folders. For Linux O.S. use gcc and -fPIC:
gcc -fPIC -I${INFORMIXDIR}/incl/public -DMI_SERVBUILD -L${INFORMIXDIR}/lib/esql -shared myproc.c -o myproc.so
Finally, register C UDR function and you can use it directly from the engine as any other SPL function:
CREATE DBA PROCEDURE myproc ( VARCHAR(8) ) EXTERNAL NAME '/home/informix/BLADE/myproc.so(myproc)' LANGUAGE C VARIANT; GRANT EXECUTE ON myproc TO PUBLIC; execute procedure myproc("HELLO");
1.2 Passing and returning arguments
allocates the return value only once the first time the function is called, stores the pointer in the MI_FPARAM structure, and retrieves the pointer for subsequent invocations. Specific code notes include:
- i_fp_setfuncstate() and mi_fp_funcstate() let you store and retrieve user-defined data in the MI_FPARAM structure.
- The first time a function is called, mi_fp_funcstate() returns NULL, so that is how you tell this is the first time the function has been called.
- So in Good Code #2, line 15 retrieves the pointer using mi_fp_funcstate() and checks on line 16 to see if it is NULL. If it is NULL, this is the first time the function has been called, so line 18 allocates storage and line 24 stores the pointer in the MI_FPARAM using mi_fp_setfuncstate().
- Line 18 allocates storage PER_COMMAND, which guarantees that the memory won't be freed until it is no longer needed by the query.
1 #include <mi.h> 2 #include <math.h> 3 4 mi_double_precision * 5 MyLog10(mi_double_precision *x, MI_FPARAM *fParam) 6 { 7 mi_double_precision *retval=NULL; 8 9 if (*x <= 0) 10 { 11 mi_db_error_raise(NULL, MI_EXCEPTION, "Input argument must be > 0!"); 12 return (mi_double_precision *)NULL; /* not reached */ 13 } 14 15 retval=(mi_double_precision *) mi_fp_funcstate(fParam); 16 if(retval==(mi_double_precision *) NULL) /* First time called */ 17 { 18 retval=(mi_double_precision *)mi_dalloc(sizeof(mi_double_precision),PER_COMMAND); 19 if(retval==(mi_double_precision *) NULL) 20 { 21 mi_db_error_raise(NULL, MI_EXCEPTION, "Memory allocation failed!"); 22 return (mi_double_precision *)NULL; /* not reached */ 23 } 24 mi_fp_setfuncstate (fParam, (void *) retval); 25 } 26 27 /* math library's log10() returns its result by value */ 28 *retval=log10(*x); 29 return (retval); 30 }
Compile the C code using Standard Informix IDS Folders. For Linux O.S. use gcc and -fPIC:
gcc -fPIC -I${INFORMIXDIR}/incl/public -DMI_SERVBUILD -L${INFORMIXDIR}/lib/esql -shared log10.c -o log10.so
Finally, register C UDR function and you can use it directly from the engine as any other SPL function:
create function MyLog10 (float) returns float with (not variant) external name "$INFORMIXDIR/extend/log10.so(MyLog10)" language c; execute function MyLog10 (1.5);
To check if an argument is null use fparam method:
mi_double_precision * MyLog10 (x, fParam) mi_double_precision *x; MI_FPARAM *fParam; { mi_double_precision *retval; if (mi_fp_argisnull(fParam,0) == MI_TRUE) /* RIGHT! */ { mi_fp_setreturnisnull(fParam, 0, MI_TRUE); /* RIGHT! */ return (mi_double_precision *)NULL; } ... }
1.3 Extending Informix
Extending Informix:
https://www.ibm.com/support/knowledgecenter/SSGU8G_14.1.0/com.ibm.extendnode.doc/extend.htm
Function Reference:
https://www.ibm.com/support/knowledgecenter/SSGU8G_14.1.0/com.ibm.dapif.doc/ids_dapif_023.htm
.
https://informix.hcldoc.com/14.10/help/index.jsp?topic=%2Fcom.ibm.dapip.doc%2Fids_dapip_0023.htm
Example:
https://www.ibm.com/developerworks/data/zones/informix/library/techtip/db_bad_code.html