4. Embedded QUEL for Fortran : Runtime Error Processing : Programming for Error Message Output
 
Share this page                  
Programming for Error Message Output
By default, all Ingres and forms system errors are returned to the EQUEL program, and default error messages are printed on the standard output device. As discussed in the QUEL Reference Guide and the Forms-based Application Development Tools User Guide, you can also detect the occurrences of errors by means of the program using the inquire_ingres and inquire_frs statements. (Use inquire_frs for checking errors after forms statements. Use inquire_ingres for all other EQUEL statements.)
This section discusses an additional technique that enables your program not only to detect the occurrences of errors, but also to suppress the printing of default Ingres error messages if you choose. The inquire statements detect errors but do not suppress the default messages.
This alternate technique entails creating an error-handling function in your program, and passing its address to the Ingres runtime routines. This makes Ingres automatically invoke your error handler whenever either an Ingres or a forms-system error occurs. You must declare your program error handler as follows:
integer function funcname (errorno)
integer errorno
...
end
You must pass this function to the EQUEL routine IIseterr( ) for runtime bookkeeping using the Fortran statements:
external funcname
integer funcname
IIseterr(funcname);
This forces all runtime Ingres errors through your function, passing the Ingres error number as an argument. If you choose to handle the error locally and suppress Ingres error message printing the function should return 0; otherwise the function should return the Ingres error number received.
Avoid issuing any EQUEL statements in a user-written error handler defined to IIseterr, except for informative messages, such as message, prompt, sleep and clear screen, and messages that close down an application, such as endforms and exit.
The example below demonstrates a typical use of an error function to warn users of access to protected tables. It also passes through all other errors for default treatment.
    program errhnd
##  declare

    external locerr
    integer locerr

    . . .

##  ingres dbname
    IIseterr( locerr )

    . . .

##  exit
    end

    integer function locerr(err_no) 
    parameter (TBLPRO = 5003)
    integer err_no

    if (err_no .eq. TBLPRO) then 
    print *, 'You are not authorized for this/ operation.'
    locerr = 0 
    else 
        locerr = err_no 
    endif 
    return
    end
A more practical example would be a handler to catch deadlock errors. For deadlock, a reasonable handling technique in most applications is to suppress the normal error message and simply restart the transaction.
The following EQUEL program executes a Multi-Query Transaction and handles Ingres errors, including restarting the transaction on deadlock.
This example uses a program-defined error handler, rather than the inquire_ingres statement, to detect Ingres errors. This technique allows the normal Ingres error message to be suppressed in the case of deadlock, and the transaction to restart automatically without the user's knowledge.
UNIX:
##    program mqterr
##    declare
      parameter (NOERR = 0) 
      external errprc, tdone 
      integer errprc, ingerr 
      logical tdone
      common /errors/ ingerr
##    ingres dbname
C Set up test data
##    create item (name=c10, number=i4) 
      call IIseterr( errprc ) 
      ingerr = NOERR
C     The following do-while loop will iterate until the
C transaction completes or fails: it restarts the
C transaction on deadlock.
10    continue
      if ( .not. tdone() ) then
            goto 10
##    end
C The function 'tdone' contains the multi-query
C transaction. The transaction consists of an APPEND, 
C a REPLACE and a DELETE of a single row.
##    logical function tdone
##    declare
      external dlock
      logical dlock
##    begin transaction
##    append To item (name='Barbara', number=38)
      if (dlock()) then 
           tdone = .false. 
           return 
      endif
##    replace item (number=39) where item.name='Barbara' 
      if (dlock()) then 
           tdone = .false. 
           return
      endif
##    delete item where item.number=38 
      if (dlock()) then 
           tdone = .false. 
           return
      endif
##    end transaction
##    destroy item
##    exit
      tdone = .true.
##    end
C The following routine differentiates deadlock from 
C other errors. If the Ingres error is deadlock,
C the DBMS will automatically
C ABORT an existing MQT. If the error is not deadlock, 
C this routine aborts the transaction and the program.

##    logical function dlock
##    declare 
      parameter (EDLOCK = 4700) 
      parameter (NOERR = 0) 
      integer ingerr 
      common /errors/ ingerr

      if (ingerr .gt. 0) then 
          if (ingerr .eq. EDLOCK) then 
              ingerr = NOERR 
              dlock = .true. 
              return   
      else 
              print *, 'Aborting -- Error #', ingerr
##            abort
##            exit 
              stop 
          endif 
      endif

      dlock = .false.
      return
##    end
C The following is a user-defined error-handling routine. 
C Returns 0 if the Ingres error is deadlock to
C prevent the runtime system from printing an error
C message.

      integer function errprc (err_no)
      parameter (EDLOCK = 4700)
      integer err_no
      integer ingerr
      common /errors/ ingerr
      ingerr = err_no
      if (err_no .eq. EDLOCK) then 
          errprc = 0
      else
          errprc = err_no
      endif
      return
      end  

VMS:
##    program mqterr 
##    declare 
      parameter (ERR_NOERROR = 0) 
      external errproc, transdone 
      integer errproc, ingerr 
      logical transdone 
      common /errors/ ingerr

##    ingres dbname

C Set up test data

##    create item (name=c10, number=i4) 
      call IIseterr( errproc )
      ingerr = ERR_NOERROR

C The following do-while loop will iterate until the 
C transaction completes or fails: it restarts the
C transaction on deadlock.

      do while ( .not. transdone() ) 
      end do 
##    end
C The function 'transdone' contains the multi-query 
C transaction. The transaction consists of an APPEND, 
C a REPLACE and a DELETE of a single row.

##    logical function transdone 
##    declare

      external deadlock 
      logical deadlock

##    begin transaction
##    append to item (NAME='Barbara', number=38) 
      if (deadlock() .eq. .true.) then 
          transdone = .false. 
          return 
      endif

##    append To (number=39) WHERE item.name='Barbara' 
      if (deadlock() .eq. .true.) then 
          transdone = .false. 
          return 
      endif

##    delete item Where item.number=38 
      if (deadlock() .eq. .true.) then 
          transdone = .false. 
          return 
      endif

##    end transaction
##    destory item 
##    exit 
      transdone = .true. 
##    end

C The following routine differentiates deadlock from
C other errors. If the Ingres error is deadlock,
C the DBMS will automatically ABORT an existing MQT. 
C If the error is not deadlock, this routine aborts 
C the transaction and the program.
##    logical function deadlock 
##    declare 
      parameter (ERR_ DEADLOCK = 4700) 
      parameter (ERR_NOERROR = 0) 
      integer ingerr 
      common /errors/ ingerr

      if (ingerr .gt. 0) then 
          if (ingerr .eq. ERR_DEADLOCK) then 
              ingerr = ERR_NOERROR
              deadlock = .true. 
              return 
          else 
              print *, 'Aborting -- Error #', ingerr 
##              abort
##              exit 
              stop 
          endif 
      endif

      deadlock = .false. 
      return 
##    end
C The following is a user-defined error-handling routine.
C Returns 0 if the Ingres error is deadlock to
C prevent the runtime system from printing an error
C message.

    integer function errproc (errorno) 
    parameter (ERR_DEADLOCK = 4700) 
    integer errorno 
    integer ingerr 
    common /errors/ ingerr

    ingerr = errorno
    if (errorno .eq. ERR_DEADLOCK) then
        errproc = 0
    else
        errproc = errorno
    endif
    return
    end 

Windows:
##    program mqterr 
##    declare 
      parameter (ERR_NOERROR = 0) 
      external errproc, transdone 
      integer errproc, ingerr 
      logical transdone 
      common /errors/ ingerr

##    ingres dbname

C Set up test data

##    create item (name=c10, number=i4) 
      call IIseterr( errproc )
      ingerr = ERR_NOERROR

C The following do-while loop will iterate until the 
C transaction completes or fails: it restarts the
C transaction on deadlock.

      do while ( .not. transdone() ) 
      end do 
##    end
C The function 'transdone' contains the multi-query 
C transaction. The transaction consists of an APPEND, 
C a REPLACE and a DELETE of a single row.

##    logical function transdone 
##    declare

      external deadlock 
      logical deadlock

##    begin transaction
##    append to item (NAME='Barbara', number=38) 
      if (deadlock() .eq. .true.) then 
          transdone = .false. 
          return 
      endif

##    append to item (number=39) WHERE item.name='Barbara' 
      if (deadlock() .eq. .true.) then 
          transdone = .false. 
          return 
      endif

##    delete item Where item.number=38 
      if (deadlock() .eq. .true.) then 
          transdone = .false. 
          return 
      endif

##    end transaction
##    destroy item 
##    exit 
      transdone = .true. 
##    end
C The following routine differentiates deadlock from
C other errors. If the Ingres error is deadlock,
C the DBMS will automatically ABORT an existing MQT. 
C If the error is not deadlock, this routine aborts 
C the transaction and the program.

##    logical function deadlock 
##    declare 
      parameter (ERR_ DEADLOCK = 4700) 
      parameter (ERR_NOERROR = 0) 
      integer ingerr 
      common /errors/ ingerr

      if (ingerr .gt. 0) then 
          if (ingerr .eq. ERR_DEADLOCK) then 
              ingerr = ERR_NOERROR
              deadlock = .true. 
              return 
          else 
              print *, 'Aborting -- Error #', ingerr 
##              abort
##              exit 
              stop 
          endif 
      endif

      deadlock = .false. 
      return 
##    end
C The following is a user-defined error-handling routine.
C Returns 0 if the Ingres error is deadlock to
C prevent the runtime system from printing an error
C message.

      integer function errproc (errorno) 
      parameter (ERR_DEADLOCK = 4700) 
      integer errorno 
      integer ingerr 
      common /errors/ ingerr

      ingerr = errorno
      if (errorno .eq. ERR_DEADLOCK) then
        errproc = 0
      else
        errproc = errorno
      endif
      return
      end