8 User Exit Functions

This chapter explains how to use user exits to extend and customize the functionality of Oracle GoldenGate for HP NonStop on Guardian.

This chapter includes:

User exits extend and customize the functionality of the Extract and Replicat processing by calling COBOL, TAL or C routines from the Extract or Replicat parameter files. At different points during processing you can invoke custom COBOL, TAL or C routines to perform specialized functions.

Reference Guide for HP NonStop (Guardian) supplies:

Two example user exits are supplied with the installation code: DEMOXCOB (written in COBOL) and DEMOXC (written in C). You can use these exits as a sample to help plan your own user exit routines. Two blank user exit templates are also included: USEREXC for C and USEREXT for TAL. You can use these to start coding your routines. There is no sample for TAL and no template for COBOL.

Note:

User exits may be used for many kinds of routines; however, you should avoid controlling transaction commits with custom user exit logic. This could interfere with Oracle GoldenGate checkpoint processing, which facilitates troubleshooting and protects you in case of system failure.

Function summary

Function parameters accept different events and information from the Extract or Replicat program, pass the information to the appropriate routine for processing and return a response and information to the caller.

Routine Description
EXIT_CALL_RESULT

Set by the user exit routines and tells the caller how to respond when each exit call completes.

EXIT_CALL_TYPE

Indicates the processing point of the caller and determines the type of processing to perform.

EXIT_PARAMS

Supplies information about the associated EXIT_REC_BUF when the call type is PROCESS_RECORD or DISCARD_RECORD. The exit routines can alter certain EXIT_PARAMS to change how the caller processes returned records.

EXIT_REC_BUF

Contains the record about to be processed by Extract or Replicat. EXIT_REC_BUF is supplied when the call type is PROCESS_RECORD or DISCARD_RECORD. Exit routines can change the contents of this buffer, for example, to perform custom mapping functions.

When changing the contents of EXIT_REC_BUF, change the SOURCE_FILE (for Extract processing only) and RECORD_LEN parameters appropriately so that external processes can identify the record.


EXIT_CALL_RESULT

EXIT_CALL_RESULT is set by the user exit routines and tells the caller how to respond when each exit call completes. The following results can be specified by the operator's routines.

Result Description
EXIT_ABEND_VAL

Instructs the caller to ABEND immediately.

EXIT_IGNORE_VAL

Reject records for further processing. IGNORE is appropriate when the exit performs all the desired processing on a record and there is no desire to output or replicate it.

EXIT_OK_VAL

If the routine does nothing to respond to an event, OK is assumed. If the call specified PROCESS-RECORD or DISCARD-RECORD and OK is returned, the caller processes the record buffer returned by the user exit and uses the parameters set by the exit (see the EXIT-REC-BUF parameter for details).

EXIT_STOP_VAL

Instructs the caller to STOP immediately. STOP or ABEND may be appropriate when an error condition occurs in your program, such as a file error.


EXIT_CALL_TYPE

EXIT_CALL_TYPE indicates the processing point of the caller and determines the type of processing to perform. Extract and Replicat use the following types of calls.

Call Description
EXIT_CALL_BEGIN_TRANS

In Extract, invoked just before the output of the first record in a transaction. In Replicat, invoked just before the start of a replicated transaction.

EXIT_CALL_DISCARD_RECORD

Called when a record is discarded. Records can be discarded for several reasons, such as the changed record is out-of-sync with the current version of an SQL table.

When DISCARD-RECORD is specified, the associated buffer is passed and custom discard processing can be specified.

EXIT_CALL_END_TRANS

In Extract and Replicat, invoked just after the last record in a transaction is processed.

EXIT_CALL_FILE_CLOSE

Invoked by a direct read Extract when it closes the current data file.

EXIT_CALL_PROCESS_RECORD

In Extract, invoked before a record buffer is output to a trail or file. In Replicat, invoked just before a Replicat operation is performed. This call is the basis of most user exit processing.

When a PROCESS_RECORD call is invoked, the record buffer and parameters describing the record are supplied to the user exit. You can map, transform, clean or perform virtually any other operation with the record. You can return a status indicating whether the caller should process or ignore the record.

EXIT_CALL_START

Invoked at the start of processing. The user exit can perform initialization work, such as opening files, initializing variables, and so forth.

EXIT_CALL_STOP

Invoked before the caller stops or ends abnormally. The user exit can perform completion work, such as closing files or outputting totals.


EXIT_PARAMS

EXIT_PARAMS supply information about the associated EXIT-REC-BUF when the call type is PROCESS_RECORD or DISCARD_RECORD. The exit routines can alter certain EXIT_PARAMS to change how the caller processes returned records. The EXIT_PARAMS structure includes the following:

Exit Parameter Description
AUDIT_TIMESTAMP

Provides the Julian, GMT timestamp of the audit block in which the record was found. This timestamp approximates the time of the original database operation.

BEFORE_AFTER_IND

For update records, determines whether the record is a before-image (B) or after-image (A). When extracted, before-images precede after-images within the same update. Inserts are after-images, and deletes are before-images.

ERR_INFO

This information is supplied with a discarded record to indicate the reason for the discard. The Oracle GoldenGate for Mainframe error number (ERR_NUM) is passed, along with a possible file or SQL error and error text.

FUNCTION_PARAM

Lets you pass a parameter to the exit. This parameter is set up in the Extract or Replicat parameter file as part of the FILE or MAP parameter.

The default size of EXIT_PARAMS is 256 bytes. If the string supplied with the EXITPARAM parameter is shorter, it will be a NULL terminated string. Use the GET_EXITPARAM_VALUE function to access data over that length.

MORE_RECS_IND

Set by the user on return from an exit. For database records, determines whether Extract or Replicat processes the record again.

This allows the exit program, for example, to output many records per record processed by Extract, a common function when converting Enscribe to SQL (data normalization). To request the same record again, set MORE_RECS_IND to Y.

RECORD_LEN

Provides the length of the record buffer passed. Change RECORD_LEN if the Extract SOURCE_FILE parameter is altered to reflect the new length of the buffer.

RECORD_TYPE

Identifies the record as SQL or ENS for Enscribe.

SOURCE_FILE

Identifies the type of record passed to the exit during Extract processing. When custom mapping is performed, it is sometimes appropriate for the exit routines to change this field. For example, if the exit uses the record buffer from $DATA5.FLS.ACCTFL and changes it to the format of $DATA6.TABS.ACCTTAB, your exit should change SOURCE_FILE to $DATA6.TABS.ACCTTAB.

UPDATE_TYPE

Determines the type of operation associated with the record buffer. Operations types are:

  • INSERT_IO

    The record is an insert to the source file.

  • DELETE_IO

    The record is a delete, and the buffer is the image of the record being deleted.

  • UPDATE_IO

    The record is an update to the source file. The full after update image is supplied.

  • UPDATE_COMP_ENSCRIBE

    The record is a compressed Enscribe update. Only primary key fields and changed fields are supplied. Routines are supplied to overlay each field in its corresponding uncompressed location.

  • UPDATE_COMP_PK_SQL_VAL

    The record is a primary key update. It contains three parts in the data portion of the record: 1) the before-image key length, 2) the before-image key values in field comp format, and 3) the after-image in field comp format.

  • UPDATE_COMP_SQL

    The record is a compressed SQL update. Only primary key fields and changed fields are supplied. Routines are supplied to overlay each field in its corresponding uncompressed location.


EXIT_REC_BUF

EXIT_REC_BUF contains the record about to be processed and is supplied when the call type is PROCESS_RECORD or DISCARD_RECORD. Exit routines can change the contents of this buffer, for example, to perform custom mapping functions. When changing the contents of EXIT_REC_BUF, change the SOURCE_FILE (for Extract only) and RECORD_LEN parameters appropriately so that external processes can identify the record.

Calling environment functions

Environment functions are routines the exit can call to retrieve context information from Extract or Replicat. These functions are summarized below and each of the functions is explained in more detail in the remainder of the chapter. Syntax examples are included for C, TAL, and COBOL.

Note:

Each COBOL syntax section documents the ?CONSULT =EXTRACT (or =REPLICAT) compiler directive. Actually, this directive is declared only once no matter how many functions are called in the user exit. Make sure it points to the correct object type, which will be Extract for an Extract user exit, Replicat for a TNS Replicat user exit or REPR for native relinkable Replicat user exit.

Function Summary

Function Description
COMPRESS_RECORD | COMPRESS_RECORD2

Use when some of a target table's columns are present after mapping. Typically, use in conjunction with DECOMPRESS_RECORD.

DECOMPRESS_RECORD | DECOMPRESS_RECORD2

Makes compressed SQL updates easier to process and map.

FETCH_CURRENT_RECORD

Obtains the current Enscribe key-sequenced or entry-sequenced target record.

FETCH_CURRENT_RECORD_WITH_LOCK

Obtains the current Enscribe key-sequenced or entry-sequenced target record while locking the record for update.

GET_ALTKEY_INFO

Returns information on a file's alternate key.

GET_COLUMN_INDEX

Given a column name, returns the column index number.

GET_COLUMN_NAME

Given a column index, returns the column's name.

GET_ENV_VALUE

Returns the source or target file name in internal or external format.

GET_EXTRBA

Gets the current position in the extract trail.

GET_EXTSEQNO

Gets the sequence number of the current extract trail.

DATEDIFF

Retrieves the source or target file name.

GET_FOPEN_NUM

Gets the open number of the current file.

GET_NUM_COLUMNS

Returns the number of columns.

GET_RECORD | GET_RECORD2

Use for custom field conversions that may not be handled by Extract or Replicat.

GET_RECORD_LENGTH | GET_RECORD_LENGTH2

Retrieves the length of the target record.

GET_SYSKEY_LENGTH

Retrieves the SYSKEY length for the current record.

GET_TRANSACTION_IND

Supplies a data records position in a transaction, such as first, last, or middle.

GET_USER_TOKEN_VALUE

Allows user to retrieve the value of a user token.

GGS_EMSMESSAGE

Allows a user exit to write an EMS message.

GGS_REPORTMESSAGE

Allows a user exit to write to the report file.

SET_TARGET_RECORD2

Sets the values of a modified record.

SET_TARGET_RECORD_LENGTH2

Sets the length of a modified record.


The function RESULT

The RESULT value returned by each function indicates whether or not the function was successful. Possible values are listed below, but different functions may be limited in those they will use.

Return value Description
EXIT_ENV_SOURCE_FILE

Indicates the 24-byte internal format source file name.

EXIT_ENV_SOURCE_FILE_EXT

Indicates the source file name in external format.

EXIT_ENV_TARGET_FILE

Indicates the target file name in internal format.

EXIT_ENV_TARGET_FILE_EXT

Indicates the target file name in external format.

EXIT_FN_RET_OK

Function succeeded.

EXIT_FN_RET_FETCH-ERROR

An error occurred when attempting to fetch a record.

EXIT_FN_RET_INVALID_COLUMN

A non-existent column was referred to in the function call.

EXIT_FN_RET_INVALID_CONTEXT

Function called at improper time.

EXIT_FN_RET_NOT_SUPPORTED

The request is not supported.

EXIT_FN_RET_INVALID_PARAM

An invalid parameter was passed to the function.


User exit libraries

Three copy libraries define error codes, constants, and structures that are passed to and from the user exits. C user exits should use XLIBC and TAL should use XLIBTAL. For COBOL the library is XLIBCOB.

The function prototypes for C user exits are defined in the library usrdecs. For TAL the library is usrdect. These should be included in the user exit routine.


COMPRESS_RECORD | COMPRESS_RECORD2

Use COMPRESS_RECORD after processing a decompressed record. DECOMPRESS_RECORD is typically invoked when missing column values need to be fetched, such as before mapping a compressed update. COMPRESS_RECORD is called after the mapping or other processing has been completed.

In a C program, precede the INVOKE statement by the #pragma SQL CHAR_AS_ARRAY.

COMPRESS_RECORD is only valid for use with records that are less than 32767. COMPRESS_RECORD2 is valid for both these shorter records and the longer records defined with DDL2.

Syntax COMPRESS_RECORD

For C:

#include "usrdecs"
char     *compressed_rec;
short    compressed_len;
char     *decompressed_rec;
short    *columns_present;
short    source_or_target;
short    result;
result = COMPRESS_RECORD (compressed_rec, compressed_len, decompressed_rec,
                          columns_present, source_or_target);

For TAL:

?source usrdect
int result;
string .ext compressed_rec;
int    .ext compressed_len;
string .ext decompressed_rec;
int    .ext columns_present;
int     source_or_target;
result := COMPRESS_RECORD (compressed_rec, compressed_len, decompressed_rec,
                            columns_present, source_or_target) ;

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 compressed-rec   PIC X(32767).
01 compressed-len   PIC S9(4) COMP.
01 decompressed-rec PIC X(32767).
01 columns-present  PIC S9(4) COMP OCCURS 2000 TIMES.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "COMPRESS_RECORD" using compressed-rec, compressed-len, 
         decompressed-rec, columns-present, source-or-target giving result.
columns_present
columns-present

An array indicating which columns to compress. For example, if the first, third and sixth columns are to be compressed, and the total number of columns is seven, the columns array should contain 1,0,1,0,0,1,0. The number of columns in the table can be obtained by GET_NUM_COLUMNS. A column that is present but set to NULL should be indicated by a 1.

compressed_len
compress-len

The returned length of the compressed record.

compressed_rec
compressed-rec

The record returned in compressed format. The size is allocated by the user up to the maximum of 32767.

decompressed_rec
decompressed-rec

The record after it has been decompressed. The size is allocated by the user up to the maximum of 32767.

result

A code indicating whether the call was successful or not.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.

Syntax COMPRESS_RECORD2

For C:

#include "usrdecs"
char     *compressed_rec;
long     compressed_len;
char     *decompressed_rec;
short    *columns_present;
short    source_or_target;
short    result;
result = COMPRESS_RECORD2 (compressed_rec, compressed_len, decompressed_rec,
                          columns_present, source_or_target);

For TAL:

?source usrdect
int result;
string .ext compressed_rec;
int(32).ext compressed_len;
string .ext decompressed_rec;
int    .ext columns_present;
int     source_or_target;
result := COMPRESS_RECORD2 (compressed_rec, compressed_len, decompressed_rec,
                            columns_present, source_or_target) ;

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 compressed-rec   PIC X(128000).
01 compressed-len   PIC S9(8) COMP.
01 decompressed-rec PIC X(128000).
01 columns-present  PIC S9(4) COMP OCCURS 2000 TIMES.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "COMPRESS_RECORD2" using compressed-rec, compressed-len, 
         decompressed-rec, columns-present, source-or-target giving result.
columns_present
columns-present

An array indicating which columns to compress. For example, if the first, third and sixth columns are to be compressed, and the total number of columns is seven, the columns array should contain 1,0,1,0,0,1,0. The number of columns in the table can be obtained by GET_NUM_COLUMNS. A column that is present but set to NULL should be indicated by a 1.

compressed_len
compress-len

The returned length of the compressed record.

compressed_rec
compressed-rec

The record returned in compressed format. Up to X(128000) can be allocated by the user as long as it is declared in extended storage.

decompressed_rec
decompressed-rec

The record after it has been decompressed. Up to X(128000) can be allocated by the user as long as it is declared in extended storage.

result

A code indicating whether the call was successful or not.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.


DECOMPRESS_RECORD | DECOMPRESS_RECORD2

DECOMPRESS_RECORD makes compressed update records easier to process and map. Typically, DECOMPRESS_RECORD is invoked before mapping a compressed update to trigger fetching of missing column values. COMPRESS_RECORD is called after processing the compressed updates.

In a C program, precede the INVOKE statement by the #pragma SQL CHAR_AS_ARRAY. Within this structure there may be one or more columns without any true values. Valid columns are indicated in the COLUMNS-PRESENT array.

DECOMPRESS_RECORD is only valid for use with records that are less than 32767. DECOMPRESS_RECORD2 is valid for both these shorter records and the longer records defined with DDL2.

Syntax DECOMPRESS_RECORD

For C:

#include "usrdecs"
char     *compressed_rec;
short    compressed_len;
char     *decompressed_rec;
short    *columns_present;
short    source_or_target;
short    result;
result = DECOMPRESS_RECORD (compressed_rec, compressed_len, decompressed_rec,
                            columns_present, source_or_target);

For TAL:

?source usrdect
int result;
string .ext compressed_rec;
int    .ext compressed_len;
string .ext decompressed_rec;
int    .ext columns_present;
int     source_or_target; 
result := DECOMPRESS_RECORD (compressed_rec, compressed_len,
                         decompressed_rec, columns_present, source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 compressed-rec         PIC X(32767).
01 compressed-len         PIC S9(4) COMP.
01 decompressed-rec       PIC X(32767).
01 columns-present.
  05 columns-present-flag PIC S9(4) COMP OCCURS 2000 TIMES.
01 source-or-target       PIC S9(4) COMP.
01 result                 PIC S9(4) COMP.
ENTER C "DECOMPRESS_RECORD" using compressed-rec, compressed-len,
          decompressed-rec, columns-present, source-or-target giving result.
columns_present
columns-present

An array of values that indicate the columns present in the compressed record. For example, if the first, third and sixth columns exist in the compressed record, and the total number of columns is seven, the array should contain 1,0,1,0,0,1,0. The number of columns in the table can be obtained by GET_NUM_COLUMNS. A column that is present but set to NULL should be indicated by a 1.

compressed_len
compressed-len

The length of the compressed record.

compressed_rec
compressed-rec

The record in compressed format. The size is allocated by the user up to the maximum of 32767.

decompressed_rec
decompressed-rec

The record returned in decompressed format. The size is allocated by the user up to the maximum of 32767

result

A code indicating whether the call was successful or not.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.

Syntax DECOMPRESS_RECORD2

For C:

#include "usrdecs"
char     *compressed_rec;
long     compressed_len;
char     *decompressed_rec;
short    *columns_present;
short    source_or_target;
short    result;
result = DECOMPRESS_RECORD2 (compressed_rec, compressed_len, decompressed_rec,
                            columns_present, source_or_target);

For TAL:

?source usrdect
int result;
string .ext compressed_rec;
int(32).ext compressed_len;
string .ext decompressed_rec;
int    .ext columns_present;
int     source_or_target; 
result := DECOMPRESS_RECORD2 (compressed_rec, compressed_len,
                         decompressed_rec, columns_present, source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 compressed-rec         PIC X(128000).
01 compressed-len         PIC S9(8) COMP.
01 decompressed-rec       PIC X(128000).
01 columns-present.
  05 columns-present-flag PIC S9(4) COMP OCCURS 2000 TIMES.
01 source-or-target       PIC S9(4) COMP.
01 result                 PIC S9(4) COMP.
ENTER C "DECOMPRESS_RECORD2" using compressed-rec, compressed-len,
          decompressed-rec, columns-present, source-or-target giving result.
columns_present
columns-present

An array of values that indicate the columns present in the compressed record. For example, if the first, third and sixth columns exist in the compressed record, and the total number of columns is seven, the array should contain 1,0,1,0,0,1,0. The number of columns in the table can be obtained by GET_NUM_COLUMNS. A column that is present but set to NULL should be indicated by a 1.

compressed_len
compressed-len

The length of the compressed record.

compressed_rec
compressed-rec

The record in compressed format. Up to X(128000) can be allocated by the user as long as it is declared in extended storage.

decompressed_rec
decompressed-rec

The record returned in decompressed format. Up to X(128000) can be allocated by the user as long as it is declared in extended storage.

result

A code indicating whether the call was successful or not.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.


FETCH_CURRENT_RECORD

Use the FETCH_CURRENT_RECORD function to get the record from the target table with the same key as the current source record without locking the record. This makes the record buffer available to be read into the user exit by completing a call to GET_RECORD for the target image.

FETCH_CURRENT_RECORD is supported only for key-sequenced and entry-sequenced Enscribe files. The implementation for entry-sequenced files requires the use of a specified ALTKEY for proper positioning.

Fetching from the target table is only supported by Replicat, and only if a mapped target buffer is available. Replicat fetches the current record by key.

Syntax

For C:

#include "usrdecs"
short     result;
typedef struct {
  long error_num; 
  char error_msg [600];
  long max_length; 
  long actual_length;
  short msg_truncated;
} error_info_def;
error_info_def error_info_ptr;
result = FETCH_CURRENT_RECORD (&error_info_ptr);

For TAL:

?source usrdect
int result;
int .ext error_info_ptr(error_info_def);
result := FETCH_CURRENT_RECORD(error_info_ptr);

For COBOL:

?CONSULT =REPLICAT
01 result          PIC S9(4) COMP.
01 error-info.
  02 error-num     PIC S9(4) COMP.
  02 error-msg     PIC X(600).
  02 max-length    PIC S9(4) COMP.
  02 actual-length PIC S9(4) COMP.
  02 msg-truncated PIC S9(4) COMP.
ENTER C "FETCH_CURRENT_RECORD" using error-info giving result.
actual-length

The actual length of the error message that is included.

error-msg

The message explaining the error. The size is set when the function is used. PIC X(600) and char [600] are only examples of a possible value.

error-num

A code indicating whether the call was successful or not.

max-length

The maximum length allowed for an error message.

msg-truncated

Indicates whether the error message has been truncated.

result

A code indicating whether the call was successful or not.


FETCH_CURRENT_RECORD_WITH_LOCK

Use FETCH_CURRENT_RECORD_WITH_LOCK to get the record from the target table with the same key as the current source record, locking the record for update. This makes the record buffer available to be read into the user exit by completing a call to GET_RECORD for the target image.

FETCH_CURRENT_RECORD_WITH_LOCK is supported only for key-sequenced and entry-sequenced Enscribe files. The implementation for entry-sequenced files requires the use of a specified ALTKEY for proper positioning. The use of FETCH_CURRENT_RECORD_WITH_LOCK is not recommended for inserts into entry-sequenced files.

Fetching from the target table is only supported by Replicat, and only if a mapped target buffer is available. Replicat fetches the current record by key.

Syntax

For C:

#include "usrdecs"
short     result;
typedef struct {
  long error_num; 
  char error_msg;
  long max_length; 
  long actual_length;
  short msg_truncated;
} error_info_def;
error_info_def error_info_ptr;
result = FETCH_CURRENT_RECORD_WITH_LOCK(&error_info_ptr);

For TAL:

?source usrdect
int result;
int .ext error_info_ptr(error_info_def);
result := FETCH_CURRENT_RECORD_WITH_LOCK(error_info_ptr);

For COBOL:

?CONSULT =REPLICAT
01 result          PIC S9(4) COMP.
01 error-info.
  02 error-num     PIC S9(4) COMP.
  02 error-msg     PIC X(600).
  02 max-length    PIC S9(4) COMP.
  02 actual-length PIC S9(4) COMP.
  02 msg-truncated PIC S9(4) COMP.
ENTER C "FETCH_CURRENT_RECORD" using error-info giving result.
actual-length

The actual length of the error message that is included.

error-msg

The message explaining the error. The size is set when the function is used. PIC X(600) is only an example of a possible value.

error_num

A code indicating whether the call was successful or not.

max-length

The maximum length allowed for an error message.

msg-truncated

Indicates whether the error message has been truncated.


GET_ALTKEY_INFO

Returns information about an alternate key.

Syntax

For C:

short  result;
short  keytag;
short  keyoff;
short  keylen;
result = GET_ALTKEY_INFO (&keytag, &keyoff, &keylen);

For TAL:

?source usrdect
int result;
int .ext keytag;
int .ext keyoff;
int .ext keylen;
result := GET_ALTKEY_INFO(keytag, keyoff, keylen);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result PIC S9(4) COMP.
01 keytag PIC S9(4) COMP.
01 keyoff PIC S9(4) COMP.
01 keylen PIC S9(4) COMP.
ENTER C "GET_ALTKEY_INFO" using keytag, keyoff, keylen giving result.
keytag

The two-byte, generally alphanumeric, code that identifies the alternate key.

keyoff

The offset of the alternate key.

keylen

The length of the alternate key.

result

A code indicating whether the call was successful or not.


GET_COLUMN_INDEX

Given a column name, returns the column index number.

Syntax

For C:

#include "usrdecs"
short    result, 
short    col_idx;
char     col_name[36];
short    source_or_target;
result = GET_COLUMN_INDEX(&col_idx, col_name, source_or_target);

For TAL:

?source usrdect
int result;
int    .ext col_idx;
string .ext col_name;
int     source_or_target;
result := GET_COLUMN_INDEX (col_idx, col_name, source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result            PIC S9(4) COMP.
01 col-idx           PIC S9(4) COMP.
01 col-name          PIC X(36).
01 source-or-target  PIC S9(4) COMP.
ENTER C "GET_COLUMN_INDEX" using col-idx, col-name, source_or_target,
                           giving result. 
col_idx
col-idx

A sequential number from 0 to (number of columns - 1) that identifies a column.

col_name
col-name

The name of the column from the SQL catalog.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.

result

A code indicating whether the call was successful or not.


GET_COLUMN_NAME

Given a column index, returns the name.

Syntax

For C:

#include "usrdecs"
short    result;
short    col_idx;
char     col_name[36];
short    max_name_len, 
short    source_or_target;
result = GET_COLUMN_NAME(col_idx, col_name, max_name_len, source_or_target);

For TAL:

?source usrdect
int result;
int     col_idx;
string .ext column_name;
int     max_name_len;
int     source_or_target;
result := GET_COLUMN_NAME (col_idx, col_name, max_name_len,
                           source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result       PIC S9(4) COMP.
01 col-idx      PIC S9(4) COMP.
01 col-name     PIC x(36).
01 max-name-len PIC S9(4) COMP.
ENTER C "GET_COLUMN_NAME" using col-idx, col-name, max-name-len, 
                          source-or-target giving result.
col_idx
col-idx

A sequential number from 0 to (number of columns - 1) that identifies a column.

col_name
col-name

The name of the column.

max_name_len

The maximum length of the returned column name.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.

result

A code indicating whether the call was successful or not.


GET_ENV_VALUE

Returns the file name of the source or target file in either internal or external format.

For a successful completion, the type of value is indicated in the result code by one following:

Result Code Meaning
EXIT_ENV_SOURCE_FILE

Return value is the source file name in internal format.

EXIT_ENV_SOURCE_FILE_EXT

Return value is the source file name in external format.

EXIT_ENV_TARGET_FILE

Return value is the target file name in internal format.

EXIT_ENV_TARGET_FILE_EXT

Return value is the target file name in external format.


Syntax

For C:

#include "usrdecs"
short    result;
short    source_or_target;
char     buf[100];
long     actuallen; 
long     maxlen;
short    truncated;
result = GET_ENV_VALUE (source_or_target, &buf, &maxlen, &actuallen,
                         &truncated);

For TAL:

?source usrdect
int     result;
int     source_or_target;
string  .ext buf;
int(32) maxlen;
int(32) .ext actuallen;
int     .ext truncated;
result :=  GET_ENV_VALUE(source_or_target, buf, maxlen, actuallen, 
                         truncated);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result           PIC S9(4) COMP.
01 source-or-target PIC S9(4) COMP.
01 buf              PIC X(100).
01 maxlen           PIC S9(8) COMP.
01 actuallen        PIC S9(8) COMP.
01 truncated        PIC S9(4) COMP.
ENTER C "GET_ENV_VALUE" using source-or-target, buf, maxlen, actuallen,
                         truncated giving result.
actuallen

The actual length of the returned buffer

buf

The character buffer that will receive data. The space is allocated when the function is used. PIC X(100) and char buf[100] are only examples of a possible value.

maxlen

The maximum size that was allocated to the buffer.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.

truncated

Indicates whether the returned data has been truncated.

result

A code indicating whether the call was successful or not.


GET_EXITPARAM_VALUE

Use to access the full value of the EXITPARAM string. (FUNCTION_PARAM of EXIT_PARAMS will only provide up to 256 bytes of any EXITPARAM.)

Syntax

For C:

#include "usrdecs"
char      *exit_parm;
short     len;
short     result;
result = GET_EXITPARAM_VALUE (exit_parm, &len));

For TAL:

?source usrdect
int result;
string .ext exit_parm;
int .ext5 len;
result := GET_EXITPARAM_VALUE (exit_parm, len);

For COBOL:

?CONSULT =EXTRACT (or = REPLICAT)
01 EXIT-PARM PIC X(1000).
01 LEN       PIC S9(4) COMP.
01 RESULT    PIC S9(4) COMP.
ENTER C"GET_EXITPARAM_VALUE" using exit_parm, len giving result.
exit_parm
exit-parm

The length of the buffer. This is defined by the user.

len

The maximum size that was allocated to the buffer.

result

A code indicating whether the call was successful or not.


GET_EXTRBA

Gets the current position in the Oracle GoldenGate trail.

Syntax

For C:

#include "usrdecs"
long long extrba;
short     result;
result = GET_EXTRBA(&extrba);

For TAL:

?source usrdect
int     result;
int(64) .ext extrba;
result := GET_EXTRBA(extrba);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result S9(4) COMP.
01 extrba S9(16) COMP.
ENTER C "GET_EXTRBA" using &extrba giving result.
extrba

The current position in the Oracle GoldenGate trail.

result

A code indicating whether the call was successful or not.


GET_EXTSEQNO

Gets the sequence number for the current Oracle GoldenGate trail.

Syntax

For C:

#include "usrdecs"
long     seqno;
short    result;
result = GET_EXTSEQNO(&extseqno);

For TAL:

?source usrdect
int     result;
int(32) .ext seqno;
result := GET_EXTSEQNO(seqno) ;

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result     PIC S9(4) COMP.
01 seqno      PIC S9(4) COMP.
ENTER C "GET_EXTSEQNO" using seqno giving result.
seqno

The sequence number of the Oracle GoldenGate trail file.

result

A code indicating whether the call was successful or not.


GET_FILENAME

Retrieves the source or target file name.

Syntax

For C:

#include "usrdecs"
short result;
typedef struct fname_def
{char volume[8];
  char subvol[9];
  char file[8];
} fname_def;
fname_def fname;
short source_or_target;
result = GET_FILENAME(fname, source_or_target);

For TAL:

?source usrdect
int result;
int .ext fname;
int source_or_target;
result :=  GET_FILENAME (fname,  source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result     PIC S9(4) COMP2.
01 fname.
  02 volume   pic x(8).
  02 subvol   pic x(8).
  02 filename pic x(8).
01 source-or-target PIC S9(4) COMP.
ENTER C "GET_FILENAME" using fname, source-or-target giving result.
filename

The name of the current record's file.

fname

The name of the file in internal format.

source_or_target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether the record is a source or target record.

result

A code indicating whether the call was successful or not.


GET_FOPEN_NUM

Returns the open number for the file.

Syntax

For C:

#include "usrdecs"
short    result;
short    fopen_num;
result = GET_FOPEN_NUM(&fopen_num);

For TAL:

?source usrdect
int  result;
int  .ext fopen_num;
result :=  GET_FOPEN_NUM (fopen_num);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result    PIC S9(4) COMP.
01 fopen-num PIC S9(4) COMP.
ENTER C "GET_FOPEN_NUM" using fopen-num giving result.
fopen_num
fopen-num

The number assigned to the file by the process opening it.

source_or_target

Indicates whether to retrieve the source or target file name.


GET_NUM_COLUMNS

GET_NUM_COLUMNS returns the number of columns in an SQL table. Use this information when processing compressed and decompressed records.

Syntax

For C:

#include "usrdecs"
short    num_columns;
short    source_or_target;
short    result;
result = GET_NUM_COLUMNS (&num_columns, source_or_target);

For TAL:

?source usrdect 
int     result;
int     .ext num_columns;
int     source_or_target;
result := GET_NUM_COLUMNS (num_columns, source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 num-columns      PIC S9(4) COMP.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "GET_NUM_COLUMNS" using num-columns, source-or-target
         giving result.
num_columns
num-columns

The number of columns in the SQL table.

source_or_target
source-or-target

Indicates whether to retrieve number of columns for the source or target table.

result

A code indicating whether the call was successful or not.


GET_RECORD | GET_RECORD2

Data mapping from a source to a different target format is often required when extracting or replicating data. Although the COLMAP specification supported by both Replicat and Extract works sufficiently for most, user exits may be necessary for some field conversions.

Extract and Replicat pass data records to the exit after converting to the target format. In the event that a few fields do not convert, GET_RECORD and GET_RECORD2 provide a way to obtain information for custom field conversions. For example, an exit could convert a proprietary date field (such as YYDDD) in an Enscribe database to a standard SQL date in the target record, while other columns would be mapped by Extract.

GET_RECORD is only valid for use with record less than 32767. GET_RECORD2 is valid for both these smaller records and the longer records defined with DDL2.

Formats

Deletes, inserts and updates appear in the buffer as full record images. For SQL tables, this is the same format as produced by an INVOKE of the table.

Compressed SQL updates

Compressed SQL updates have the format:

index length value index length value

Where:

  • index is a two byte index into the list of columns of the table (first column is zero).

  • length is the two byte length of the table.

  • value is the actual column value, including when applicable a two byte null indicator (0 for not null, -1 for null).

Compressed Enscribe updates

Compressed Enscribe updates have the format:

offset length value offset length value

Where:

  • offset is the offset into the Enscribe record of the data fragment that changed.

  • length is the length of the fragment and value is the actual data. Fragments can span field boundaries, so full fields are not always retrieved (unless compression is off or FETCHCOMPS is elected).

Compressed Primary Key Updates

Compressed primary key updates contain three parts:

  • The before-image key length

  • The before-image key value in field comp format

  • The after-image in field comp format

You can modify the record keeping the format intact, or use DECOMPRESS_RECORD and COMPRESS_RECORD to obtain a full record format. To use the callback functions, you will need to separate the before and after-images and use the callback on only one portion at a time.

Use the following to move the record pointer so that you can manipulate the before-image up to the before_len. Note that the size of key length fields must be a long.

long before_len;
long after_len;
char *rec_ptr;
memcpy (&before_len, rec, sizeof(before_len));  /* get before len */
rec_ptr = rec + sizeof (before_len);   /* move rec_ptr passed len */

For the after-image, use the following to manipulate the after-image up to the after_len.:

rec_ptr += before_len;
after_len = exit_params->record_len - sizeof (before_len) - before_len;

To see an example of the trail record with its before and after-images, use Logdump with the Detail option set on.

Syntax GET_RECORD

For C:

#include "usrdecs"
char     *buf;
short    len;
short    io_type;
short    source_or_target;
short    result;
result = GET_RECORD (buf, &len, &io_type, source_or_target);

For TAL:

?source usrdect
int result;
string .ext buf;
int    .ext len;
int    .ext io_type;
int    source_or_target;
result := GET_RECORD (buf, len, io_type, source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 buf              PIC X(32767).
01 len              PIC S9(4) COMP.
01 io-type          PIC S9(4) COMP.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "GET_RECORD" using buf, len, io-type, source-or-target
                     giving result.
buf

The record buffer for data returned by the Extract or Replicat programs. The memory for this buffer must be allocated by the user. Up to X(32767) can be used for the buffer.

io_type
io-type

Indicates the type of operation represented by the record, such as:

3 — Delete

5 — Insert

10 — Update

11 — Compressed Enscribe Update

15 — Compressed SQL Update

115 — Compressed primary key Update

len

LEN is the length of the data returned in BUF.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether to retrieve the source or target record.

result

A code indicating whether the call was successful or not.

Syntax GET_RECORD2

For C:

#include "usrdecs"
char     *buf;
long    len;
short    io_type;
short    source_or_target;
short    result;
result = GET_RECORD2 (buf, &len, &io_type, source_or_target);

For TAL:

?source usrdect
int result;
string .ext buf;
int(32).ext len;
int    .ext io_type;
int    source_or_target;
result := GET_RECORD2 (buf, len, io_type, source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 buf              PIC X(128000).
01 len              PIC S9(8) COMP.
01 io-type          PIC S9(4) COMP.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "GET_RECORD2" using buf, len, io-type, source-or-target
                     giving result.
buf

The record buffer for data returned by the Extract or Replicat programs. The memory for this buffer must be allocated by the user. Up to X(128000) can be used in the buffer as long as it is declared in extended storage.

io_type
io-type

Indicates the type of operation represented by the record, such as:

3 — Delete

5 — Insert

10 — Update

11 — Compressed Enscribe Update

15 — Compressed SQL Update

115 — Compressed primary key Update

len

LEN is the length of the data returned in BUF.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether to retrieve the source or target record.

result

A code indicating whether the call was successful or not.


GET_RECORD_LENGTH | GET_RECORD_LENGTH2

When returning control to Extract or Replicat, user exits are responsible for setting the length of the target record if and when mapping occurs. Use GET_RECORD_LENGTH or GET_RECORD_LENGTH2 to obtain this value when the mapped record is not compressed. Set the EXIT-PARAMS structure member RECORD-LENGTH to this value.

GET_RECORD_LENGTH2 is only valid for use with records less than 32767. GET_RECORD_LENGTH2 is valid for both these smaller records and the longer records defined with DDL2.

Syntax GET_RECORD_LENGTH

For C:

#include "usrdecs"
short    record_length;
short    source_or_target;
short    result;
result = GET_RECORD_LENGTH (&record_length, source_or_target);

For TAL:

?source usrdect
int     result;
int     .ext record_length;
int     source_or_target;
result := GET_RECORD_LENGTH(record_length,  source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 record-length    PIC S9(4) COMP.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "GET_RECORD_LENGTH" using record-length, source-or-target
         giving result.
record_length
record-length

The record length as calculated internally by Extract or Replicat.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether to retrieve the source or target record.

result

A code indicating whether the call was successful or not.

Syntax GET_RECORD_LENGTH2

For C:

#include "usrdecs"
long    record_length;
short    source_or_target;
short    result;
result = GET_RECORD_LENGTH2 (&record_length, source_or_target);

For TAL:

?source usrdect
int     result;
int(32) .ext record_length;
int     source_or_target;
result := GET_RECORD_LENGTH2(record_length,  source_or_target);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 record-length    PIC S9(8) COMP.
01 source-or-target PIC S9(4) COMP.
01 result           PIC S9(4) COMP.
ENTER C "GET_RECORD_LENGTH2" using record-length, source-or-target
         giving result.
record_length
record-length

The record length as calculated internally by Extract or Replicat.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether to retrieve the source or target record.

result

A code indicating whether the call was successful or not.


GET_SYSKEY_LENGTH

Returns the length of SYSKEY for the current record.

Syntax

For C:

include "usrdecs"
short   syskeylen, 
short   source_or_target;
short   result;
result = GET_SYSKEY_LENGTH(&syskey_len, source_or_target);

For TAL:

?source usrdect
int  result;
int  .ext syskeylen;
int  source_or_target;
result := GET_SYSKEY_LENGTH (syskeylen, source_or_target) ;

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result           PIC S9(4) COMP.
01 syskeylen        PIC S9(4) COMP.
01 source_or_target PIC S9(4) COMP.
ENTER C "GET_SYSKEY_LENGTH" using syskeylen, source-or-target 
         giving result.
syskeylen

The length of the system key.

source_or_target
source-or-target

Represented by either EXIT-FN-SOURCE-VAL or EXIT-FN-TARGET-VAL to indicate whether to retrieve the source or target record.

result

A code indicating whether the call was successful or not.


GET_TRANSACTION_IND

Knowing whether a data record is the first, last or middle operation in a transaction can prove useful to an exit routine. For example, an exit might want to compile the details of each transaction and output a special summary record at the end. This type of processing is accommodated by GET_TRANSACTION_IND.

Syntax

For C:

#include "usrdecs"
short result;
short trans_ind;
result = GET_TRANSACTION_IND (&trans_ind);

For TAL:

?source usrdect
int result;
int .ext trans_ind;
result := GET_TRANSACTION_IND (trans_ind);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result    PIC S9(4) COMP.
01 trans-ind PIC S9(4) COMP.
ENTER C "GET_SOURCE_RECORD" using trans-ind giving result.
trans_ind
trans-ind

Indicates whether the current record is the first (0), middle (1), last (2), or both first and last (3) record in a transaction.

result

A code indicating whether the call was successful or not.


GET_USER_TOKEN_VALUE

GET_USER_TOKEN_VALUE allows the user exit to retrieve the value of user tokens.

Buffers

xlibc

typedef struct __user_token_value {
   char   token_name[256];
   short  actual_length;
   char   token_value_buf[2000];
} user_token_vaue_def;

xlibcob

01 result native-2.
?Section TOKENS,Tandem
  01 USER-TOKEN-VALUE.
    02 TOKEN-NAME PIC X(256).
    02 ACTUAL-LENGTH NATIVE-2.
    02 TOKEN-VALUE-BUF PIC X(2000).

Syntax

For C:

#include "usrdecs"
#include "xlibc"
short result = 0;
user_token_value_def usr_token_val;
result = GET_USER_TOKEN_VALUE (&usr_token_val);

For TAL:

?source usrdect
int result;
int .ext utoken_value_ptr(user_token_value_def);
result := GET_USER_TOKEN_VALUE(utoken_value_ptr); 

For COBOL:

?ENV COMMON
?CONSULT =EXTRACT (or =REPLICAT)

ENTER C "GET_USER_TOKEN_VALUE" using USER-TOKEN-VALUE giving RESULT. 

Return Values

EXIT_FN_RET_OK
EXIT_FN_RET_INVALID_CONTEXT
EXIT_FN_RET_TOKEN_NOT_FOUND
token_name
TOKEN-NAME

Up to 256 characters to specify the name of the user token.

actual_length

The actual length of the data returned in the buffer.

token_value_buf

The 2000 byte buffer that will receive data.

result

A code indicating whether the call was successful or not. One of the following:

EXIT_FN_RET_OK
EXIT_FN_RET_INVALID_CONTEXT
EXIT_FN_RET_TOKEN_NOT_FOUND

GGS_EMSMESSAGE

GGS_EMSMESSAGE allows a user exit to write a message to the EMS log file. The message will have the Oracle GoldenGate subsystem ID.

Syntax

For C:

#include "usrdecs"
short result;
int   evtnum;
int   severity;
char  *text;
result = GGS_EMSMESSAGE(int evtnum, text, severity);

For TAL:

?source usrdect
int    result;
int    evtnum;
string .ext text;
int    severity;
result := GGS_EMSMESSAGE(evtnum, text, severity);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 evtnum        PIC S(4) COMP.
01 result        PIC S(4) COMP.
01 text          PIC X(132).
01 severity      PIC S(4) COMP.
ENTER C "GGS_EMSMESSAGE" using evtnum, text, severity giving result.
evtnum

An arbitrary number used to identify a message.

text

The text of the message.

severity

A value that identifies how severe the message is, as in:

  • MSG_INFO 1 — normal EMS message.

  • MSG_CRITICAL 2 — EMS message with emphasis set to ON.

  • MSG_FATAL 3 — abends the process after writing the message.

result

A code indicating whether the call was successful or not.


GGS_REPORTMESSAGE

Allows a user exit to write a message to the report file.

Syntax

For C:

#include "usrdecs"
short    result;
char    text[132];
result = GGS_REPORTMESSAGE(&text);

For TAL:

?source usrdect
int result;
string .ext text;
result := GGS_REPORTMESSAGE(text) ;

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 result PIC S9(4) COMP.
01 text   PIC X(132).
ENTER C "GGS_REPORTMESSAGE" using text giving result.

Note:

The string value in message text must be null terminated.

text

The text of the message.

result

A code indicating whether the call was successful or not.


SET_TARGET_RECORD2

Use SET_TARGET_RECORD2 to set the values of a modified record. This step is not required for the buffers under 32 K, but is required for larger records defined with DDL2.

Syntax

For C:

#include "usrdecs"
char     *buf;
long     record_len;
short    io_type;
short    result;
result = SET_TARGET_RECORD2 (buf, &record_len, &io_type);

For TAL:

?source usrdect
string  .ext buf;
int(32) len;
int     io_type;
int     result;
result := SET_TARGET_RECORD2 (buf, len, io_type);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 buf       PIC X(128000).
01 len       PIC S9(8) COMP.
01 io-type   PIC S9(4) COMP.
01 result    PIC S9(4) COMP.
ENTER C "SET_TARGET_RECORD2" using buf, len, io-type giving result.
buf

The record buffer for data returned by the Extract or Replicat programs. The memory for this buffer must be allocated by the user. Up to X(127000) can be used in the buffer as long as it is declared in extended storage.

len

LEN is the length of the data returned in BUF.

io_type
io-type

Indicates the type of operation represented by the record, such as:

3 — Delete

5 — Insert

10 — Update

11 — Compressed Enscribe Update

15 — Compressed SQL Update

115 — Compressed primary key Update

result

A code indicating whether the call was successful or not.


SET_TARGET_RECORD_LENGTH2

Use SET_TARGET_RECORD_LENGTH2 to set the length of a modified target record. This step is not required for the smaller records defined with DDL, but is required for large records defined with DDL2.

Syntax

For C:

#include "usrdecs"
long     record_len;
short    result;
result = SET_TARGET_RECORD_LENGTH2 (&record_len);

For TAL:

?source usrdect
int(32) record_len;
int     io_type;
int     result;
result := SET_TARGET_RECORD_LENGTH2 (record_len);

For COBOL:

?CONSULT =EXTRACT (or =REPLICAT)
01 record-len  PIC S9(8) COMP.
01 result      PIC S9(4) COMP.
ENTER C "SET_TARGET_RECORD_LENGTH2" using record-length giving result.
record_len
record-len

The record length as calculated internally by Extract or Replicat.

result

A code indicating whether the call was successful or not.