Skip to content

6. 3GL Trigger

When data is being written to or read from Thoroughbred files, the 3GL Trigger allows you to modify that data transparent to the running application. Data can be normalized and file integrity can be maintained, without changing your current 3GL code.

When an I/O operation is performed and the data file is contained in a trigger list, that I/O is intercepted and passed to the trigger code before being returned to the application or being written to the disk.

The LOAD directive activates the given Trigger Method. The DROP directive can then deactivate the given Trigger Method.

LOAD trigger-definition-list, OPT="IOT"
DROP trigger-definition-list, OPT="IOT"

Where:

trigger-definition-list is the trigger file list to activate or deactivate.

OPT=“IOT” is the keyword that indicates to Basic that this is a Trigger Definition List.

This causes a lookup in OOLIOT0 to match the trigger-definition-list. On each entry in the data-file-list for that trigger-definition-list is a Data-File/Trigger-Method pair.

Besides LOAD, you can also activate a trigger using the IPLINPUT file.

PRM LOADTRIGGER=trigger-definition-list

To set up the trigger, you must first create a trigger definition list, and then create a data file list for that definition.

Below is the Format of the Trigger Definition List Files.

Name: OOFIOT1 , Trigger Definition List Files
Fld Key --- Position ----
Data Element Length Sep HELP Ind
1 TRIGGER-DEF-NAME.... 8 - TNAME Y

The name of this trigger definition list. This is the name which ties back to the trigger definition list header and is used in the LOAD “trigger-definition-list”, OPT=“IOT” and DROP “ trigger-definition-list“, OPT=“IOT”.

2 TRIGGER-DESC........ 40 - TDESC

Provides a descriptive definition for this trigger definition list.

3 CREATED-DATE........ 11.4 - TCDATE

The date on which this trigger definition list was created is automatically created.

Perform screen maintenance on OOLIOT1 and define the trigger-definition-list using normal Thoroughbred procedure (2-character library name and up to 6 characters for the file name).

You then can use up to 40 characters to describe your trigger definition.

Example

07/03/03 Trigger Definition List Files 1
Trigger
Def Name Description Created Date/Time
HRTALL All Files 05/12/03 13:19:29
HRTUSERS Users Triggers 06/20/03 13:24:58

Once you have created your Trigger Definition List you then must set up the data file list to be accessed by the Trigger Method during I/O to the data file.

Below is the format of the data file list.

Name: OOFIOT0 , I/O Trigger CONNECT spec
Fld Key
Data Element Length Sep HELP Ind
=========================================================
1 TRIGGER-DEF-NAME.... 8 - TNAME Y

The name of this trigger definition list. This is the name which ties back to the trigger definition list header and is used in the LOAD “ trigger-definition-list “, OPT=“IOT” and DROP “ trigger-definition-list“, OPT=“IOT”.

2 DATA-FILE-NAME...... 14 - TFILE Y

The name of each Data file to be included in this trigger definition list.

3 LINK-NAME........... 8 - TLINK -

Dictionary-IV Link Name that defines the FORMAT and any SORTS, which may exist for this file.

4 FORMAT-NAME......... 8 - TFMT -

The Dictionary-IV Format Name that defines the data for the records in this file.

5 APPLICATION-TRIGGER. 8 - TTRIG -

The Basic method that will be invoked by OOIO on any I/O to the data file.

6 IO-OPTION........... 1 - TIOOPT -

Reserved for future use.

Example:

07/03/03 Data File List 1
Trigger Data Link Format Applic I/O
Def Name File Name Name Name Trigger Option
HRTALL ACCCHG HRL0123 HRF0123 HRTFTRIG N
HRTALL ACCDEL HRL0124 HRF0124 HRTFTRIG N
HRTALL ACCTA HRL0122 HRF0122 HRTFTRIG N
HRTALL ACFILE HRL0313 HRF0313 HRTFTRIG N

When an I/O directive to a file is executed and that file is contained in a trigger, Basic activates the “OOIO” method. Basic provides all information necessary for “OOIO” to determine which trigger method should be executed for the I/O action. This information is passed from Basic to OOIO in OOIO$[0] through OOIO$[7]. The record data passed into the trigger in entry OOIO$[5] is raw data. OOIO$[5] will have field separators and lengths just as if the record had been read into a string with the READ RECORD() directive. The data passed back to Basic in OOIO$[7] must have the delimiters in place so that the variable list for the READ directive can be filled. Please refer to the DTR() and RTD() functions in the Basic Language Reference for information on processing data in this format.

If an error condition occurs in OOIO, error processing can be controlled by setting the following variables prior to exiting:

OOIO$[0]:
"X" or "ERROR nnn".

When OOIO$[0] is set to “X” Basic assumes the trigger has done whatever is needed to complete the I/O directive. The interrupted program will continue at the next statement.

When OOIO$[0] is set to “ERROR nnn” the interrupted program will receive an ERR=nnn.

CGV(“OOIO_ERROR”):
The Common Global Variable "OOIO_ERROR" can be used to pass back additional message text or a CONNECT METHOD or RETURN directive including parameter values.

If OOIO is invoked from UPDATE, CONNECT SCREEN or CONNECT VIEW and OOIO$[0] is set to “ERROR 99”, the CONNECT METHOD or RETURN directive defined in “OOIO_ERROR” will be processed prior to returning control back to your application. If “OOIO_ERROR” is not set, normal error processing will be executed based on the value of ERR. In the case of the UPDATE directive, standard UPDATE ERROR PROCESSING IS procedure_name is always executed based on the value of ERR when control is returned to the Script.

The following example assumes an OPENworkshop environment. When OOIO exits, ERR will be set to 99 and the Method named TRIGERROR will be executed. The parameter “OutOfStock” is passed to the Method TRIGERROR.

LET O$=CGV("OOIO_ERROR","CONNECT METHOD TRIGERROR, OutOfStock");
LET OOIO$[0]="ERROR 99";
EXIT

The following example assumes an OPENworkshop environment. When OOIO exits, ERR will be set to 99 and the Dictionary-IV Help definition named HELP01 will be displayed.

LET O$=CGV("OOIO_ERROR","ERROR HELP01; EXIT");
LET OOIO$[0]="ERROR 99";
EXIT

The following example assumes a 3GL environment. When OOIO exits, ERR will be set to 90 and “OOIO_ERROR” will contain the message text “OutOfStock”. The application code can then test for the case where ERR=90 and process the appropriate error logic.

LET O$=CGV("OOIO_ERROR","OutOfStock");
LET OOIO$[0]="ERROR 9O";
EXIT

Important: An example OOIO trigger is supplied in the Thoroughbred OO0 source library. The OO0 Source-IV library is a Thoroughbred library, it will be replaced if an upgrade is done. Never maintain your triggers in the OO0 library. To use OO0.OOIO as a template for your triggers you must first copy it to one of your application Source-IV libraries.

METHOD OOIO$[ALL], OOIO[ALL]
OOIO$
[0] - Return values for basic.
[1](1,1) - Basic directive code.
(2,2) - Channel number for I/O operation.
(4,14)- Basic file name associated with the channel.
(18,1)- $02$ = IND= was specified
$01$ = KEY= was specified
$00$ = neither IND= or KEY= were specified.
(19,1)- $01$ = DOM= was specified on a WRITE.
(20,1)- $01$ = a record was not found for a READ.
[2] - Basic file name table created by Load(s). Comes from file
OOIOT0 and is defined by the link OOLIOT0 and the format
OOFIOT0. This table is created and maintained by basic as
LOAD trigger-class,OPT="IOT" and
DROP trigger-class,OPT="IOT" directives are done.
1,14 - Basic File name.
15,8 - Dict Link name.
23,8 - Dict Format name.
31,8 - Basic File Trigger name.
39,1 - I/O Type: R-Read W-Write B-Both
40,x - etc.
[3] - Channel number + Basic file name table entry address table.
This table is maintained as basic files are opened closed.
1,2 - Channel number.
3,2 - Entry address within Basic File name table.
[4] - Old record key when write.
Current record key when read.
[5] - Old record data when write is being done.
Current record data when read.
[6] - New record key when write.
[7] - New record data when write.
[8-N] These can be used by the trigger developer to maintain information
needed by subsequent invocations, or to retain information to
optimize access.
OOIO[ALL] Currently not used.
PROCEDURE
FUNC$= OOIO$[1], ! Set: basic function.
DIRF$= FUNC$(1,1), ! dir/func code.
CHN$ = FUNC$(2,2), ! channel number (str) .
CHN = DEC(CHN$), ! channel number (num) .
FILE$= FUNC$(4,14), ! dir/func file name.
W$ = OOIO$[3], ! channel/file table.
W = POS(CHN$=W$,4); ! Find channel in file table.
IF W=0 ! If channel not opened
EXIT ! Get out.
FI; ! endif
I = DEC($00$+W$(W+2,2)), ! Set: trigger table entry adr
TE$ = OOIO$[2](I,39); ! trigger info entry.
DF$ = TE$(1,14), ! data file name.
LNK$ = TE$(15,8), ! link name.
FMT$ = TE$(23,8), ! format name.
FMI$ = "#"+FMT$, ! (usable form)
TRG$ = TE$(31,8), ! trigger name.
IOT$ = TE$(39,1), ! I/O type.
OOIO$[0]=""; ! Clear return value.
CALL TRG$,OOIO$[ALL],OOIO[ALL],DIRF$, ! Go process
FILE$,DF$,LNK$,FMT$,IOT$,CHN$,CHN;! I/O
IF OOIO$[0]="" ! If no return code
OOIO$[0]="." ! Set ok return.
FI; ! endif
EXIT ! Get out
METHOD IOT$[ALL],IOT[ALL],DIRF$,FILE$,DF$,LNK$,FMT$,IOT$,CHN$,CHN
IOT$
[0] - Return values for basic.
[1](1,1) - Basic directive code.
(2,2) - Channel number for I/O operation.
(4,14)- Basic file name associated with the channel.
(18,1)- $02$ = IND= was specified
$01$ = KEY= was specified
$00$ = neither IND= or KEY= were specified.
(19,1)- $01$ = DOM= was specified on a WRITE.
(20,1)- $01$ = a record was not found for a READ.
[2] - Basic file name table created by Load(s). Comes from file
OOIOT0 and is defined by the link OOLIOT0 and the format
OOFIOT0. This table is created and maintained by basic as
LOAD trigger-class,OPT="IOT" and
DROP trigger-class,OPT="IOT" directives are done.
1,14 - Basic File name.
15,8 - Dict Link name.
23,8 - Dict Format name.
31,8 - Basic File Trigger name.
39,1 - I/O Type: R-Read W-Write B-Both
40,x - etc.
[3] - Channel number + Basic file name table entry address table.
This table is maintained as basic files are opened closed.
1,2 - Channel number.
3,2 - Entry address within Basic File name table.
[4] - Old record key when write.
Current record key when read.
[5] - Old record data when write is being done.
Current record data when read.
[6] - New record key when write.
[7] - New record data when write.
[8-N] These can be used by the trigger developer to maintain information
needed by subsequent invocations, or to retain information to
optimize access.
IOT[ALL] Currently not used.
DIRF$ = One byte directive/function code.
(Corresponds to the Basic Atom for that Directive)
FILE$ = File name.
LNK$ = Link name.
FMT$ = Format name.
IOT$ = IO Trigger type.
CHN$ = Two byte binary channel number.
CHN = Numeric channel number.
PROCEDURE
IOTT$= $20$+ ! OPEN.
$21$+ ! CLOSE.
$25$+ ! PRINT.
$26$+ ! WRITE.
$27$+ ! REMOVE
$29$+ ! INPUT.
$2A$+ ! READ.
$2B$+ ! EXTRACT.
$2C$+ ! FIND.
$4A$+ ! INPUT RECORD.
$4B$+ ! READ RECORD.
$4C$+ ! EXTRACT RECORD.
$4D$+ ! FIND RECORD.
$4E$+ ! PRINT RECORD.
$4F$+ ! WRITE RECORD.
$54$+ ! READ PREVIOUS.
$55$+ ! READ PREVIOUS RECORD.
$56$+ ! EXTRACT PREVIOUS.
$57$; ! EXTRACT PREVIOUS RECORD.
ON POS(DIRF$=IOTT$) GOSUB ! Go process I/O directive.
BADDIR, ! Bad directive/function.
XOPEN, ! OPEN.
XCLOSE, ! CLOSE.
XPRINT, ! PRINT.
XWRITE, ! WRITE.
XREMOVE, ! REMOVE
XINPUT, ! INPUT.
XREAD, ! READ.
XEXTRACT, ! EXTRACT.
XFIND, ! FIND.
XINPUTRECORD, ! INPUTRECORD.
XREADRECORD, ! READRECORD.
XEXTRACTRECORD, ! EXTRACTRECORD.
XFINDRECORD, ! FINDRECORD.
XPRINTRECORD, ! PRINTRECORD.
XWRITERECORD, ! WRITERECORD.
XREADPREV, ! READPREV.
XREADPREVRECORD, ! READPREVRECORD.
XEXTRACTPREV, ! EXTRACTPREV.
XEXTRACTPREVRECORD, ! EXTRACTPREVRECORD.
BADDIR; ! Bad directive/function.
EXIT
BADDIR ! PROCESS BAD DIRECTIVE.
PRINT "Bad Directive: $"+HTA(DIRF$),"$",; ! Show status.
INPUT *; ! Wait for input.
RETURN ! Return.
XOPEN
! Processing
RETURN
XCLOSE
! Processing
RETURN
XPRINT
! Processing
RETURN
XWRITE
! Processing
RETURN
XREMOVE
! Processing
RETURN
XINPUT
! Processing
RETURN
XREAD
! Processing
RETURN
XEXTRACT
GOSUB XREAD;
RETURN
XFIND
GOSUB XREAD;
RETURN
XINPUTRECORD
! Processing
RETURN
XREADRECORD
GOSUB XREAD;
RETURN
XEXTRACTRECORD
GOSUB XREAD;
RETURN
XFINDRECORD
GOSUB XREAD;
RETURN
XPRINTRECORD
! Processing
RETURN
XWRITERECORD
GOSUB XWRITE;
RETURN
XREADPREV
GOSUB XREAD;
RETURN
XREADPREVRECORD
GOSUB XREAD;
RETURN
XEXTRACTPREV
GOSUB XREAD;
RETURN
XEXTRACTPREVRECORD
GOSUB XREAD;
RETURN

From the Thoroughbred Basic Developer Guide, version 8.9.1. Open this page in the PDF