Elvis,
   Sorry if I sounded snippy.  I realize that my
sample code was poorly written, and I appreciate you
pointing out the things that you did.  I learned
several things from your reply, which is a sizable
percentage of C knowledge for me given how little I
know (although I _am_ learning the "C will not only
let you shoot yourself in the foot, it will let the
bullet ricochet into unlikely places" lesson).
   The code was my attempt at "least common
denominator" code that would show SQL (embedded in C)
inserting a blank-padded string where SQL (embedded in
RPGLE) would insert a null-terminated string.
   In actual practice, I am not using a char field in
the table; it is a graphic field with a CCSID of
13488.  The values being written to that field are
supplied by a java program, including the padding with
nulls; that program is expecting those values back as
orginally passed in, including the nulls.  Since I now
know how C is supposed to write this (at least, C
using embedded SQL), I can figure out the best way to
deal with the overall problem I have.
   Thanks again for you time, knowledge, and patience.

Don Whittaker
   

--- Donald Whittaker <donald_whittaker@xxxxxxxxx>
wrote:

> Elvis,
>    Thanks for the info.  And sorry for the sloppy
> code; I was trying to condense the orginal into the
> least amount of lines for testing.
>    So the answer to my orginal question would be
> "The
> expected behavior is for the insert to drop the null
> character(s) and pad with blank(s), and that is done
> by SQL (and so the *CNULRQD is not pertinent)."
>    So I guess my step is to post to the RPG list to
> see why embedded SQL in RPGLE _is_ writing the null
> character(s)....
> 
> Thanks,
> Don Whittaker
>    
> 
> --- Elvis Budimlic
> <ebudimlic@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
> 
> > Your base issue is that SQL performs data
> validation
> > when it writes
> > (inserts) records, instead of traditional RPG way
> of
> > doing data validation
> > on the reads.
> > If you run your program under debug (just type
> > STRDBG in your interactive
> > session) you'll see that one of the messages is
> > SQL7939.  Here is the
> > relevant text from that message:
> > 
> >
>
===================================================================
> > Message . . . . :   Data conversion required on
> > INSERT or UPDATE.
> > Cause . . . . . :   The INSERT or UPDATE values
> can
> > not be directly moved to
> > 
> >   the columns because the data type or length of a
> > value is different than
> > one
> >   of the columns. The INSERT or UPDATE statement
> ran
> > correctly.
> > Performance, 
> >   however, would be improved if no data conversion
> > was required. The reason
> > 
> >   data conversion is required is 3.
> > 
> > ......
> >    -- Reason 3 is that the INSERT or UPDATE value
> is
> > a variable length
> > string
> >  and column FLD2 is not.
> > 
> > ......
> > Recovery  . . . :   To get better performance, try
> > to use values of the same
> > 
> >   type and length as their corresponding columns.
> > 
> >
>
===================================================================
> > 
> > So, everything is working as designed (WAD as IBM
> > puts it).
> > Even if you find a way to turn off data
> validation,
> > I would strongly
> > recommend against it as it safeguards you from
> > future errors.  
> > If you really need to place invalid data into the
> > character field, you'll
> > need to use native I/O.  RPG is an obvious
> > candidate, but you can do it in C
> > using _R* functions (i.e. _Ropen, _Rwrite,
> _Rclose).
> >  No data validation
> > takes place on writes and very little on reads.
> > 
> > I have some general questions on your test code
> > unrelated to the error you
> > are seeing.  
> > 
> > *  memset(wrkFld2, 0, 64); 
> > It is bad practice to hardcode array size like
> this.
> >  Use this instead:
> >    memset(wrkFld2, 0, sizeof(wrkFld2);
> > 
> > *  memcpy(wrkFld2, "From C", sizeof(wrkFld2));
> > Your input buffer "From C" has size of 7 bytes,
> and
> > you are copying 64 bytes
> > starting at the undefined address of the temporary
> > buffer "From C".  Most of
> > the time you'll get lucky and what follows those 7
> > bytes will be hex zeros
> > (nulls), but there is no guarantee.  Here is one
> > possible correction, but I
> > list another in the alternate source on the
> bottom:
> >    memcpy(wrkFld2, "From C", strlen("From C") >
> > sizeof(wrkFld2) ?
> > sizeof(wrkFld2) : strlen("From C");
> > 
> > * tPtr = (char *)&wrkFld2;
> > You are pointing tPtr to the address of wrkFld2
> > pointer, which is not what
> > you intended to do.  You intended to point it to
> the
> > address of what wrkFld2
> > pointer is pointing to.  Yes, I said wrkFld2 is a
> > pointer! It points to the
> > address allocated by those 64 bytes.  This is what
> > you should have used:
> > tPtr = wrkFld2 + 7;
> > Why it worked in your test program?  Because
> > compiler took care of you.  But
> > not all compilers will do that.
> > 
> > Here is my take on your test code just for
> > illustration purposes (i.e. it
> > fails with the same data conversion error):
> > 
> > #include <stdlib.h>                               
>  
> >                        
> > #include <string.h>                               
>  
> >                        
> >                                                   
>  
> >                        
> > EXEC SQL INCLUDE SQLCA;                           
>  
> >                        
> >                                                   
>  
> >                        
> > int main(int args, char *argv[] )  {              
>  
> >                        
> >     EXEC SQL BEGIN DECLARE SECTION;               
>  
> >                        
> >        long     wrkFld1;                          
>  
> >                        
> >        char     wrkFld2[64];                      
>  
> >                        
> >     EXEC SQL END DECLARE SECTION;                 
>  
> >                        
> >     char testStr[] = "From C";                    
>  
> >                        
> >     int len = strlen(testStr);                    
>  
> >                        
> >                                                   
>  
> >                        
> >     memset(wrkFld2, 0, sizeof(wrkFld2));          
>  
> >                        
> >     wrkFld1 = 11;                                 
>  
> >                        
> >     memcpy(wrkFld2, testStr, len > sizeof(wrkFld2)
> ?
> > sizeof(wrkFld2) : len);
> >                                                   
>  
> >                        
> >     EXEC SQL                                      
>  
> >                        
> >        insert into QGPL/TESTSQL3                  
>  
> >                        
> >              ( Fld1, Fld2)          
> >       values ( :wrkFld1, :wrkFld2); 
> > }                                   
> >   
> > I realize I probably over-explained this, but I
> > always wished someone
> > explained these things to me when I was getting
> > started with C programming
> > on the iSeries.
> > 
> > Good luck with your project and post back if you
> > have other issues.
> > 
> > Elvis
> 
=== message truncated ===



                
__________________________________ 
Yahoo! Mail - PC Magazine Editors' Choice 2005 
http://mail.yahoo.com

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available here. If you have questions about this, please contact [javascript protected email address].