Re: Pro*C, '\0' and LONG columns

From: Thomas Kyte <tkyte_at_us.oracle.com>
Date: Wed, 19 May 1999 12:25:35 GMT
Message-ID: <3744a8fd.4359648_at_newshost.us.oracle.com>


A copy of this was sent to jgr_at_cix.compulink.co.uk ("John Ratcliffe") (if that email address didn't require changing) On Wed, 19 May 1999 11:46:01 GMT, you wrote:

>I would like to have a Pro*C routine that inserts and fetches text in and
>out of a LONG column. The text can be longer than the 32k limit on PL/SQL.
>In order to interface with other external systems the requirements are
>that this text must contain embedded ASCII null characters ('\0' in C).
>
>Does anyone know of a way of using Pro*C to do this?
>
>John Ratcliffe
>
>jgr_at_cix.compulink.co.uk
>
>
>BACKGROUND:
>
>Pro*C generates code that uses the C str* functions like strlen(), which
>doesn't help.
>

no, pro*c doesn't insert str* function calls into the code. it packs a structure with pointers and calls internal routines.

I don't think i've ever seen pro*c inject str* calls into code.

>Pro*C data types are built around the idea of C style strings, so any data
>type I tried did not help. I have tried VARCHARS, STRINGS, CHARZ but all

varchar is not. a varchar structure is explicitly *not* null terminated. It has a .len field and a .arr field.

>expect/use C style strings. Insertion meant that the string was inserted
>up to the first null character then space filled up to the specified
>length.
>
>I have tried altering the CHAR_MAP and DBMS pre compiler settings.
>
>I tried coercing data types for example, VARCHAR -> VARCHAR2, but that
>didn't help. It needs more code, and I found that I was getting some
>strange side effects, and life is too short.
>
>I know PL/SQL can do this, so it is not an Oracle restriction. However, I
>can't use PL/SQL because I want to handle strings > 32k.

Consider the following example:

SQL> create table t ( x long );

Table created.

SQL> desc t;

 Name                            Null?    Type
 ------------------------------- -------- ----
 X                                        LONG



with the pro*c code:

static void process()
{
exec sql begin declare section;
varchar my_string[100000];
exec sql end declare section;
int i;

#define TEXT "How Now \0 Brown Cow"
#define TEXT_LEN 20

    memmove( my_string.arr, TEXT, 20 );
    my_string.len = TEXT_LEN;

    exec sql whenever sqlerror do sqlerror_hard();     exec sql insert into t values ( :my_string );     exec sql commit work;

    memset( my_string.arr, 0, sizeof(my_string.arr) );     my_string.len = 0;

    exec sql select x into :my_string from t;

    printf( "my_string.len = %d\n", my_string.len );

    for( i = 0; i < my_string.len; i++ )

        printf( "--> %3d, %c\n", my_string.arr[i], my_string.arr[i] ); }

the output from that is:

my_string.len = 20

-->   72, H
-->  111, o
-->  119, w
-->   32,  
-->   78, N
-->  111, o
-->  119, w
-->   32,  
-->    0, 
-->   32,  
-->   66, B
-->  114, r
-->  111, o
-->  119, w
-->  110, n
-->   32,  
-->   67, C
-->  111, o
-->  119, w
-->    0, 




After I run that, i use the plsql block

SQL> declare

  2      y    long;
  3      z    varchar2(5000);
  4  begin
  5      select * into y from t;
  6      select dump(y) into z from dual;
  7  
  7      dbms_output.put_line( z );
  8      dbms_output.put_line( length(y) );
  9  
  9      for i in 1 .. length(y)
 10      loop
 11          dbms_output.put_line( '--> ' ||
 12                                to_char(ascii(substr(y,i,1)),'999') ||
 13                                ' ' ||
 14                                substr(y,i,1) );
 15      end loop;

 16 end;
 17 /

to verify my work independent of C and get:

Typ=1 Len=20:
72,111,119,32,78,111,119,32,0,32,66,114,111,119,110,32,67,111,119,0 20

-->   72 H
-->  111 o
-->  119 w
-->   32
-->   78 N
-->  111 o
-->  119 w
-->   32
-->    0
-->   32
-->   66 B
-->  114 r
-->  111 o
-->  119 w
-->  110 n
-->   32
-->   67 C
-->  111 o
-->  119 w
-->    0


which shows that both the embedded and trailing \0 was inserted for me. Both 'dump' and a manual dump show that.

See http://www.oracle.com/ideveloper/ for my column 'Digging-in to Oracle8i'...  

Thomas Kyte
tkyte_at_us.oracle.com
Oracle Service Industries
Reston, VA USA

-- 
Opinions are mine and do not necessarily reflect those of Oracle Corporation
Received on Wed May 19 1999 - 14:25:35 CEST

Original text of this message