| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Usenet -> c.d.o.tools -> Re: oci stored procedure parameter bind
Tom,
Thanks for your quick reply to my post. Unfortunately, your answer didn't seem to fix the problem. I have included with this message copies of the code used to generate the package procedure and C executable. I am using a library of oci calls that was written to emulate the PHP style oci calls to simplify coding. The function within the library that calls obndra has also been included:
PACKAGE dc_test
IS
TYPE ttchar16 IS TABLE OF VARCHAR2(16) INDEX BY BINARY_INTEGER;
PROCEDURE log_msg (in_msg_num IN messages.msg_num%TYPE,
in_msg_txt IN messages.msg_txt%TYPE,
results OUT NUMBER);
PROCEDURE test_oci (inout_txt IN OUT ttchar16);
END;
PACKAGE BODY dc_test IS
PROCEDURE log_msg (in_msg_num IN messages.msg_num%TYPE,
in_msg_txt IN messages.msg_txt%TYPE,
results OUT NUMBER) IS
BEGIN
results := 0;
INSERT INTO messages VALUES(in_msg_num, in_msg_txt, SYSDATE);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('Oracle Error ' || SQLERRM);
END log_msg;
PROCEDURE test_oci (inout_txt IN OUT ttchar16) IS
results NUMBER;
func_name VARCHAR2(16) := 'test_oci: ';
BEGIN
log_msg(1,
func_name || 'inout_txt 1:' || inout_txt(1), results);
log_msg(1,
func_name || 'inout_txt 2:' || inout_txt(2), results);
inout_txt(1) := 'Return Text 1';
inout_txt(2) := 'Return Text 2';
END test_oci;
END;
#include <dblib.h>
#include <db.h>
static oraConnection conn;
static oraCursor cursor;
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <ctype.h>
#include <signal.h>
#include <curses.h>
#include <term.h>
#include <errno.h>
#include <string.h>
#include <sys/shm.h>
#include "proto.h"
#include "myapp.h"
#include "app.h"
#include "myapplp.h"
#define MAX_RECS 2
sb2 indp[MAX_RECS];
ub2 alen[MAX_RECS];
ub2 arcode[MAX_RECS];
char inout_str[80];
char inout_text[MAX_RECS][16];
char ac_locprog[PRGNMSZ+1], /* local program name */
ac_locnode[SYSNMSZ+1], /* local program node */
ac_hostname[SYSNMSZ+1]; /* name of computer program is on */
char ac_logmsg[161];
char ac_sql[8192];
int main(argc, argv)
int argc;
char *argv[];
{
char *pc_locprog;
void cleanup(int);
/* --- Get the local system host name. --- */
gethostname(ac_hostname, sizeof(ac_hostname));
/* --- Get the program name from the runstring. --- */
if((pc_locprog = strrchr(argv[0], '/')) == NULL)
strcpy(ac_locprog, argv[0]);
else
strcpy(ac_locprog, ++pc_locprog);
/* --- Connect to the database. --- */
if(!ora_logon(&conn, (char *)pc_dbuserid)) {
fprintf(stderr,"Connect: %s\n",ora_error(&conn));
cleanup(EXIT_FAILURE);
}
if(!ora_open(&cursor,&conn)) {
fprintf(stderr,"Open: %s\n",ora_error(&cursor));
cleanup(EXIT_FAILURE);
}
strcpy(inout_text[0], "Some Text...");
strcpy(inout_text[1], "More Text...");
sprintf(ac_sql,
"BEGIN \n"
" dc_test.test_oci(\n"
" :inout_text\n"
" );\n"
"END;\n");
if(!ora_parse(&cursor, ac_sql)) {
fprintf(stderr,"ora_parse: %s\n", ora_error(&cursor));
cleanup(EXIT_FAILURE);
}
if(!ora_bindspvara(&cursor, ":inout_text", inout_text, 16, SQLT_STR,
indp, alen, arcode, MAX_RECS, "INOUT")) {
fprintf(stderr,"ora_bindspvar(:inout_text): %s\n",
ora_error(&cursor));
cleanup(EXIT_FAILURE);
}
if(!ora_exec(&cursor)) {
fprintf(stderr,"ora_exec:%s\n", ora_error(&cursor));
cleanup(EXIT_FAILURE);
}
printf("inout_text1=[%s]\n", inout_text[0]);
printf("inout_text2=[%s]\n", inout_text[1]);
cleanup(EXIT_SUCCESS);
}
/************************************************************************** **************************************************************************Function cleanup() -- Close data base, detach from shared memory segment,
shutdown UISG, close XCS, and exit the program.
**************************************************************************
**************************************************************************/
void cleanup(j_exitcode)
int j_exitcode;
{
/* Disconnect from Oracle */
if(!ora_close(&cursor)) {
sprintf(ac_logmsg,"Close: %s\n",ora_error(&cursor));
logmsg(SYS_MSGSEV, ac_locprog, ac_hostname, ac_logmsg);
}
sprintf(ac_logmsg,"Disconnect: %s\n",ora_error(&conn));
logmsg(SYS_MSGSEV, ac_locprog, ac_hostname, ac_logmsg);
}
exit(j_exitcode);
}
int ora_bindspvara(oraCursor *p_curs, char *pc_name, void *buf, size_t buflen,
sword type, sb2 *indp, ub2 *alen, ub2 *arcode, int
j_maxsiz,
char *pc_inout)
ORAERR();
if(strncmp(pc_inout, "IN", 2) == 0) {
for(j=0; j<j_maxsiz; j++) {
indp[j] = 0;
alen[j] = (ub2)buflen;
mycursiz = (ub4)j_maxsiz;
return obndra(&p_curs->cda, pc_name, -1, (ub1 *)buf, (sword) buflen, type,
-1, indp, alen, arcode, (ub4)j_maxsiz, &mycursiz,
(text *) 0,
-1, -1) ? ORA_FAIL : ORA_SUCCESS;
}
Thanks again for any help you can provide,
John Bullock
OCI Programmer (Wannabee)
Thomas Kyte <tkyte_at_us.oracle.com> wrote in message news:<9gkpm602cu4_at_drn.newsguy.com>...
> In article <bfd9866f.0106180053.32c895cc_at_posting.google.com>,
> jbullock_at_neo.rr.com says...
> >
> >I am trying to get a standard C application to call an existing
> >database stored procedure using the OCI library. The program uses
> >function "obndra" to bind a parameter declared as "IN OUT" and "TABLE
> >OF VARCHAR2(16)" to a two dimensional C char array. When the
> >application is run, the following error is reported:
> >
> >error 1485 "compile bind length different from execute bind length"
> >
> >If I modify the stored procedure parameter to be OUT only, the C app
> >works fine.
> >
> >Can anyone tell me if you can bind to an "IN OUT" parameter this way?
> >
> >I would like to know if it's even possible to bind to an "IN OUT"
> >procedure parameter using "obndra". I have not included copies of the
> >software here because the application can be made to work, although it
> >would be more effective to leave the existing stored procedure as is.
> >I will supply stored procedure and C code upon request if more
> >information is required.
> >
> >Thanks in advance for any help you can give.
>
>
> 01485, 00000, "compile bind length different from execute bind length"
> // *Cause: You bound a buffer of type DTYVCS (VARCHAR with the two byte
> // length in front) and at execute time the length in the first two
> // bytes is more than the maximum buffer length (given in the bind
> // call). The number of elements in the array and the current number
> // of elements in the array cannot be more than the maximum size of
> // the array.
>
>
> that typically means the data in the array on the way in was un-initialized. It
> is customary to set the length fields to the maximum width for uninitialized
> data on the way in.
>
>
> Here is an example from a pro*c app that needed to dynamically call a procedure
> with a PLSQL table type:
>
> static void process()
> {
> Lda_Def lda;
> Cda_Def cda;
> char stmt[255];
> char ename[40];
> char data[50][255];
> short data_l[50];
> short data_i[50];
> short data_rc[50];
> int data_nelements;
> int i;
>
>
> sqllda( &lda );
>
> if ( oopen(&cda,&lda,NULL,-1,01,NULL,-1) ) oci_error(lda,cda);
>
> strcpy( stmt, "begin do_something( :p_table ); end;" );
>
> if ( oparse(&cda, stmt, -1, 0, 2 ) ) oci_error(lda,cda);
>
> /* init all array elements to NULL and set their max length */
> for( i = 0; i < sizeof(data)/sizeof(data[0]); i++ )
> {
> data_i[i] = -1;
> data_l[i] = sizeof(data[0]);
> }
>
> /* for the elements we have data for, fix the NULL indicator and
> put some data in there */
> for( data_nelements = 0; data_nelements < 15; data_nelements++ )
> {
> data_i[data_nelements] = 0;
> sprintf( data[data_nelements], "Some data %d", data_nelements );
> }
>
> /* Bind it */
> if (
> obndra( &cda, /* cursor data area */
> ":p_table", /* bind variable name */
> -1, /* indicates prev. parameter is C String */
> (void*)data, /* data array (plsql table) */
> sizeof(data[0]), /* sizeof each array element */
> STRING_TYPE, /* binding C strings in table */
> -1, /* scale (not used) */
> data_i, /* indicators for the i'th tbl entry */
> data_l, /* lengths of the i'th tbl entry */
> data_rc, /* return codes for the i'th tbl entry */
> sizeof( data )/sizeof(data[0]), /* MAXsize of array */
> &data_nelements, /* CURRENT size of array */
> (void*)0, /* not used */
> -1, /* not used */
> -1 ) /* not used */
> ) oci_error(lda,cda);
>
> /* run it */
> if( oexec( &cda ) ) oci_error(lda,cda);
>
> /* show it... */
> for( i = 0; i < data_nelements; i++ )
> printf( "Element(%d), Length = %d ind = %d = %s\n",
> i, data_l[i], data_i[i], data[i] );
> }
Received on Tue Jun 19 2001 - 12:56:15 CDT
![]() |
![]() |