dataEvent_record_AfterDeleteRowWithConcurrentAccess

Function called after deleting a row with concurrent access.

Syntax

PUBLIC FUNCTION dataEvent_record_AfterDeleteRowWithConcurrentAccess( 
   errNo INTEGER, 
   errMsg STRING, 
   p_dataT0 record-type)
   RETURNS (INTEGER, STRING)

The function has these parameters:

  1. errNo. This is an SQLCA.SQLCODE error.
  2. errMsg. This is the SQLERRMESSAGE message.
  3. p_dataT0. This is a RECORD containing a row of data. It is defined according to the structure of the database table.
Returns values:
  1. An integer is returned with the SQLCA.SQLCODE error number. Codes are defined as constants in the libdbappSql and libdbappCore libraries. The errors that are relevant to this function are shown in Table 1.
    Table 1. SQLCA.SQLCODE
    Description Constant Value
    Success ERROR_SUCCESS 0
    Failure ERROR_FAILURE -1
    Concurrent access failure ERROR_CONCURRENT_ACCESS_FAILURE -2
    Concurrent access not found ERROR_CONCURRENT_ACCESS_NOTFOUND -3
    Cascade delete error ERROR_DELETE_CASCADE_ROW_USED -4
  2. A string is returned with the SQLERRMESSAGE error message.

Usage

When you select the After Delete Row With ConcurrentAccess property for the creation of the event, a function shell is created. Enter your code in the function.

Use this function to perform some operation, typically a SQL operation, on another table. For example, you could record details about the deleted row of data to a log table. This function is called after deleting a row in the database where access is concurrent and a table can be locked.

Example: AfterDeleteRowWithConcurrentAccess

This example uses the After Delete Row With ConcurrentAccess code event for the Account table in the OfficeStore demo.

In the example a row of data is written to a log table with a call to the function writeDataToLog.

The writeDataToLog function references two parameters:
  • The record that stores the row of data from the account table.
  • The operation type of the code event function in a reference to the relevant libdbappUI constant.
The parameters hold values written to the log table.
# AccountForm.4gl

-- import user-defined functions
IMPORT FGL myAccountFunc 

PUBLIC FUNCTION dataEvent_recAccount_AfterDeleteRowWithConcurrentAccess(errNo INTEGER, 
                                        errMsg STRING, p_dataT0 RECORD LIKE account.*)
    RETURNS (INTEGER, STRING)

    CALL libdbappCore.log(C_LOG_INFO, "dataEvent_recAccount_AfterDeleteRowWithConcurrentAccess (Row scope) is raised")
    CALL myAccountFunc.writeDataToLog(p_dataT0,libdbappUI.C_ACTION_DELETE) RETURNING errNo
    IF errNo = libdbappCore.ERROR_FAILURE THEN
       LET errMsg = " - AfterDeleteRowWithConcurrentAccess failed to insert log " 
    END IF
    CALL libdbappCore.log(C_LOG_INFO, "dataEvent_recAccount_AfterDeleteRowWithConcurrentAccess (Row scope) is exited")

    RETURN errNo, errMsg
END FUNCTION

For more information on the libdbappCore.log() function, go to DBAPPDEBUG and the debug level API.

writeDataToLog

In this section there is an example of the function writeDataToLog called to write data to a log table.

It is assumed that you have created the log table before saving the row to it. The log table in the example has the following schema:
  • an "id" field that is auto incremented
  • a "date" timestamp field to record the date and time of the operation
  • a "type" field to record the operation (Update/Insert/Delete)
  • a "data" field to record a copy of all field values from the account table

All functions that you would reuse across forms and applications would reside in a module you create. To use these functions in your project, you would import your module into the entity module (for example, AccountForm.4gl) using the IMPORT FGL statement.

# MyAccountFunc.4gl

IMPORT FGL libdbappCore

FUNCTION writeDataToLog(dataRec RECORD LIKE account.*, opType INTEGER) 
  RETURNS (INTEGER)
  
  DEFINE errNo INTEGER
  DEFINE recLog RECORD LIKE log.*
  DEFINE t TEXT   
  
  LOCATE t IN MEMORY  
  LET recLog.id = NULL
  LET recLog.date = CURRENT  
  LET recLog.type = opType
  LET t = SFMT("id = %1 email = %2 firstname = %3 lastname = %4  acstatus = %5  addr1 = %6  
               addr2= %7 city = %8  state = %9 zip = %10 country = %11 phone = %12",
               dataRec.userid, dataRec.email, dataRec.firstname, dataRec.lastname,
               dataRec.acstatus, dataRec.addr1, dataRec.addr2, dataRec.city, dataRec.state,
               dataRec.zip, dataRec.country, dataRec.phone)  
  LET recLog.data = t
  TRY
     INSERT INTO log VALUES (recLog.*)
  CATCH
     DISPLAY "SQL ERROR: ", sqlca.sqlcode
     LET errNo = libdbappCore.ERROR_FAILURE
  END TRY
  RETURN errNo
 
END FUNCTION