Re: Pro*C ANSI C Variable Length Strings

From: Thomas Kyte <tkyte_at_us.oracle.com>
Date: 1998/02/26
Message-ID: <34f8d84c.24914755_at_192.86.155.100>#1/1


A copy of this was sent to "Thomas Hilke" <Thomas.Hilke_at_dlh.de> (if that email address didn't require changing) On Thu, 26 Feb 1998 19:30:20 +0100, you wrote:

>>
>
>
>This is good.
>
>But now I'm try to do this in a seperate function like
>"varchar_copy(´VARCHAR *source, VARCHAR *dest)" .
>
>I have trouble with the the call of this function ( of an function that
>should get a pointer of VARCHAR as parameter).
>

The problem here is that when the ProC preprocess sees

VARCHAR 	x[5];
VARCHAR     y[10];


It needs 2 structures -- one for varchar 5 and another for 10. It cannot just use one typedef for any varchar as each varchar may be a different size. If you look at the output of preprocessing something like:

EXEC SQL BEGIN DECLARE SECTION;
VARCHAR oracleid[50];
VARCHAR tmp[10];
EXEC SQL END DECLARE SECTION; You'll see that it looks like:

/* EXEC SQL BEGIN DECLARE SECTION; */
#line 31 "t.pc"

/* VARCHAR oracleid[50]; */
struct { unsigned short len; unsigned char arr[50]; } oracleid; #line 32 "t.pc"

/* VARCHAR tmp[50]; */
struct { unsigned short len; unsigned char arr[10]; } tmp; #line 33 "t.pc"

/* EXEC SQL END DECLARE SECTION; */
#line 34 "t.pc"

You see, in this example, oracleid and tmp each have their own structure definition and aren't type compatible (they each define their own type). They are not VARCHAR types *as far as C is concerned*.

The solution to your problem is something like:

void varchar_copy( VARCHAR * dest, VARCHAR * src ) {

    strncpy( dest->arr, src->arr, src->len );     dest->len = src->len;
}

void main()
{
.....

   varchar_copy( (VARCHAR *)&tmp, (VARCHAR *)&oracleid ); }

Or, what I prefer to do with VARCHARS is to use inline macros. For example:

#define vstrcpy( a, b ) \
(strcpy( a.arr, b ), a.len = strlen( a.arr ), a.arr)

#define vstrcat( a, b ) \
(strcat( a.arr, b ), a.len = strlen( a.arr ), a.arr)

#define vmaxlen( a ) \
(a.len = sizeof(a.arr))

#define vnull( a ) \
(a.arr[ a.len ] = 0)

#define vstring( a ) \
(a.arr[a.len] = 0, a.arr)

This works to convert C strings into Oracle VARCHARs and back. For example:

EXEC SQL BEGIN DECLARE SECTION;
VARCHAR oracleid[50];
EXEC SQL END DECLARE SECTION;    vstrcpy( oracleid, "scott/tiger" );

   vstrcat( oracleid, "_at_somedatabase" );

   printf( "Here is the C string of an Oracle Varchar '%s'\n", vnull(oracleid));

>The compiler brings up the following warnings :
>
>>
>> cc: "sample1.c", line 534: warning 604: Pointers are not
 assignment-compatible.
>> cc: "sample1.c", line 534: warning 563: Argument #1 is not the correct
 type.
>> cc: "sample1.c", line 534: warning 604: Pointers are not
 assignment-compatible.
>> cc: "sample1.c", line 534: warning 563: Argument #2 is not the correct
 type.
>> cc: warning 463: Ignoring the option '+Ostatic_prediction'; use this
 option with '+P'.
>>
>
>The function is defined as follows :
>
>void varchar_copy(VARCHAR *source,VARCHAR *dest)
> {
> message("test");
> }
>
>
>
 

Thomas Kyte
tkyte_at_us.oracle.com
Oracle Government
Bethesda MD  

http://govt.us.oracle.com/ -- downloadable utilities  



Opinions are mine and do not necessarily reflect those of Oracle Corporation  

Anti-Anti Spam Msg: if you want an answer emailed to you, you have to make it easy to get email to you. Any bounced email will be treated the same way i treat SPAM-- I delete it. Received on Thu Feb 26 1998 - 00:00:00 CET

Original text of this message