Re: Pro*C 2.0 "char" bug

From: Timo Haatainen <Timo.Haatainen_at_tietogroup.com>
Date: 1997/06/06
Message-ID: <3397B433.20C1_at_tietogroup.com>


Rick Wiggins wrote:
>
> We've noticed an erroneous behavior with Pro*C 2.0 that doesn't seem to
> be present in versions 1.6 or 2.2. In version 2.0, if a CHAR(1)
> database column is SELECTed into a "plain old char" variable that's not
> an array (e.g. char one_char_var;), no error occurs, but the variable's
> contents ARE NOT REPLACED with what was (supposedly) pulled from the
> database! In version 1.6 and 2.2 things seem to work as expected; the
> character from the database ends up in the variable in the C program.
>
> To demonstrate the symptoms, I wrote a trivial Pro*C program that
> selects a CHAR(1) column value into various kinds of host variables.
> Each of the variables is initialized and displayed before the SELECT and
> then displayed afterwards.
>
> $ cat char.pc
> #include <stdio.h>
> EXEC SQL BEGIN DECLARE SECTION;
>
> char uid[2] = "/";
> EXEC SQL VAR uid IS STRING;
>
> char plain_old_char = 'Z';
>
> char char_string[2] = "S";
> EXEC SQL VAR char_string IS STRING;
>
> char charf_char = 'F';
> EXEC SQL VAR charf_char IS CHARF;
>
> EXEC SQL END DECLARE SECTION;
>
> EXEC SQL INCLUDE SQLCA;
>
> main()
> {
> EXEC SQL connect :uid;
>
> printf( "Before: plain_old_char='%c'\n", plain_old_char );
> printf( "Before: char_string=[%s]\n", char_string );
> printf( "Before: charf_char='%c'\n", charf_char );
> EXEC SQL
> SELECT
> dummy,
> dummy,
> dummy
> INTO
> :plain_old_char,
> :char_string,
> :charf_char
> FROM
> dual
> ;
> printf( "sqlca.sqlcode=(%d)\n", sqlca.sqlcode );
> printf( "After: plain_old_char='%c'\n", plain_old_char );
> printf( "After: char_string=[%s]\n", char_string );
> printf( "After: charf_char='%c'\n", charf_char );
> }
>
> To hopefully exclude anything we're doing to screw things up, I compiled
> this program using ORACLE's demo makefile instead of our
> application-specific compile procedures. I've shown my results below.
>
> Pro*C 1.6 (7.1.4) Compile command line and program output:
>
> $ make -f $ORACLE_HOME/proc16/demo/proc16.mk char
> $ mv char char.16
> $ char.16
> Before: plain_old_char='Z'
> Before: char_string=[S]
> Before: charf_char='F'
> sqlca.sqlcode=(0)
> After: plain_old_char='X' <--This is what I expected!
> After: char_string=[X]
> After: charf_char='X'
>
> Pro*C 2.0 (7.1.4) Compile command line and program output:
>
> $ make -f $ORACLE_HOME/precomp/demo/proc/proc.mk EXE=char.22
> OBJS=char.o
> $ char.20
> Before: plain_old_char='Z'
> Before: char_string=[S]
> Before: charf_char='F'
> sqlca.sqlcode=(0)
> After: plain_old_char='Z' <--This oughta be an 'X'!
> After: char_string=[X]
> After: charf_char='X'
>
> Pro*C 2.2 (7.3.2.3) Compile command line and program output:
>
> $ make -f $ORACLE_HOME/precomp/demo/proc/proc.mk EXE=char.22
> OBJS=char.o
> $ char.22
> Before: plain_old_char='Z'
> Before: char_string=[S]
> Before: charf_char='F'
> sqlca.sqlcode=(0)
> After: plain_old_char='X' <--This is what I expected!
> After: char_string=[X]
> After: charf_char='X'
>
> If you'll notice, with version 2.0 the initial value of
> "plain_old_char", 'Z', is still there AFTER the SELECT. I would have
> expected an 'X' since that's what's in the database and no error
> occurred. 1.6 and 2.2 returned an 'X', as expected. I've opened a TAR
> with ORACLE to find out if this is a known "bug" with 2.0 but am getting
> nowhere so far. The response on the CompuServe ORACLE Support forum was
> that "char in 1.6 is converted to CHARZ external datatype if mode=ansi
> and VARCHAR if mode=oracle. All 2.x (including 2.0 and 2.2) char is
> bound to CHARZ. ... contact the Language group in WW support ....", for
> whatever this is worth.
>
> We usually use null-terminated "strings" (char arrays) or varchar, not
> "plain old char" or exactly-sized char arrays, but this situation scares
> me since I haven't seen it explicitly addressed and it doesn't
> necessarily cause a program to abend; it just makes it "wrong". We have
> been bitten a couple of times in Production by this and never knew
> anything funny happened until data got fouled up enough downstream to
> cause an error to occur or a person to notice.
>
> If anyone has seen and/or struggled with this and has any more
> information about this "bug", I'd love to hear about it. Incidentally,
> we're on an NCR UNIX platform, but I'm not sure whether or not this
> problem is platform-specific.
>
> Sorry this is so verbose. Thanks in advance for any feedback.
> +================+========================================+
> | Rick Wiggins | Phone: (910)279-2270 |
> | Lead Developer | FAX: (910)697-8021 |
> | AT&T HRISO | Internet: mailto:rickwiggins_at_att.com |
> | Greensboro, NC | CompuServe: rick_wiggins |
> +================+========================================+

We were experiencing the same kind behaviour when moving from ProC 1.6 to ProC 2. The problem in our case was that we had VARCHAR(1) column in db and we fetched it into 'char plain_old_char'. The result was always NULL. The 'unofficial' explanation was that Oracle did put a 'varchar-struct'

	struct {
		short len;
		char  arr;
	}

into plain_old_char and what you saw in plain_old_char was the first byte of len-field which was 0.
If I remember right we changed the column to CHAR(1) and did no modifications to C-program. Then the effect was exactly the same than in your case (the value did not change after FETCH).

We corrected the problem by making changes into our code and replaced 'char plain_old_char' with 'VARCHAR plain_old_char[2]' (one extra byte for null-terminator). Of course we needed to change the manipulation of plain_old_char as well.

I'm glad to hear that ProC 2.2 works like 1.6 in this situation.

-- 

Timo Haatainen
Carelcomp Forest Oy
Received on Fri Jun 06 1997 - 00:00:00 CEST

Original text of this message