• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • No Automatic Casting for Char

    June 28, 2006 Howard Arner

    Recently, I did a Web services project to integrate a legacy iSeries system with a new GUI and a new Web-based interface. When programming the system, I needed to write a stored procedure to take incoming data and store it in the both the legacy program’s data tables and our “new” database. This new database was still on the iSeries, and was just new in the sense that it has more and varied fields and capabilities that the previous system. I found an interesting iSeries feature and would like to take the opportunity to present the potential problem with it and give you a work around.

    Part of the incoming data from our Web service was text that described a problem being reported. In the previous system, users were allowed to enter lines of text that were stored in a file associated with the problem record. The file contained a problem ID, text line number and then a 66 character field to hold that line of text. In the new system, we opted to store the text data in a CLOB object so as not to limit the amount of text information. This system was going to serve several thousand potential users and they would be rolled out department by department, therefore in order to perform the rollout we had to keep the green screen application updated and in sync with the new version of the system. I elected to write a stored procedure that would serve two purposes: Store the data in the “new” target tables and then update the legacy system. I won’t show you the entire procedure, but let’s recreate the situation so I can walk you through the problem.

    Here are the create table statements required to make the files referred to in these examples:

    /*create NTEST2 to represent new problem file*/
    
    CREATE TABLE SQLBOOK.NTEST2
    	(ID INTEGER NOT NULL, TDATA CLOB);
    
    /*create NTEST3 to represent legacy text file*/
    
    CREATE TABLE SQLBOOK.NTEST3
    	(ID INTEGER NOT NULL,
    	 LINENUM INTEGER NOT NULL,
    	 LINETEXT CHAR(66) NOT NULL,
    	 PRIMARY KEY(ID,LINENUM));
    
    Here is my first attempt at programming the procedure:
    
    /*vID and vText represent the ID of the problem and the 
    problem text only*/
    
    CREATE PROCEDURE sqlbook.clobtest1
    (vID  IN INTEGER ,
     vText  IN CLOB)
     LANGUAGE SQL 
     Modifies SQL DATA
    BEGIN
    DECLARE CL INTEGER;
    DECLARE T INTEGER DEFAULT 1;
    DECLARE i INTEGER DEFAULT 1;
    /*Write data to new file*/
    
    INSERT INTO sqlbook.ntest2 VALUES (vid,vtext);
    
    /*Get string length and update legacy file*/
    
    SET CL=LENGTH(vText);
    WHILE T<=CL DO
    	INSERT INTO sqlbook.ntest3 VALUES
    		(vid,i,SUBSTRING(vText,T,66));
    	SET T=T+66, i=i+1;
    END WHILE;
    END
    

    Now, I go to SQLThing or Operations Navigator and execute the following statement:

    CALL SQLBOOK.CLOBTEST1 (2,’this is some really long test that I need to pass you what do you think of it I do not know nor kare so that is all good men must come to the aid.’);

    I know the sample text is a lot of blather, but it will become clear in a moment. What is supposed to happen is that while the variable T, initialized to 1, is less than the variable CL, set to the length of the CLOB object, the program should substring the CLOB starting at position 1 with a length of 66 and write that substring to the file NEST3. Next, the program increments the variable I to the next line number and the position variable T to the value of 67, T+66. The program loops and then writes the second line which is the substring from position 67 for the next 66 characters. Finally, the program attempts to write the last line by making a substring from position 133 and then next 66 characters.

    However, there are only 14 characters left in the string and we are specifying to read 66; one would assume that this would return a string of the first 14 characters and then pad the result with blank characters. However, this is not the case as the substring function returns just the fist 14 characters and does not pad the string because the substring function returns the data type VARCHAR not CHAR. Now, it doesn’t seem like this should present a problem, as we are inserting into a CHAR 66 field, but it does. See, the internally generated program does not clear the string variable that it uses to hold the result of the substring and write it to the NTEST3 file; and by not clearing the internal variable the results of the last operation, a full 66 character string are still there. The program uses a memory move to put just the 14 characters of the resultant varchar from the substring operation into the filled 66 character variable. Your variable now contains the characters you desire along with garbage left over from the previous operation.

    Here is a screen shot of the data written to the legacy table NTEST3, which demonstrates the problem. You can recreate this by using the statement:

    SELECT * FROM SQLBOOK.NTEST3


    Fixing the Problem

    In order to fix this, you need to cast the result of the substring operation to the appropriate data type. A side effect of the cast operation is that it will append blank characters to the end of the third substring operation and thereby overwrite any data left in the buffer. Here is the revised procedure that correctly writes the data:

    CREATE PROCEDURE sqlbook.clobtest2
    (vID  IN INTEGER ,
     vText  IN CLOB)
     LANGUAGE SQL 
     Modifies SQL DATA
    BEGIN
    DECLARE CL INTEGER;
    DECLARE T INTEGER DEFAULT 1;
    DECLARE i INTEGER DEFAULT 1;
    /*Write data to new file*/
    
    INSERT INTO sqlbook.ntest2 VALUES (vid,vtext);
    
    /*Get string length and update legacy file*/
    
    SET CL=LENGTH(vText);
    WHILE T<=CL DO
    	INSERT INTO sqlbook.ntest3 VALUES
    		(vid,i,CAST(SUBSTRING(vText,T,66) AS CHAR(66)));
    	SET T=T+66, i=i+1;
    END WHILE;
    END
    

    Once this version of the procedure is created, simply re-execute the call to the stored procedure with the following code:

    CALL SQLBOOK.CLOBTEST2 (3,’this is some really long test that I need to pass you what do you think of it I do not know nor kare so that is all good men must come to the aid.’);

    Now execute the following SQL statement and view the correctly written text:

    SELECT * FROM SQLBOOK.NTEST3;


    Notice that in the figure showing the output of the select statement, the text is correctly written for the last line and no longer contains the data from the substring operation.

    The moral of this story: never assume. No automatic casting is performed when attempting to write from a VARCHAR to a CHAR column, so you need to ensure that you perform the CAST operation in order to clear any byte droppings from the table.

    Howard Arner is a consultant that primarily writes .NET programs that keep all of their data on the industrial strength System i platform. You can contact him at hfarner@sqlthing.com or visit his site at www.SQLThing.com to learn more about SQL, purchase his books, or download free products and code.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Computer Keyes

    Fax Directly from your IBM i

    KeyesFax is a full function automated IBM i fax system. Spooled files are burst by fax number and auto transmitted with overlays.  It combines both a send and receive facsimile processing system with a complete image package.

    The fax software will edit, send, receive, display, print, and track fax documents or images using any standard IBM i without additional expensive hardware, software or subscriptions.

    Computer Keyes has been developing Software Solutions since 1978!

    www.computerkeyes.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    ASNA:  DataGate for access to OS/400 DB2 UDB and SQL Server from any .NET application
    COMMON:  Join us at the Fall 2006 conference, September 17-21, in Miami Beach, Florida
    Integrated Print Solutions:  Print AFP/IPDS documents to any network printer

    IBM and Georgia Tech Push Silicon’s Speed Limit up to 500 GHz Why Unix Experience Matters for System i5 Sales

    Leave a Reply Cancel reply

Volume 6, Number 25 -- June 28, 2006
THIS ISSUE SPONSORED BY:

T.L. Ashford
Asymex
WorksRight Software

Table of Contents

  • Query/400 Handles Zero Dates (Sort Of)
  • No Automatic Casting for Char
  • Admin Alert: Creating More Distinctive PC5250 Window Titles

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18
  • Will The Turbulent Economy Downdraft IBM Systems Or Lift It?
  • How IBM Improved The Database With IBM i 7.6
  • Rocket Celebrates 35th Anniversary As Private Equity Owner Ponders Sale
  • 50 Acres And A Humanoid Robot With An AI Avatar
  • IBM i PTF Guide, Volume 27, Number 17

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle