IBM Books

Application Development Guide


Example: Using a Locator to Work With a CLOB Value

In this example, the application program retrieves a locator for a LOB value; then it uses the locator to extract the data from the LOB value. Using this method, the program allocates only enough storage for one piece of LOB data (the size is determined by the program) and it needs to issue only one fetch call using the cursor.

How the Sample LOBLOC Program Works

  1. Declare host variables. The BEGIN DECLARE SECTION and END DECLARE SECTION statements delimit the host variable declarations. Host variables are prefixed with a colon (:) when referenced in an SQL statement. CLOB LOCATOR host variables are declared.

  2. Fetch the LOB value into the host variable LOCATOR. A CURSOR and FETCH routine is used to obtain the location of a LOB field in the database to a host variable locator.

  3. Free the LOB LOCATORS. The LOB LOCATORS used in this example are freed, releasing the locators from their previously associated values.

The CHECKERR macro/function is an error checking utility which is external to the program. The location of this error checking utility depends upon the programming language used:

C
check_error is redefined as CHECKERR and is located in the util.c file.

COBOL
CHECKERR is an external program named checkerr.cbl.

FORTRAN
CHECKERR is a subroutine located in the util.f file.

See Using GET ERROR MESSAGE in Example Programs for the source code for this error checking utility.

C Sample: LOBLOC.SQC

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
 
#ifdef DB268K
/* Need to include ASLM for 68K applications */
#include <LibraryManager.h>
#endif
 
EXEC SQL INCLUDE SQLCA;
 
#define  CHECKERR(CE_STR)   if (check_error (CE_STR, &sqlca) != 0) return 1;
 
int main(int argc, char *argv[]) {
 
   EXEC SQL BEGIN DECLARE SECTION; (1)
      char number[7];
      long deptInfoBeginLoc;
      long deptInfoEndLoc;
      SQL TYPE IS CLOB_LOCATOR resume;
      SQL TYPE IS CLOB_LOCATOR deptBuffer;
      short lobind;
      char buffer[1000]="";
      char userid[9];
      char passwd[19];
   EXEC SQL END DECLARE SECTION;
 
#ifdef DB268K
   /* Before making any API calls for 68K environment,
      need to initial the Library Manager */
        InitLibraryManager(0,kCurrentZone,kNormalMemory);
        atexit(CleanupLibraryManager);
#endif
 
   printf( "Sample C program: LOBLOC\n" );
 
   if (argc == 1) {
      EXEC SQL CONNECT TO sample;
          CHECKERR ("CONNECT TO SAMPLE");
   }
   else if (argc == 3) { 
      strcpy (userid, argv[1]);
      strcpy (passwd, argv[2]);
      EXEC SQL CONNECT TO sample USER :userid USING :passwd;
      CHECKERR ("CONNECT TO SAMPLE");
   }
   else {
      printf ("USAGE: lobloc [userid passwd]");
      return 1;
   } /* endif */
   
   /* Employee A10030 is not included in the following select, because 
      the lobeval program manipulates the record for A10030 so that it is 
      not compatible with lobloc */
 
   EXEC SQL DECLARE c1 CURSOR FOR
      SELECT empno, resume FROM emp_resume WHERE resume_format='ascii' 
      AND empno <> 'A00130'; 
 
   EXEC SQL OPEN c1;
   CHECKERR ("OPEN CURSOR");
 
   do {
      EXEC SQL FETCH c1 INTO :number, :resume :lobind;  (2)
      if (SQLCODE != 0) break;
      if (lobind < 0) {
         printf ("NULL LOB indicated\n");
      } else {
         /* EVALUATE the LOB LOCATOR */
         /* Locate the beginning of "Department Information" section */
         EXEC SQL VALUES (POSSTR(:resume, 'Department Information'))
            INTO :deptInfoBeginLoc;
         CHECKERR ("VALUES1");
 
         /* Locate the beginning of "Education"
            section (end of "Dept.Info")       */
         EXEC SQL VALUES (POSSTR(:resume, 'Education'))
            INTO :deptInfoEndLoc;
         CHECKERR ("VALUES2");
 
         /* Obtain ONLY the "Department Information"
            section by using SUBSTR                 */
         EXEC SQL VALUES(SUBSTR(:resume, :deptInfoBeginLoc,
            :deptInfoEndLoc - :deptInfoBeginLoc)) INTO :deptBuffer;
         CHECKERR ("VALUES3");
 
         /* Append the "Department Information" section 
            to the :buffer var.                  */
         EXEC SQL VALUES(:buffer || :deptBuffer) INTO :buffer;
         CHECKERR ("VALUES4");
      } /* endif */
   } while ( 1 );
 
   printf ("%s\n",buffer);
 
   EXEC SQL FREE LOCATOR :resume, :deptBuffer; (3)
   CHECKERR ("FREE LOCATOR");
 
   EXEC SQL CLOSE c1;
   CHECKERR ("CLOSE CURSOR");
 
   EXEC SQL CONNECT RESET;
   CHECKERR ("CONNECT RESET");
   return 0;
}
/* end of program : LOBLOC.SQC */

COBOL Sample: LOBLOC.SQB

       Identification Division.
       Program-ID. "lobloc".
 
       Data Division.
       Working-Storage Section.
 
           copy "sqlenv.cbl".
           copy "sql.cbl".
           copy "sqlca.cbl".
 
           EXEC SQL BEGIN DECLARE SECTION END-EXEC.                     (1)
       01 userid            pic x(8).
       01 passwd.
         49 passwd-length   pic s9(4) comp-5 value 0.
         49 passwd-name     pic x(18).
       01 empnum            pic x(6).
       01 di-begin-loc      pic s9(9) comp-5.
       01 di-end-loc        pic s9(9) comp-5.
       01 resume            USAGE IS SQL TYPE IS CLOB-LOCATOR.
       01 di-buffer         USAGE IS SQL TYPE IS CLOB-LOCATOR.
       01 lobind            pic s9(4) comp-5.
       01 buffer            USAGE IS SQL TYPE IS CLOB(1K).
           EXEC SQL END DECLARE SECTION END-EXEC.
 
       77 errloc          pic x(80).
 
       Procedure Division.
       Main Section.
           display "Sample COBOL program: LOBLOC".
 
      * Get database connection information.
           display "Enter your user id (default none): " 
                with no advancing.
           accept userid.
 
           if userid = spaces
             EXEC SQL CONNECT TO sample END-EXEC
           else
             display "Enter your password : " with no advancing
             accept passwd-name.
 
      * Passwords in a CONNECT statement must be entered in a VARCHAR
      * format with the length of the input string.
           inspect passwd-name tallying passwd-length for characters
              before initial " ".
 
           EXEC SQL CONNECT TO sample USER :userid USING :passwd
               END-EXEC.
           move "CONNECT TO" to errloc.
           call "checkerr" using SQLCA errloc.
 
      * Employee A10030 is not included in the following select, because
      * the lobeval program manipulates the record for A10030 so that it
      * it is not compatible with lobloc
 
           EXEC SQL DECLARE c1 CURSOR FOR
                    SELECT empno, resume FROM emp_resume
                    WHERE resume_format = 'ascii'
                    AND empno <> 'A00130' END-EXEC.
 
           EXEC SQL OPEN c1 END-EXEC.
           move "OPEN CURSOR" to errloc.
           call "checkerr" using SQLCA errloc.
 
           Move 0 to buffer-length. 
 
           perform Fetch-Loop thru End-Fetch-Loop
              until SQLCODE not equal 0.
 
      * display contents of the buffer.
           display buffer-data(1:buffer-length).
 
           EXEC SQL FREE LOCATOR :resume, :di-buffer END-EXEC.          (3)
           move "FREE LOCATOR" to errloc.
           call "checkerr" using SQLCA errloc.
 
           EXEC SQL CLOSE c1 END-EXEC.
           move "CLOSE CURSOR" to errloc.
           call "checkerr" using SQLCA errloc.
 
           EXEC SQL CONNECT RESET END-EXEC.
           move "CONNECT RESET" to errloc.
           call "checkerr" using SQLCA errloc.
       End-Main.
              go to End-Prog.
 
       Fetch-Loop Section.
           EXEC SQL FETCH c1 INTO :empnum, :resume :lobind              (2)
              END-EXEC.
 
           if SQLCODE not equal 0
              go to End-Fetch-Loop.
 
      * check to see if the host variable indicator returns NULL.
           if lobind less than 0 go to NULL-lob-indicated.
 
      * Value exists.  Evaluate the LOB locator.
      * Locate the beginning of "Department Information" section.
           EXEC SQL VALUES (POSSTR(:resume, 'Department Information'))
                    INTO :di-begin-loc END-EXEC.
           move "VALUES1" to errloc.
           call "checkerr" using SQLCA errloc.
 
      * Locate the beginning of "Education" section (end of Dept.Info)
           EXEC SQL VALUES (POSSTR(:resume, 'Education'))
                     INTO :di-end-loc END-EXEC.
           move "VALUES2" to errloc.
           call "checkerr" using SQLCA errloc.
 
           subtract di-begin-loc from di-end-loc.
 
      * Obtain ONLY the "Department Information" section by using SUBSTR
           EXEC SQL VALUES (SUBSTR(:resume, :di-begin-loc,
                    :di-end-loc))
                    INTO :di-buffer END-EXEC.
           move "VALUES3" to errloc.
           call "checkerr" using SQLCA errloc.
 
      * Append the "Department Information" section to the :buffer var
           EXEC SQL VALUES (:buffer || :di-buffer) INTO :buffer
                    END-EXEC.
           move "VALUES4" to errloc.
           call "checkerr" using SQLCA errloc.
 
           go to End-Fetch-Loop.
 
       NULL-lob-indicated.
           display "NULL LOB indicated".
 
       End-Fetch-Loop. exit.
 
       End-Prog.
                  stop run.

FORTRAN Sample: LOBLOC.SQF

      program lobloc
      implicit none
 
      include 'sqlenv.f'
      include 'sql.f'
      EXEC SQL INCLUDE SQLCA
 
      EXEC SQL BEGIN DECLARE SECTION
* (1)
        character*8               userid
        character*18              passwd
        character*6               empnum
        integer*4                 di_begin_loc
        integer*4                 di_end_loc
        SQL TYPE IS CLOB_LOCATOR  resume
        SQL TYPE IS CLOB_LOCATOR  di_buffer
        integer*2                 lobind
        SQL TYPE IS CLOB(1K)      buffer
      EXEC SQL END DECLARE SECTION
 
      character*80     errloc
 
      print *, 'Sample Fortran Program: LOBLOC'
 
      print *, 'Enter your user id (default none):'
      read 101, userid
101   format (a8)      
 
      if( userid(1:1) .eq. ' ' ) then
	EXEC SQL CONNECT TO sample 
      else
	print *, 'Enter your password :'
	read 101, passwd
 
	EXEC SQL CONNECT TO sample USER :userid USING :passwd
      end if
      errloc = 'CONNECT'
      call checkerr (sqlca, errloc, *999)
 
*     Employee A10030 is not included in the following select, because
*     the lobeval program manipulates the record for A10030 so that 
*     it is not compatible with lobloc 
 
      EXEC SQL DECLARE c1 CURSOR FOR
     +         SELECT empno, resume FROM emp_resume
     +         WHERE resume_format = 'ascii'
     +         AND empno <> 'A00130'
 
      EXEC SQL OPEN c1
      errloc = 'OPEN CURSOR'
      call checkerr (sqlca, errloc, *999)
 
 
   10 continue
         EXEC SQL FETCH c1 INTO :empnum, :resume :lobind
* (2)
         if (sqlcode .ne. 0) goto 100
         if (lobind .lt. 0) goto 50
 
*     The CLOB value exists.
*     Locate the beginning of the 
*     "Department Information" section
         EXEC SQL VALUES (POSSTR(:resume, 'Department Information'))
     +            INTO :di_begin_loc
         errloc = 'VALUES1'
         call checkerr (sqlca, errloc, *999)
 
*     Locate the beginning of the 
*     "Education" section (end of Dept.Info)
         EXEC SQL VALUES (POSSTR(:resume, 'Education'))
     +            INTO :di_end_loc
         errloc = 'VALUES2'
         call checkerr (sqlca, errloc, *999)
 
*     Obtain ONLY the "Department Information"
*     section by using SUBSTR
         EXEC SQL VALUES(SUBSTR(:resume, :di_begin_loc,
     +            :di_end_loc - :di_begin_loc)) INTO :di_buffer
         errloc = 'VALUES3'
         call checkerr (sqlca, errloc, *999)
 
*     Append the "Department Information" 
*     section to the :buffer variable
         EXEC SQL VALUES(:buffer || :di_buffer) INTO :buffer
         errloc = 'VALUES4'
         call checkerr (sqlca, errloc, *999)
 
      goto 10
 
   50 print *,'NULL LOB indicated'
      goto 10
 
  100 print *, buffer
 
      EXEC SQL FREE LOCATOR :resume, :di_buffer
* (3)
      errloc = 'FREE LOCATOR'
      call checkerr (sqlca, errloc, *999)
 
      EXEC SQL CLOSE c1
      errloc = 'CLOSE CURSOR'
      call checkerr (sqlca, errloc, *999)
 
      EXEC SQL CONNECT RESET
      errloc = 'CONNECT RESET'
      call checkerr (sqlca, errloc, *999)
 
  999 stop
      end


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]

[ DB2 List of Books | Search the DB2 Books ]