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