Transaction Connection


About This Book

This book provides technical information for using Transaction Connection (TC). It describes the script language that you use to pass information between DCConnect and a host system, database(s) or XML-based application. Following a discussion of general data collection concepts is a reference for the commands in the script language. At the end is a description of the messages that TC might generate.

This section provides general information about how to use this online book, as well as the legal notices, service marks, and trademarks used in this book.

To receive information about a topic that is highlighted, click on it:


Notices

Last Update (January 2024)

References in this documentation to IBM products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program, or service is not intended to state or imply that only IBM's product, program, or service can be used. Any functionally equivalent product, program, or service that does not infringe upon any of IBM's intellectual property rights or other legally protectible rights can be used instead of the IBM product, program, or service. Evaluation and verification of operation in conjunction with other products, programs, or services, except those expressly designated by IBM, are the user's responsibility.

IBM may have patents or pending patent applications covering the subject matter in this documentation. The furnishing of this publication does not give you any rights to these patents. You can inquire, in writing, to:

IBM Director of Licensing
IBM Corporation
500 Columbus Avenue
Thornwood, NY  10594
U.S.A.

For online versions of this documentation, we authorize you to:

You are responsible for payment of any taxes, including personal property taxes, resulting from this authorization.

THERE ARE NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Some jurisdictions do not allow the exclusion of implied warranties, so the above exclusion might not apply to you.

Your failure to comply with the terms above terminates this authorization. Upon termination, you must destroy your machine-readable documentation.


Trademarks and Service Marks

The following terms are trademarks of the IBM Corporation in the United States or other countries or both:

IBM

Transaction Connection

OS/2

Operating System/2

MAPICS

Presentation Manager

DB2

 

Other company, product, and service names may be trademarks or service marks of others.

Windows is a trademark of Microsoft Corporation.


Transaction Connection Overview

The Transaction Connection (TC) program is a is a script-based data collection transaction processing program which make it easy to integrate with:

TC can connect to any combination of these systems at one time and pass data in any direction among them. You write TC scripts containing commands to format, process and route data.

Unique TC scripts can be defined for each transaction type that must be handled; TC scripts can also be set up to handle the movement of data between otherwise unconnected systems.

For example, a worker at a data collection terminal can press a function key, scan a few bar codes in response to input prompts, and create a transaction that is routed through DCConnect and TC to the relational database and/or the host application screen. Query results or host application responses can be routed back to the operator at the terminal. All of this happens without the operator being required to log-on, navigate menus and windows, or know how to handle application errors.

For the part of the application involving the relational database, basic database inserts, updates, and queries can be developed and up and running in production in very little time. Also, the power and flexibility are available to be as elaborate with the SQL as you want to be -- again with a fraction of the effort required to write SQL from scratch, and with the performance of having a compiled C program performing your dynamic SQL.

For the host application screen manipulation, your script, consisting of high-level commands, is used to automate the function of a data entry operator. Once you train the system with your script of actions to be taken for each type of transaction, your Transaction Connection scripts will work tirelessly and without any keystroke errors as it intelligently transcribes data to the host application.


Transaction, Remote Validation, or Data Request Modes

A TC session can be run in one of three modes: Transaction, Remote Validation, or Data Request mode. In any mode, you can perform database inserts, updates, and queries, and/or host screen manipulations using the data from the DCT.

Transaction Mode

Transaction mode requests data transactions from a DCConnect mailbox, processes the data as you have specified in your script command file, and finally releases the transaction from the DCConnect mailbox. The TC session operates in Transaction mode if the mailbox specified on the command line or in the script files is any name except REMOTE_VALIDATION or DATA_REQUEST, and the mailbox matches one configured in DCConnect.

Each TC session that is running in Transaction mode can receive and individually process transactions from up to 50 function groups, with each function group having up to 121 unique scripts for each possible key event (F1, F2, ..., PF1, PF2, ...)

Alternately, instead of identifying script processing based on function group and key event (using StartFunctionGroup/StartKey), you can base it on a portion of the received data using the StartMatch statement. Typically the first 3 to 5 characters of the data would be an identifier that must match one of the StartMatch statements in the script being processed. Regardless of the number of characters you choose, it is recommended that you use that number for all scripts in order to avoid problems where the characters of one ID are a subset of another ID.

Remote Validation Mode

In Remote Validation mode, the TC session informs DCConnect of a list of validation file names that it will be handling. Each time a DCT sends a remote validation request to DCConnect that matches one of these validation file names, DCConnect routes the validation request to this TC session for validation and response. In this case, the file names do not refer to an actual file, but the name is used as the identification of the validation required for the incoming data.

The TC session operates in Remote Validation mode if it has been started with REMOTE_VALIDATION specified as the mailbox. Then, in your command script file, instead of specifying a terminal event (for example, F1, F2, and so forth) in a StartKey command, you specify the validation file name in a StartVal command.

The TC session determines the list of validation files from all of the StartVal() statements in the script it is processing.

A single TC session can handle processing for up to 125 remote validation files. You may start as many remote validation sessions of TC as you need and that your system can handle. Use of the mailbox REMOTE_VALIDATION repeatedly for these sessions is an exception to the rule about requiring unique mailboxes for each TC session.

A typical method of actually performing the remote validation is to perform a query (SELECT statement) that yields either no rows or one or more rows of resulting report data. This provides the information necessary to determine if the data being verified is present or absent in the system. The Perform_Select or Perform_Fetch commands allow you to branch to the appropriate step if no rows were found or to fall through to another step if one or more rows were found. Refer to the example Handling Remote Validation Request.

Data Request Mode

In Data Request Mode, the TC session informs DCConnect that it is handling data requests for a particular application name. That application name can be specified on the command line or in the command script file.

Data requests can be made in a several different ways:

A TC session could be set up as a kind of server for other TC sessions to allow them to communicate with each other indirectly. The 'server' TC session would set itself up in data request mode to allow all the other TC sessions to communicate with it, regardless of what mode they are running in.

No matter where the data request originated, it contains the name of the application that is supposed to service the request. This is the application name that DCConnect uses to route the request to the proper server. It is the name that must be specified by the 'server' TC session as the <application> parameter or in the Application script command.

The TC session operates in Data Request mode if it has been started with the keyword DATA_REQUEST being specified as the mailbox name, either on the command line for the <mailbox> parameter or in the script using the mailbox() command. In Data Request mode, you must specify the application name in the command file or on the command line.

You can start as many data request TC sessions as you need and that your system can handle. For each, the mailbox parameter always is DATA_REQUEST. However, the application name used by each session must be unique.

When in Data Request mode, you cannot use the StartKey/StartVal/StartCluster commands or the corresponding End commands. You must use StartMatch / EndMatch blocks to divide up the processing of the data requests. You should ensure that all possible kinds of data requests that are handled by the TC session are unique in some portion of the data. It is recommended that the first one or more characters of the data be used for identifying the type of request. Regardless whatever number of characters you choose, use that number for all scripts in order to avoid problems where the characters of one ID are a subset of another ID.

When in Data Request mode, each request that is received contains the following data parts, accessible through the Set / Append_UV_Xact_Data command and other commands that access data parts:

    DATALEN
    TXNDATA
    ORIGINATOR
    TERM_NAME
    TXNFIELD1

The data parts ORIGINATOR and TERM_NAME are synonymous. The term ORIGINATOR is used because data requests, unlike transactions or validation requests, may originate from another application rather than from a terminal. The term ORIGINATOR covers both terminals and applications, although using TERM_NAME works even if the originator is not a terminal.

Even those data requests that do originate from a terminal, do so from a special kind of terminal, the DCConnect DOS and Windows terminal. These terminals can generate only data requests, transaction and validation requests; they cannot process commands initiated by other applications - with the exception of Set_Term_UV_Data/Send_Named_Term_UV_Data/Send_Term_Data. All other terminal-related script commands are not to be used for the originator of a data request.

The data portion of the data request can be up to 16383 bytes in length. Because the data request can be much larger than most of the user variables (235 bytes), several of the user variables can accommodate data up to 16383 bytes. By default the user variables in the range 241-250 are automatically allocated for 16383 bytes if they are referenced any where in the script. These user variables can be treated just like the other user variables; they are just longer than the others.

Note: The total number of user variables and the number of large user variables can be changed by using the Define_UVs command. The size of large user variables can be changed using Define_Large_UV_Size command.

After a data request is received, the script must do one of two things:

Build a reply for that request

This can be done in one of the large user variables - or even a smaller one if the reply does not exceed 235 bytes. When the reply has been built, the script command:

    Reply_To_Data_Request()

can be used to send the reply to the originator of the request. This command specifies the user variable that contains the reply and an optional label to branch to if the reply is not sent successfully.

Forward the data request to another application

Using the command:

    Forward_Data_Request()
to specify the name of an application to which the current data request should be given. That application must currently be registered with DCConnect in order for the forward operation to be successful. This command takes one parameter, the target application name. This application name can even be the same application (the current TC session), in which case the request is added to the end of the queue of outstanding requests for this application.


Routing Incoming Transactions/Requests for Processing

Your incoming transactions, remote validation requests, web service requests, and data requests are sorted and routed along the way by each layer of the system.

The various Start... commands allow you to customize processing of many types of incoming data. TC sorts each transaction, remote validation requests, web service requests, or data requests as follows.


Running Scripts Based on Time-Related Events

You can define scripts to be run based on various time-related events:


Elements of the TC Script Language

This section describes various data elements and control features that are used to create scripts for processing your transactions, validation requests and data requests.

Using White Space, Blank Lines and Comments in TC Scripts

When entering commands in TC scripts, the following rules apply:

User Variables

Transaction Connection allows two types of user variables:

  1. Global user variables, which are accessible from any script at any time

  2. Local user variables, which may be manipulated only by the script in which they are defined.

By default TC allows you to define up to 250 global user variables for your use to accumulate and store data. The total number of user variables can be changed using the Define_UVs command.

Being global means that they are accessible from all places in the execution of the command file, and that they are never automatically cleared or changed (except on start-up of the session). When in doubt about the contents of a user variable, useClear_UV to reset the user variable.

Each of the user variables is always referred to by name, not by a plain number. The default names are UV1 through UV250, but you can give them more meaningful aliases by using the Name_UV command.

  Name_UV( UV1,     uvBadgeNumber )    // uvBadgeNumber is alias for UV1
  Name_UV( NEXT_UV, uvRow         )    // uvRow         is alias for UV2
  Name_UV( NEXT_UV, uvCol         )    // uvCol         is alias for UV3

Many commands require you to provide the name (UVn format, or your own chosen alias) of a user variable to be used as a target for the output of a command. For example:

  Append_UV_Host_Data( UV1, 12, 25, 10 )

tells TC to copy 10 characters starting at row 12, column 25 from the host application screen to the UV1 storage.

Other commands allow you to specify either a constant or the current value of a user variable to be used as an input to the command. For example, if you wanted to copy information from the host screen but you wanted to specify which row to copy from dynamically, you could do:

  Append_UV_Host_Data( UV1, UV2, 25, 10 )

where UV2 has a value that can be interpreted as an integer row number.

Using the aliases assigned above, you could alternatively write this as:

  Append_UV_Host_Data( uvBadgeNumber, uvRow, uvCol, 10 )
and achieve the same results with a script, that is easier to develop and maintain. In this case, the value 25 would have to have been assigned to the uvCol user variable prior to this command.

TC creates storage for as many user variables as you reference in your script, up to the defined maximum. Even if the user variables used are not consecutive, only the minimum amount of storage is allocated.

By default, user variables 1 through 240 are 235 characters long, and have no particular data type (you can store integers, real numbers, or character strings in them). And by default, user variables 241 through 250 have the same characteristics except that they are 16383 characters long. These large user variables are useful when processing or making data requests because data requests and their replies can be up to 16383 characters long. If you do not handle data greater than 235 characters, you should not use variables 241-250. This helps conserve your PC's resources.

You can change the total number of user variables available as well as the number of large user variables using the Define_UVs command.

In addition to the usual global user variables ( named user variables and UVn references) you can declare local user variables within a StartMatch / EndMatch, StartTime / EndTime etc. block or within a subroutine. Local user variables are created using the Declare command:

  DECLARE ( localUVName )
The locally-declared user variable is known only within the confines (scope) of the Start... / End... or subroutine where it was defined. Local user variables may be declared at any point in the script, but must be declared before they can be used in a command in that script.

You can have local user variables with the same name in many routines -- they each have their own storage area. Local user variables may not, however, have the same name as any global user variable which has already been named via the Name_UV command, nor have a name like 'UV12' which would be confused with a basic global user variable name. It is recommended that you use a naming convention (say, a leading 'g' on all global user variables) in order to keep things straight and to avoid any compile errors.

Local user variables are the same size as 'regular' global user variables (235 characters). If you need a long user variable (16KB unless redefined) you will need to use a suitably defined large global user variable.

There are several commands that can be used to affect the contents of the local/global user variables:

Data Parts

TC provides descriptive names for various data parts that are predefined for your use. These parts can be distinct elements of the incoming transaction, remote validation request, data request, or the TC user variables. Many commands require that you specify a data part name as one of their parameters.

The predefined names allowed are shown in Data Parts You Can Use. Some names are only valid when executing in Transaction Mode. Others are valid only in Remote Validation Mode, while others are valid in only Data Request mode. The remainder can be used in either mode.

Table of Data Parts


Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
LAST_DS_ALIAS Yes Yes Yes Records the last data source alias name used in any SQL (including fetches, commit, etc.). This can be used, for example, to create generic routines to handle the 'no more records' condition of a fetch loop. Start, Length are ignored for this data part; use "0, 0"
LAST_ERROR Yes Yes Yes Records the last error value for a number of different commands, including the Web Service commands (e.g. WS_CreateElement, WS_SendRequest), the Host Screen Interface functions (e.g. Check_Color, Send_Host_UV_Data), XML Functions (e.g. XML_CreateBOD, XML_LeaveElement), Database commands - stores the SQLSTATE value (e.g. Begin / End_SQL, PerformInsert), commands that interface to DCConnect (e.g. Submit_Validation, Reply_To_Data_Request), plus the following miscellaneous commands: Append_UV_File_Data, Log_Data, Open_File_Data, and System. For all successful executions of commands this value is set to the appropriate good return code value for that command (usually 0). Start, Length are ignored for this data part; use "0, 0"
LAST_WS_COMMAND_INFO Yes Yes Yes Set during the execution of any WS_xxxxx command to a string that identifies that command and its key input parameters. Intended to be used in conjunction with an On_Error_Goto ( WEBSERVICE, <error label> ) command as a way to identify which command caused the branch to the error label. Start, Length are ignored for this data part; use "0, 0"
SESSION_STATUS Yes Yes Yes EHLLAPI ('screen scraper') connection status to host screen. "1" if connected, "0" if not. Start, Length are ignored for this data part; use "0, 0"
XACT_AGE Yes Yes* Yes* Age of the current transaction in seconds, calculated based on the current PC time and the DCT-applied time stamp in the transaction data. Note *: This is always 0 for remote validation and data request modes.

See note at end of table about adjusted date/time.

Start, Length are ignored for this data part; use "0, 0"
SEQ Yes No No DCConnect sequence number. Max is 9 but TC uses Start and Length provided without checking. If Length is 0, no data is returned.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
RIC Yes Yes No Terminal's location number. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
LINE Yes Yes No Terminal's location line number. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADDRESS Yes Yes No Terminal's single-character address. Max is 1 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
FUNCTIONGROUP Yes No No The DCConnect function group to which the terminal belongs. If the terminal does not belong to a function group, the job name is returned. Max is 31 but Start, Length are ignored for this data part; use "0, 0"
TERMSEQ Yes No No The terminal sequence number. Max is 5 but TC uses Start and Length provided without checking. If Length is 0, no data is returned.
DATE Yes No No The date from the transaction in the format YYMMDD

See note at end of table about adjusted date/time.

Max is 6 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
DATE4 Yes No No The date from the transaction in the format YYYYMMDD

See note at end of table about adjusted date/time.

Max is 8 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TIMESTAMP Yes No No Timestamp from the transaction in the format YYMMDDHHmmSS.

See note at end of table about adjusted date/time.

Max is 12 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TIMESTAMP4 Yes No No Timestamp from the transaction in the format YYYYMMDDHHmmSS.

See note at end of table about adjusted date/time.

Max is 14 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
YEAR Yes No No The year from the transaction in the format YY.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
YEAR4 Yes No No The year from the transaction in the format YYYY.

See note at end of table about adjusted date/time.

Max is 4 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
MONTH Yes No No The month from the transaction in the format MM.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
DAY Yes No No The day from the transaction in the format DD.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TIME Yes No No The time from the transaction in the format HHmmSS.

See note at end of table about adjusted date/time.

Max is 6 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
HOUR Yes No No The hour from the transaction in the format HH.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
MINUTE Yes No No The minute from the transaction in the format mm.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
SECOND Yes No No The second from the transaction in the format SS.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
MODE Yes No No The mode of the transaction (I, B, and so forth; see ETS Tech Ref). Max is 1 but TC uses Start and Length provided without checking. If Length is 0, no data is returned.
TRANSID Yes No No Terminal event ID that started the transaction. Max is 3 but TC uses Start and Length provided without checking. If Length is 0, no data is returned.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
DATALEN Yes Yes Yes The length of the data portion of the transaction/request.
Default 4 for transaction, but can be longer.
Max is 4 for validation
Max is 5 for data request
TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TXNDATA Yes Yes Yes The beginning of the data in the transaction, remote validation request or data request. Max is variable but TC uses Start and Length provided after making sure they do not exceed the current data length. If Length is 0, Max minus Start is used. As of October 2004, TC support transactions with up to 750 bytes of data, provided the DCConnect Server is at the same level or later. Prior to October 2004, a transaction could have no more than 108 bytes of data.
TERM_NAME Yes Yes Yes The DCConnect terminal name. For data request this is synonymous with ORIGINATOR. Max is 31 but Start, Length are ignored for this data part; use "0, 0"
VAL_TYPE No Yes No Set to POSITIVE or NEGATIVE based on requested validation type (inclusive in file or exclusive in file, respectively). Max is 8 but Start, Length are ignored for this data part; use "0, 0"
VAL_FILE No Yes No The remote validation file name requested by the terminal. Max is 12 but TC uses Start and Length provided without checking. If Length is 0, no data is returned.
ORIGINATOR No No Yes The application or terminal that originated the data request. Synonymous with TERM_NAME. Max is 32 but Start, Length are ignored for this data part; use "0, 0"
RECORD Yes No No The beginning of entire DCConnect transaction. Max is variable but TC uses Start and Length provided without checking. If Length is 0, no data is returned.
NULL Yes Yes Yes Use no data part (used when you want only the PREFIX and/or SUFFIX constants in the Select_Having, Select_Where, Setup_Insert_Field, Setup_Update_Field, or Update_Where commands). 0
CURRENT_TIME Yes Yes Yes HH:MM:SS (24-hour style) Max is 8 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_SEC Yes Yes Yes 00-59 Max is 2 but Start, Length are ignored for this data part; use "0, 0"
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
CURRENT_MIN Yes Yes Yes 00-59 Max is 2 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_HOUR Yes Yes Yes 00-23 Max is 2 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_DATE Yes Yes Yes MM/DD/YY (DD.MM.YY if DP_IS_COMMA is used) Max is 8 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_DATE4 Yes Yes Yes MM/DD/YYYY (DD.MM.YYYY if DP_IS_COMMA is used) Max is 10 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_DAY Yes Yes Yes 01-31 Max is 2 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_MON Yes Yes Yes 01-12 Max is 2 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_YEAR Yes Yes Yes YY Max is 2 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_YEAR4 Yes Yes Yes YYYY Max is 4 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_WEEKDAY Yes Yes Yes 0-6 (SUN - SAT) Max is 1 but Start, Length are ignored for this data part; use "0, 0"
CURRENT_TIMESTAMP Yes Yes Yes MM/DD/YY HH:MM:SS (DD.MM.YY HH:MM:SS if DP_IS_COMMA is used) Max is 17 but Start, Length are ignored for this data part; use "0, 0"
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
CURRENT_TIMESTAMP4 Yes Yes Yes MM/DD/YYYY HH:MM:SS (DD.MM.YYYY HH:MM:SS if DP_IS_COMMA is used) Max is 19 but Start, Length are ignored for this data part; use "0, 0"
COUNT_HANDLES Yes Yes Yes The quantity of Windows OS handles owned by the TC process is obtained using this data part. Start, Length are ignored for this data part; use "0, 0"
COUNT_TXNFIELDS Yes Yes Yes The quantity of delimited fields in the transaction data is obtained using this data part. Start, Length are ignored for this data part; use "0, 0"
NEXT_TXNFIELD Yes Yes Yes Make an explicit use of a numbered TXNFIELD to set the starting field, then use NEXT_TXNFIELD to step through each of the following fields. Max is variable but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
UV1 to UV250 (or other maximum), or aliases and local variables Yes Yes Yes User variable number 1 through 250 (or other maximum defined by Define_UVs) Max is up to 235 bytes for UV1 through UV240. Up to 16383 bytes for UV241 through UV250. (Unless ranges changed by the Define_UVs command or the large UV size changed by the Define_Large_UV_Size). TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TXNFIELD1 to
TXNFIELD1024

Yes Yes Yes Transaction data field number 1 through 1024. The individual data fields in the transaction must be separated with semi-colons, including a final terminating semi-colon. The fields can be variable length, with LENGTH specified as 0 to use the entire length up to the next semi-colon. Max is variable but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
DBTYPE Yes Yes Yes Is a string that specifies the type of database to which TC is connected. Could be set to DB2 if DBTYPE is set to DB2 on the command line or using a script command. But if DBTYPE was set to ODBC on the command line or using a script command, TC queries the database driver for the actual database type and then matches the response to one of the aliases defined in DBTYPE.INI. The DBTYPE data part is then set to one of the database types defined in that file. For more information please see Handling Differences Between Database Types When Using ODBC. Start, Length are ignored for this data part; use "0, 0"
SQLCURRENTTIME Yes Yes Yes Is the string defined for the CURRENT_TIME_FUNCTION from dbtype.ini for the current database type. If no database is in use this will resolve to "SQLCURRENTTIME ???" Start, Length are ignored for this data part; use "0, 0"
ADJDATE Yes No No The date from the transaction, adjusted to the server's time zone, in the format YYMMDD.

See note at end of table about adjusted date/time.

Max is 6 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
ADJDATE4 Yes No No The date from the transaction, adjusted to the server's time zone, in the format YYYYMMDD

See note at end of table about adjusted date/time.

Max is 8 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJTIMESTAMP Yes No No Timestamp from the transaction, adjusted to the server's time zone, in the format YYMMDDHHmmSS.

See note at end of table about adjusted date/time.

Max is 12 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJTIMESTAMP4 Yes No No Timestamp from the transaction, adjusted to the server's time zone, in the format YYYYMMDDHHmmSS.

See note at end of table about adjusted date/time.

Max is 14 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJYEAR Yes No No The year from the transaction, adjusted to the server's time zone, in the format YY.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJYEAR4 Yes No No The year from the transaction, adjusted to the server's time zone, in the format YYYY.

See note at end of table about adjusted date/time.

Max is 4 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJMONTH Yes No No The month from the transaction, adjusted to the server's time zone, in the format MM.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJDAY Yes No No The day from the transaction, adjusted to the server's time zone, in the format DD.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJTIME Yes No No The time from the transaction, adjusted to the server's time zone, in the format HHmmSS.

See note at end of table about adjusted date/time.

Max is 6 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJHOUR Yes No No The hour from the transaction, adjusted to the server's time zone, in the format HH.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
ADJMINUTE Yes No No The minute from the transaction, adjusted to the server's time zone, in the format mm.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
ADJSECOND Yes No No The second from the transaction, adjusted to the server's time zone, in the format SS.

See note at end of table about adjusted date/time.

Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMDATE Yes No No The date from the transaction, based on terminal's time zone, in the format YYMMDD. Max is 6 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMDATE4 Yes No No The date from the transaction, based on terminal's time zone, in the format YYYYMMDD Max is 8 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMTIMESTAMP Yes No No Timestamp from the transaction, based on terminal's time zone, in the format YYMMDDHHmmSS. Max is 12 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMTIMESTAMP4 Yes No No Timestamp from the transaction, based on terminal's time zone, in the format YYYYMMDDHHmmSS. Max is 14 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMYEAR Yes No No The year from the transaction, based on terminal's time zone, in the format YY. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMYEAR4 Yes No No The year from the transaction, based on terminal's time zone, in the format YYYY. Max is 4 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMMONTH Yes No No The month from the transaction, based on terminal's time zone, in the format MM. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMDAY Yes No No The day from the transaction, based on terminal's time zone, in the format DD. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMTIME Yes No No The time from the transaction, based on terminal's time zone, in the format HHmmSS. Max is 6 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMHOUR Yes No No The hour from the transaction, based on terminal's time zone, in the format HH. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
TERMMINUTE Yes No No The minute from the transaction, based on terminal's time zone, in the format mm. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
Name Used in Transaction Mode Used in Remote Validation Mode Used in Data Request Mode Description Max Character Length + Start/Length Notes
TERMSECOND Yes No No The second from the transaction, based on terminal's time zone, in the format SS. Max is 2 but TC uses Start and Length provided after making sure they do not exceed the Max. If Length is 0, Max minus Start is used.
CURRENT_MAILBOX Yes Yes Yes Returns the name of the mailbox from which the TC session is reading. If running in remote validation mode or data request mode, this data part will have the value "REMOTE_VALIDATION" or "DATA_REQUEST" respectively. And if the TC session is not receiving transactions/remote validation requests or data requests from the DCConnect Server then the value of this data part will be "NO_DCCONNECT". Start, Length are ignored for this data part; use "0, 0"
EXECUTION_TIME_LAST Yes Yes Yes Gives the individual execution time, in milliseconds, of the last (i.e. previous) script command. Start, Length are ignored for this data part.
EXECUTION_TIME_TOTAL Yes Yes Yes Gives the total execution time, in milliseconds, of the current script. Start, Length are ignored for this data part.
EXECUTION_TIME_EXTERNAL Yes Yes Yes Gives the total execution time, in milliseconds, for all operations that the current script has performed externally - including database calls, web service calls, XML BOD sends, and screen scraping operations. Start, Length are ignored for this data part.
IDLE_TIME Yes Yes Yes Gives the time, in milliseconds, that TC was idle before the current script began its execution. Start, Length are ignored for this data part.
Note:As of October 2004, TC now supports the command Use_Adjusted_Xact_Time which affects the values returned for the original transaction date and time data parts (e.g. YEAR, MONTH, DAY...) and for the XACT_AGE data part. For more information, please seeUse_Adjusted_Xact_Time.

This command and the date and time data parts with the ADJ prefix (e.g. ADJYEAR, ADJMONTH, ADJDAY, ...) are only available when both TC and the DCConnect Server are at versions from October 2004 or later.

Using Environment Variables in TC Commands

TC supports the use of environment variables in certain TC commands. An environment variable is specified by using opening and closing percent signs (%) around the environment variable name. For example:

For the following TC commands:

if one or more environment variables are specified as part of the file name parameter and that parameter is a literal string, TC will resolve the environment variable(s) at compile time. For example, if the following TC command is found in the script:
 
  Open_File_Data(uvRC, "%SystemRoot%\tc2out.log")
 
and the SystemRoot environment variable is defined to be C:\WINNT then at compile time TC will store the following for the file name to be opened:
 
  C:\WINNT\tc2out.log
 
and whenever this Open_File_Data command is executed, TC will always try to open that file.

TC will also look for environment variables in the command line parameter that is the top level script file name. However, chances are the operating system will have already resolved any environment variables that are specified on the command line; so TC will not have to do it.

For the commands:

the filename parameter may be a user variable or in the case of Open_File_Data, any data part. In this case, TC will look for environment variable(s) in the data part at execution time and will try to resolve them at that time.

The following commands:

which can be used to set / append literal strings or special control characters to TC user variables can also be used to set / append environment variable definitions to TC user variables. At compile time, if a Set / Append_UV_Kbd_Data (or Set / Append) command's second parameter starts and ends with a percent sign (%), TC will try to resolve the environment variable(s) and assign the result to the TC user variable. TC will not attempt to resolve environment variables for these commands if the second parameter is enclosed in double quotes.

Script Control Using If/Else

TC supports use of If-then-Else-then types of flow-of-control constructions, much like traditional programming languages. The If/Else construct can take many forms, and is best explained with some examples:

  // A simple If statement
  // Command A is executed only when the first 3 characters of
  // user variable 1 are equal to 'ABC'
  // Command B is always executed.
 
  If ( UV1(0, 3) == "ABC")
    Command A
 
  Command B
 
  // Execute several statements enclosed with braces if the
  // condition is true.  Again, Command B is always executed.
 
  If ( UV1(0, 3) == "ABC")
   {
    Command A
    Command AA
    Command AAA
   }
 
  Command B
 
  // Execute several statements enclosed with braces if the
  // condition is true.  This time, use Else to cause Command B
  // and Command BB to be executed only when the If condition was false.
 
  If ( UV1(0, 3) == "ABC")
   {
    Command A
    Command AA
    Command AAA
   }
  Else
   {
    Command B
    Command BB
   }
 
  // Nest several levels of Ifs and brace sets to structure the
  // flow of execution.
  // Execute commands A and AA when the first If is true; when
  // the second If is also true, execute commands AAA and AAAA.
  // Finally, drop through the Else statement and the statements
  // below it, until you get down to Command D (which is always executed).
  //
  // When the first If is false, skip down to the matching Else
  // statement and execute the third If statement -- if it is true,
  // execute commands B and BB, if it is false, execute
  // Command C.
  // Command D is always executed in this example.
 
  If ( UV1(0, 3) == "ABC")
   {
    Command A
    Command AA
    If ( UV2(0, 3) >= TIME(0, 6))
     {
      Command AAA
      Command AAAA
     }
   }
  Else
    If ( "1200" < TIME(0, 4) )
     {
      Command B
      Command BB
     }
    Else
      Command C
 
  Command D

When an opening brace { is the next statement after an If or Else, all commands between that opening brace and the matching closing brace belong to that If or Else statement. The statements that belong to an If or Else statement are executed whenever the If or Else condition is true.

If the next statement after an If or Else is a regular command (instead of an opening brace), only that command belongs to the If or Else. Subsequent commands either belong to a higher-level If or Else, or belong at the main level of your script.

You can have up to 50 levels of nested brace sets in effect at one time in your script.

For more information about the If statement please see If.

For information about using AND, OR and NOT operators in an If statment, please see Using AND, OR and NOT operators in If and While Statements.

Script Control Using Do...While

TC supports use of the Do...While type of flow-of-control constructions, much like traditional programming languages. For example, if you wanted to print 10 lines of underscore characters on a paper form for the worker, you could use If/Else logic:

    Append_UV_Kbd_Data( UV20, "___________________________________"
    UV_Math( UV1, =, 1 )
 
  PRINT_ANOTHER_LINE:
    Log_Data( REPORT, UV20, APPEND )
    UV_Math( UV1, +, 1)
    IF ( UV1 #<= "10")
      Goto PRINT_ANOTHER_LINE

Using Do...While logic saves some typing, and yields a more structured script:

  Append_UV_Kbd_Data( UV20, "___________________________________"
  UV_Math( UV1, =, 1 )
 
  Do
   {
    Log_Data( REPORT, UV20, APPEND )
    UV_Math( UV1, +, 1)
   }
  While ( UV1 #<= "10")

For more information about the While statement, please see While (Do...While).

For information about using AND, OR and NOT operators in an If statment, please see Using AND, OR and NOT operators in If and While Statements.

Using AND, OR and NOT operators in If and While Statements

As of November 2002, TC supports the use of the AND / OR / NOT operators (and their equivalents &&, &, ||, |, !) so that multiple comparison and logic operations can be performed in an 'If' or 'While' statement.

First a few quick examples:

 
  // Make sure the dimensions are valid.  Note the command
  // is split across multiple lines and comments are included
  // at the end of each of those lines.
  if ((uvRow #< "1") OR (uvRow #> "16")  OR   // Dimensions of
      (uvCol #< "1") OR (uvCol #> "20"))      // terminal are 16x20 
    Goto InvalidDimensions
 
  // This illustrates the use of multiple levels of comparison
  // prioritized using parentheses
  if (((UV1 == "1") and (UV2 == ")") and not (UV3 != "ABC") and (UV4 == UV14)) OR
     ((UV5 == UV6) and (UV7 == UV17)))
    Goto Error
 
  // The following loop should execute only 3 times
  Set_UV_Kbd_Data(uv50, "5")
  Set_UV_Kbd_Data(uv51, "Green")
  do
   {
    Log_Error("You should see this 3 times")
    UV_Math(uv50, -, 1)
    if (uv50 #== "2")
      Set_UV_Kbd_Data(uv51, "Red")
   }
  while ((uv50 #> "0") && (uv51 == "Green"))
 

The following statements describe what syntax rules must be followed when using these operators and describe how TC processes these statements.

Delimited Transaction Fields

TC can automatically parse your incoming transaction or request data area to extract ordered fields that are delimited by semi-colon characters. Using the delimiter characters allows you freedom from needing to maintain strict columnar alignments of your individual fields within the overall data area. You do not need to worry about having fixed-length formats for each read done by the operator, or having optional fields being skipped. As long as each field, whether filled-in or not, is delimited from the next field by a semi-colon, TC can find the correct data from the transaction or request.

The delimited fields are known in the TC scripts as TXNFIELD1 to TXNFIELD1024. Field 1 begins with the first character of the transaction or request data area, and continues up until the first semi-colon in the data area. The last field in the transaction or request must have a semi-colon separating it from the timestamp added by the DCT. Each empty field in the data must have a semi-colon delimiting it from the other fields. In short, the transaction program at the terminal should append a ";" character after each input is added to the transaction record.

  Field 1;Field 2;;Field 4 (3 was empty);...;Nth Field;
The COUNT_TXNFIELDS data part can be used to obtain the count of fields which TC has found in the current transaction. NEXT_TXNFIELD can be used to loop through all fields:
  //* Display the contents of each field
 
  //* Learn how many fields are in the txn
  Set_UV_Xact_Data( uvLOOPMAX, COUNT_TXNFIELDS, 0, 0 )
 
  UV_Math( uvLOOPCTR, =, 1 )
 
  //* Set the NEXT_TXNFIELD starting point
  //* while getting the data.
  Set_UV_Xact_Data( UV1, TXNFIELD1, 0, 0 )
 
  Do
   {
    //* Log to file as "FIELD x = field_data"
    Set_UV_Kbd_Data    ( UV2, "FIELD " )
    Append_UV_UV       ( UV2, uvLOOPCTR )
    Append_UV_Kbd_Data ( UV2, " = " )
    Append_UV_Xact_Data( UV2, UV1 )
 
    //* Don't go past end
    If ( uvLOOPMAX #> "1" )
      Set_UV_Xact_Data( UV1, NEXT_TXNFIELD, 0, 0 )
 
    UV-Math( uvLOOPCTR, +, 1 )
    UV_Math( uvLOOPMAX, -, 1 )
   }
  While ( uvLOOPMAX #> "0" )

Check_XXX Command Logic Modes

The various Check*us.XXX commands (Check_Screen, Check_II, etc.) require that you specify the logic style which you want to use when checking for a condition or text to be present/absent on the screen, as well as a time duration indicating the maximum number of seconds you want to wait for the condition to happen or go away.

The following table describes how the commands behave for the various combinations of logic style and timeout values:


Condition Timeout Behavior
FOUND 0 The host screen is inspected once and the result is 'true' if the specified text or condition is present
FOUND > 0 The host screen is inspected and the result is 'true' if the specified text or condition is present. If the text or condition is not present it delays 0.25 seconds and looks again. It repeats until either the text or condition becomes present or the maximum timeout expires. If the text or condition never appears then the result is 'false'.
NOT_FOUND 0 The host screen is inspected once and the result is 'false' if the specified text or condition is present -- or in other words the result is 'true' if the text or condition is not present.
NOT_FOUND > 0 The host screen is inspected and the result is 'false' if the specified text or condition is present upon first inspection. If the text or condition is not present it delays 0.25 seconds and looks again. If the timeout duration expires and the specified text or condition is still not present then the result is 'true'. If the text or condition becomes present at any time up until the timeout then the result is 'false'. In other words, the command will make sure the text or condition is not there and that it does not appear for some time as it watches.
NOT_FOUND_IMMED 0 The host screen is inspected once and the result is 'false' if the specified text or condition is present -- or in other words the result is 'true' if the text or condition is not present upon first inspection.
NOT_FOUND_IMMED > 0 The host screen is inspected and the result is 'true' if the specified text or condition is not present upon first inspection. If the text or condition is present it delays 0.25 seconds and looks again. If the timeout duration expires and the specified text or condition is still present then the result is 'false'. If the text or condition goes awy at any time up until the timeout then the result is 'true'. In other words, the command will wait for the text or condition to go away, and as soon as it is not present it will return 'true'.


Web Services

TC may be used to service requests for web services (provide), or create requests for web services (consume). For example, TC may provide other applications with access to the ERP system by exposing a web service, or may connect a data collection terminal to a remote web service.

TC provides an extension to Microsoft Windows Internet Information Server (IIS) that, with proper configuration, allows incoming HTTP requests to be routed to specific TC sessions. IIS is configured to use a TC function to handle the HTTP request if the URL includes a segment that ends with the extension ".tcws" (e.g. CreateOrder.tcws ) and the URI points to the IIS virtual directory where TC is installed (the 'TCWS' segment in the URI "http://127.0.0.1/TCWS/....")

TC can provide web services that are accessed by clients via:

TC can also create and send requests to web service provided by any other endpoint ('consume' web services). Again, this request can be made in either the SOAP XML format or a RESTful format, and the response can be in SOAP XML, plain XML, JSON, HTML, or plain text.

See the examples below.

Web Services Setup

Regardless of whether your TC scripts will be consuming and/or providing web services, the following steps must be done in order to define those web services for TC.

  1. Create the tc2.exe.config file. You have a choice of two different methods for telling TC which web services it needs to be able to consume or provide:

    1. Using an XML file
    2. Using a database table

    TC is told of the method you have chosen via the tc2.exe.config file. This file should be created in the same directory that contains TC2.EXE (typically C:\dcconn\tc). The tc2.exe.config is used by all TC sessions.

    Below are examples of this file for each method:

    1. Using an XML file. In this case the tc2.exe.config file will use the key WSDLXMLPath to specify the full path and name of the XML file:
                  <?xml version="1.0" encoding="utf-8" ?>
                  <configuration>
                      <appSettings>
                          <add key = "WSDLXMLPath" value = "c:\wsdl.xml" />
                      </appSettings>
                  </configuration>
                  
      In the example above the XML file is C:\wsdl.xml. Below is an example of this file containing a single web service definition for the Twitter web service. Each of these parameters will be explained in the table below.
                  <?xml version="1.0" encoding="utf-8" ?>
                  <configuration>
      
                    <!-- List of Web Services -->
      
                    <!-- "TwitterXML","REST","GET","XML","","",0,0 -->
                    <WSDL>
                      <NAME>TwitterXML</NAME>
                      <WSTYPE>REST</WSTYPE>
                      <METHOD>GET</METHOD>
                      <RESPONSETYPE>XML</RESPONSETYPE>
                      <TARGETNAMESPACE></TARGETNAMESPACE>
                      <SOAPACTION></SOAPACTION>
                      <PORT>0</PORT>
                      <TWCS_RESPONSE_SECS_MAX>0</TWCS_RESPONSE_SECS_MAX>
                    </WSDL>
      
                  </configuration>
                  
      If you have multiple web services to define, then the <WSDL> section should be repeated for each of those web services.

    2. Using a database table. In this case the tc2.exe.config file will use the keys connectionString, schema and table to specify the database and table that contains the web service definitions. Set the data source name (dsn) per the Windows ODBC data source you have already created. Note that if you saved the password with the Windows data source you can remove the uid and pwd pieces of information from the config file. Set the database schema and table name as appropriate.
                  <?xml version="1.0" encoding="utf-8" ?>
                  <configuration>
                      <appSettings>
                  	    <add key = "connectionString" value = "dsn=oDCLIBdb2;uid=myuser;pwd=mypw;"/>
                          <add key = "schema" value = "DCLIB"/>
                  	    <add key = "table" value = "WSDL"/>
                      </appSettings>
                  </configuration>
                  
  2. Create the database table or .XML file and populate them with the parameters for each Web Service.

    If using a database table, you will have one record per web service in that table. If using the XML file, you will have one <WSDL> section in that XML file for each web service. The set of parameters are named the same in either case.

    The first column in the table below is the parameter name in the XML file if you are using that method. But it is the database column name in your table if you are using that method. The second column in the table below specifies the data type and applies only if you are using a database table. The last column in the table below describes the parameter usage, regardless of whether it came from an XML file or database table:

    XML parameter / database column NameData TypeDescription of Use
    NameVARCHAR(25) Primary KeyName of the web service. In the incoming web service request, this is the "filename" in front of the ".tcws" extension in a segment of the URL. In this RESTful request, "http://127.0.0.1/TCWS/TestRest.tcws/testing.xml?x=ThisIsXValue&y=8.12&zzzzz=ZZZZZ", the name would be "TestRest" (case sensitive). Or in this SOAP request, "http://localhost/TCWS/CreateOrder.tcws", the name would be "CreateOrder"
    WSType VARCHAR(25) For a web service that is provided by TC, this is the expected type of incoming request for the web service name. For a web service request created by TC (i.e. WS_CreateRequest) this is the request type expected by the provider. This may be one of the values "SOAP" or "REST" -- no other types are supported.
    Method VARCHAR(12) The HTTP Request Method to use in a web service request created by TC (only used in WS_CreateRequest / WS_SendRequest). This can be be "GET", "PUT", "POST", "DELETE" or "OPTION". For SOAP requests this is generally 'GET'. For REST requests the method is often used as a verb with specified meaning per the particular web service (with PUT/POST/DELETE often for requests that affect data on the server, and 'GET' for inquries that leave no effect
    ResponseType VARCHAR(12) To specify what type is response is expected by TC when it sends a request, or what type of response it should formulate when replying to a reqeust. This can be SOAPXML (XML with the specific SOAP schema), XML, JSON (Javascript Object Notation), HTML, or TEXT.
    TargetNamespace VARCHAR(128) Specifies the "tns" namespace for incoming and outgoing XML messages.

    Use of this data element is optional. For namespaces, use of the WS_DefineNamespace and/or WS_AddAttribute commands is advised because of the increased flexibility and clarity.

    This can be used for SOAP messages and is taken from the WSDL (Web Services Definition Language) file provided by the web service provider. Search in the WSDL XML file for 'targetNamespace="http://something.something/"' and copy the 'http://..../' URL (including trailing slash) to this column of the table. This namespace is used to give meaning to the "tns:" prefix that TC uses to give namespace meaning to the application-specific fields in a SOAP message that it creates, and is used to give meaning to whatever default namespace prefix is used on SOAP messages that arrive from outside of TC.

    For parsing of simple XML responses that come back to TC from other web service provides, this column may be set to an empty string ('').

    For simple XML responses created by TC, set this to any unique 'http://..../' URL (it does not need to actually exist) and refer to it in WS_CreateElement / WS_SetElement commands using the standard "tns:" prefix.

    SOAPAction VARCHAR(128) This is the SOAPAction that is included in the header of outgoing SOAP web service requests that are created by TC. This is needed only for SOAP message request creation. Get the value from the SOAP WSDL document provided by the web service. Search for the SOAPAction that represents the desired web service operation in the SOAP format (e.g. look for '<soap:operation' and copy the soapAction value, such as soapAction="http://tempuri.org/ShowOrder")
    PORT INTEGER This is the local port number to use in communications between the IIS web server and TC. The value is used only for web services PROVIDED by the local TC sessions(s) and must be a unique integer for each of those services (use a number not in use for any other service on the computer). For web service names that are only called from TC sessions you can use any value and they do not need to be unique amount rows in the table (so, 0 is suggested).
    TWCS_Response_Secs_Max INTEGER Set to how many seconds the Local IIS web server should allow for a response to be returned from the TC session that serves a web service name. This is not used when TC calls a remote web service.

    If you are creating a database table, the SQL to create this table is similar to:

    CREATE TABLE "DCLIB.WSDL"  ( NAME VARCHAR(25) NOT NULL , WSType VARCHAR(25), Method VARCHAR(12), ResponseType VARCHAR (12), TargetNamespace VARCHAR(128) , SOAPAction VARCHAR(128),
    PORT integer, twcs_response_secs_max integer, PRIMARY KEY (NAME) ) 
    

If TC will be providing web services, then two additional steps must be performed:

  1. Create web.config to inform all web service "provider" TC sessions where to get information about the web service each will handle - in the same way that tc2.exe.config is used for "consumer" TC sessions. Adjust the dsn, schema, and table as was done for the tc2.exe.config file above. Likewise, the WSDLXMLPath keyword can be used instead of the database parameters.

    web.config should be created in the same directory that contains TC2.EXE and tc2.exe.config (typically C:\dcconn\tc). Here is a sample web.config file:

                <?xml version="1.0" encoding="utf-8" ?>
                <configuration>
                  <appSettings>
                	<add key = "connectionString" value = "dsn=oDCLIBdb2;uid=myuser;pwd=mypw;"/>
                	<add key = "schema" value = "DCLIB"/>
                	<add key = "table" value = "WSDL"/>
                  </appSettings>
                </configuration>
                
    Note: Previous versions of these instructions included a <system.webServer> and <handlers> element in the web.config contents above. Instead the handler definition is now set up in the IIS configuration steps below.

  2. Configure IIS. Microsoft Internet Information Services must be configured to be able to use TC's WebServiceHandler.dll to handle incoming requests for web services.

    1. If you do not already have an Application Pool that is set to use .NET Framework v2.0.50727 and 'Integrated' managed pipeline mode then add a new pool with these attributes (Basic Settings) and call it something like 'DCC32'. This application pool must also be set to allow 32-bit applications (Advanced Settings, General section). And, if it is not already set, make sure the Identity is set to LocalSystem in the Process Model section, also in Advanced Settings.

      Note: While 'Integrated' is the recommended request-processing mode, 'Classic' mode can work as well.

    2. Create a new web site and set its name to DCCpp, for example, where 'pp' is the port number that you will use. For this example, we'll use port 88 and so the web site will be called DCC88.

      Set the physical path to the default which is typically c:\inetpub\wwwroot and set the port to 88 or to whatever number you have chosen.

      Also set the application pool to DCC32 or whatever one you have that has been created with the settings described in the previous step.

      Finally, set up the connection user ID and password as needed.

    3. Create a new virtual directory under the web site that you created in the previous step. Name the virtual directory something like 'TCWS' and point it to the C:\DCCONN\TC directory (or wherever your Transaction Connection is installed). The virtual directory name you choose (e.g. TCWS) will become part of the URI / endpoint for the web services provided by TC. For example:

      • http://127.0.0.1:88/TCWS/ValidateUser.tcws?userid=JohnDoe&pw=4d103f3e229402f325ea12784c42198d

    4. IIS needs to be told that TC's WebServicesHandler.dll is the handler for all URLs with a ".tcws" extension. For example:

      • http://127.0.0.1:88/TCWS/ValidateUser.tcws?userid=JohnDoe&pw=4d103f3e229402f325ea12784c42198d

      For the same web site created above, use the Handler Mappings option in the IIS section to Add a Managed Handler with the following initial parameters:

      • Request path: *.tcws
      • Type: WebServiceHandler.clsIISExtension
      • Name: TC web service

      And the following Request Restrictions:

      • Mapping: uncheck “Invoke handler only if …”
      • Verbs: select All verbs
      • Access: Script

      IIS stores the above settings in a file called web.config but it is in the c:\inetpub\wwwroot folder. The contents of that folder will look something like:

              <?xml version="1.0" encoding="utf-8" ?>
              <configuration>
                 <system.webServer>
                    <handlers>
                       <add verb="*" path="*.tcws" type="WebServiceHandler.clsIISExtension" resourceType="Unspecified"/>
                    </handlers>
                 </system.webServer>
              </configuration>
              
      Note: In previous versions of these instructions, the above <handlers> definition was included in the web.config that was created in the c:\dcconn\tc folder. In fact, that <handlers> definition could be in either web.config (but not both) and things would work. But only the one in the c:\inetpub\wwwroot folder is managed by the IIS user interface that is used for configuring handlers and other web service settings.

    5. Register the DLL: The installation of TC should have automatically taken care of this step. However, if you get an error popup from TC when your script is attempting to execute a web service-related command (e.g. WS_CreateRequest, WS_CreateResponse) then you may need to register this .DLL manually:

      From the directory where TC's WebServiceHandler.dll resides (e.g. C:\DCCONN\TC\BIN) run the .bat file:

       regtcweb.bat
                  
      This .bat file performs the following commands for you.
       %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm.exe /unregister /tlb WebServiceHandler.dll
       %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb WebServiceHandler.dll
       %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm.exe /codebase WebServiceHandler.dll
                  
      Note that on the last command you may get a warning about registering an unsigned assembly and strong naming; this can be ignored.

      Also note that if you ever get an update to the TC program, which is usually provided as a .zip file to update the c:\dcconn\tc directory, then the regtcweb.bat file needs to be rerun after installing that TC update, so that the new version of the WebServiceHandler.dll is registered.

    6. Make sure you have created the web.config file described in step 1 above and then stop and restart the IIS web site that you created (e.g. DCC88)

    7. Now that the web site is restarted, the web.config file should have been read which in turn should have registered the *.tcws extension. Verify this by selecting the Virtual Directory that you added above (e.g. TCWS) and then looking at the Handler Mappings for the path *.tcws. It should have the following parameters:

      • Executable: C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
      • Name: Transaction Connection
      • Verbs: All verbs
      • Access: Execute

    8. The WebServiceHandler.dll may also need to be copied to other locations in order for IIS to find it. If IIS cannot find this .DLL there will likely be an entry in the Windows Event Viewer, in the Application section of the Windows Logs when an attempt is made to call any TC provider web service. Try any of the following locations (but always keep it wherever TC is installed no matter where it is copied):

      • c:\inetpub\wwwroot\bin
      • c:\inetpub\wwwroot
      • c:\dcconn\tc\bin (or .\bin under wherever TC is installed)

Web Service Examples

See the following examples: Note: If a TC session is running in the mode where it displays each step of script execution on its window (see Menu Bar - Display) then it will also display any outgoing or incoming web service request, as well as information about current XML document navigation during WS_EnterElement command execution. This is helpful for debugging, but the modal pop-up windows are disruptive so you will generally want to run with the display mode turned off.

Call a SOAP Web Service

This TC subroutine will call a commercial stock quotation service to obtain the current IBM stockprice. The web service table entry looks like this:
NameWSTypeMethodResponseTypeTargetNamespaceSOAPActionPortTWCS_ Response_ Secs_ Max
'Quote''SOAP''POST''SOAPXML'(Leave this empty - define via script commands!)'http://www.xignite.com/services/GetGlobalDelayedQuote'00
Note that the Method has been set to POST per the requirements of the web service provider; the response is expected to be in SOAPXML format; the TargetNamespace has been set per the value found in the WSDL document provided by the web service; the port value and timeout are not used when TC consumes a service, so 0 is used by convention.
Sub CallWS()

   // Form this SOAP request to obtain the stock price for IBM:
   //  <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance/" xmlns:xsd="http://www.w3.org/2001/XMLSchema/" 
   //    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:qns="http://www.xignite.com/services/">
   //  <soap:Header>
   //     <qns:Header>
   //        <qns:Username>hornern@us.ibm.com</qns:Username>
   //        <qns:Password>Fred</qns:Password>
   //        <qns:Tracer>?</qns:Tracer>
   //     </qns:Header>
   //  </soap:Header>
   //  <soap:Body>
   //     <qns:GetGlobalDelayedQuote>
   //        <qns:Identifier>IBM</qns:Identifier>
   //        <qns:IdentifierType>Symbol</qns:IdentifierType>
   //     </qns:GetGlobalDelayedQuote>
   //  </soap:Body>
   //  </soap:Envelope>

   Declare (handle)
   Declare (rc)
   Declare (RespHandle)
   Declare (outValue)
   Declare ( CurrTS )
   
   Set_UV_Data_Part( CurrTS, CURRENT_TIMESTAMP, 0, 0 ) 

   Declare( WSName )
   Set_UV_Kbd_Data( WSName, "Quote" )
   
   // Initialize a SOAP XML document with the targetNamespace found in the local 
   // web services table under  name 'Quote'.  
   // This will form the shell of the SOAP XML as shown below and associate 
   // with the handle returned in 'handle' UV.
   // 'The Name Space' qns: is set to the targetNamespace
   //  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...xmlns
   //     :qns="http://www.xignite.com/services/">
   //  <soap:Header>
   //  </soap:Header>
   //  <soap:Body>
   //  </soap:Body>
   //  </soap:Envelope>
   WS_CreateRequest(handle,WSName, rc)
                        

   // At this point our WS XML navigation is pointed at the soap:Envelope node.  
   
   // Add a custom namespace attribute to the soap_Envelope using the special prefix "xmlns:" 
   WS_AddAttribute( handle, "xmlns:qns", "http://www.xignite.com/services/", rc ) 
                        
   // Put qns:Header section in soap:Header and populate with userid, password    
   
   // Navigate to soap:Header as the current node             
   WS_EnterElement(handle,"soap:Header", 1, rc) 
   
   // Create qns:Header inside of soap:Header
   WS_CreateElement(handle, "qns:Header", rc)      
   
   // Make qns:Header the current node
   WS_EnterElement( handle, "qns:Header", rc )
   
   If( rc #<> 0 )
     Log_Error("Did not create/enter qns:Header!", ERROR ) 
   
   // Inside of qns:Header create and populate 3 nodes
   WS_SetElement( handle, "qns:Username", 1, "hornern@us.ibm.com", rc )     
   WS_SetElement( handle, "qns:Password", 1, "Frred", rc )     
   WS_SetElement( handle, "qns:Tracer", 1, "myTracer", rc )     
      
   WS_LeaveElement( handle, rc ) //  Backup one to soap:Header                                                                       
   WS_LeaveElement( handle, rc ) //  Backup one to soap:Envelope 
   
   // Done building Header 
   
   // Make soap:Body the current node
   WS_EnterElement(handle,"soap:Body", 1, rc)  // Enter soap:Body, hopefully
   
   // Create node and make it current
   WS_CreateElement(handle,"qns:GetGlobalDelayedQuote", rc)  
   WS_EnterElement(handle,"qns:GetGlobalDelayedQuote", 1, rc)

   // Create and then set Identifier 
   // (Note: Could be done simply with WS_SetElement as above)
   WS_CreateElement(handle,"qns:Identifier", rc)
   // WS_SetElement (handle, param name, [occurrence, ] field value, return code)
   WS_SetElement    (handle, "qns:Identifier",   1,           "IBM",       rc)
   
   // Create and set Identifier type
   WS_CreateElement(handle,"qns:IdentifierType", rc)
   WS_SetElement(handle,"qns:IdentifierType",1,"Symbol", rc)    
   
   // Log the SOAP XML doc we are about to send 
   WS_ToFile( handle, "%TC2%\soaprequest.xml", rc ) 
	
   // Send the web service request, waiting up to 30 seconds for response
   // 	
   WS_SendRequest(handle, "http://www.xignite.com/xGlobalQuotes.asmx", rc, RespHandle, 30 )        
   
   If( rc #== 0 )
   { 
       // Tell the parser we will find the reply elements of namespace "http://www.xignite.com/services/" 
       // via our chosen prefix 'rqns':  
       WS_DefineNamespace( RespHandle, "http://www.xignite.com/services/", "rqns", rc )   
       
       // Log the SOAP XML response we received
       WS_ToFile( RespHandle, "%TC2%\soapresponse.xml", rc ) 
       
       // Navigate into result part of response XML  
       
       // Note:  Already positioned at soap:Envelope node, so this will fail harmlessly
       WS_EnterElement( RespHandle, "soap:Envelope", rc )  
       
       // Navigate into soap:Body and then into ...Response and ...Result sections
       WS_EnterElement( RespHandle, "soap:Body", rc )
       WS_EnterElement( RespHandle, "rqns:GetGlobalDelayedQuoteResponse", rc ) 
       WS_EnterElement( RespHandle, "rqns:GetGlobalDelayedQuoteResult", rc ) 
        
       // Get the rqns:Last price 
       WS_GetElement (RespHandle, "rqns:Last", 1, outValue, rc)
       
       Log_Error( "Success!", INFO ) 
       Log_Error( outValue, INFO ) 
   }
   Else
   {
       Log_Error( "Failed to get response", ERROR )
   }
   
   // Must destroy handles so they can be re-used.  Failure to destroy will 
   // 'leak' handles and eventually run out / stop working.
   WS_Cleanup (handle)
   WS_Cleanup (RespHandle)
   


EndSub()

Provide a SOAP Web Service

This TC subroutine will provide a SOAP web service to create a new sales order. The web service table entry looks like this:
NameWSTypeMethodResponseTypeTargetNamespaceSOAPActionPortTWCS_ Response_ Secs_ Max
'CreateOrder''SOAP''PUT''SOAPXML''http://someuri.org/' (We will let TC automatically create the "tns" namespace in the soap:Envelope element)'http://someuri.org/CreateOrder'905030
Note that port 9050 is dedicated to this web service for communication between IIS and the TC session that handles this web service. IIS will wait up to 30 seconds after forwarding an incoming request to TC (via port 9050) for that TC session to return a response.
Start_WS ("CreateOrder", gHandle)

   Declare (varA)
   Declare (varB)
   Declare (outHandle)
   Declare (rc)
   Declare ( OrderID )
   Declare ( OrderDate )
   Declare ( Qty)
   Declare ( Price ) 
   Declare ( ItemID ) 
   Declare ( ItemName ) 
   Declare ( OrderLineID)
   Declare ( CurrTS )
   Declare ( Method ) 
   Declare ( RequestHost ) 
   
   Log_Error( "Processing CreateOrder ", INFO ) 
   
   Set_UV_Data_Part( CurrTS, CURRENT_TIMESTAMP, 0, 0 ) 
   
   // Upon start-up of this scriptlet, the incoming SOAP XML
   // has been stored under the handle saved in gHandle.  The current
   // node is automatically set to the soap:Envelope node, so we can
   // navigate directly into the HTTPRequest element:
   
  
   WS_EnterElement( gHandle, "HTTPRequest", 1, rc )  
   WS_GetElement( gHandle, "Method", Method, rc ) 
   WS_GetElement( gHandle, "Host", RequestHost, rc ) 
   
   if( Method <> "POST" )
   {
       // Do something else, like return FAULT message and lot
       // bad request from the RequestHost
   }
   
   WS_LeaveElement( gHandle ) // Return to soap:Envelope node
   
   WS_EnterElement(gHandle,"soap:Body", 1, rc)
   
   // Navigate into the default namespace's CreateOrder section.
   WS_EnterElement(gHandle,"tns:CreateOrder", 1, rc)

   // Get some values that are in the 'tns:' default namespace
   WS_GetElement (gHandle, "tns:orderID", OrderID, rc)
   WS_GetElement (gHandle, "tns:orderDate", OrderDate, rc)
   WS_GetElement (gHandle, "tns:orderLineID", OrderLineID, rc)
   WS_GetElement (gHandle, "tns:qty", Qty, rc)
   WS_GetElement (gHandle, "tns:price", Price, rc)
   WS_GetElement (gHandle, "tns:itemID", ItemID, rc)
   WS_GetElement (gHandle, "tns:itemName", ItemName, rc ) 
   
   // Create a reponse message, referenced by outHandle.
   // Based on ResponseType in the web services table, this creates
   // a SOAP XML message with empty soap:Header and soap:Body elements.
   WS_CreateResponse (gHandle, outHandle)
   
   // Enter the soap:Body and create a hierarchy of sections
   // tns:CreateOrderResponse and its child tns:CreateOrderResult
   WS_EnterElement( outHandle, "soap:Body", 1, rc )

   WS_CreateElement(OutHandle,"tns:CreateOrderResponse", rc);
   WS_EnterElement( outHandle, "tns:CreateOrderResponse", rc ); 
   
   WS_CreateElement(OutHandle,"tns:CreateOrderResult", rc)
   WS_EnterElement( outHandle, "tns:CreateOrderResult", rc ); 
   
   // Create then set a value
   WS_CreateElement(OutHandle,"tns:orderID", rc)
   WS_SetElement (outHandle,"tns:orderID",1, OrderID, rc)
   
   // Create AND set a value in one step
   WS_SetElement (outHandle,"tns:price",1, Price, rc)
   
   // Retreat back to tns:CreateOrderResponse 
   WS_LeaveElement( outHandle, rc )
   
   // Create and set tns:Trash is tns:CreateOrderResponse 
   WS_SetElement (outHandle,"tns:Trash",1, CurrTs, rc)

   // Send our response and clean-up
   WS_SendResponse (outHandle)

   WS_Cleanup (outHandle)
   WS_Cleanup (gHandle)
   
   // All done serving this request
   
End_WS ()


Call a RESTful Web Service

This TC subroutine will use the Twitter REST web service API to read the status of a Twitter user into an XML document that is returned. The web service table entry looks like this:
NameWSTypeMethodResponseTypeTargetNamespaceSOAPActionPortTWCS_ Response_ Secs_ Max
'TwitterXML''REST''GET''XML'''''00
Note that the WSType is set to 'REST' so no SOAP XML document is created by the WS_CreateRequest call. Since the request is not XML there is no data needed for the TargetNamespace. There is no SOAPAction as the request is not SOAP. The port is not used because this TC only does requests for this web service. The timeout is not used because on a WS_SendRequest you set the timeout (how long you will wait for reply) in the command.
Sub CallTwitter()

   Declare (handle)
   Declare (rc)
   Declare (RespHandle)
   Declare (outValue)
   Declare ( CurrTS )
   Declare ( URL ) 
   Declare ( Timeout )
   Declare ( Occur )
   Declare ( Sect ) 
   
   Set_UV_Data_Part( CurrTS, CURRENT_TIMESTAMP, 0, 0 ) 

   WS_CreateRequest(handle,"TwitterXML", rc)
 
   UV_Math( Timeout, =, 4, 0.0 )
   
   // Ask for statuses for user NealHorner.  
   // The URI segment 'user_timeline.xml' tells Twitter we want an 
   // XML document as a response (we could change to .JSON to get JSON style)
   Set_UV_Kbd_Data( URL,  "http://twitter.com/statuses/user_timeline.xml?id=NealHorner" )   
   
   // Send the request and get the response in handle RespHandle.
   // Any error message can be returned in glLarge2 user variable. 
   WS_SendRequest(handle, URL, rc, RespHandle, Timeout, glLarge2 )   
   
   If( rc #== 0 )
   {   
       // Enter the 2nd occurrence of the status element in the response
       UV_Math( Occur, =, 2 );
       Set_UV_Kbd_Data( Sect, "status" );
       WS_EnterElement( RespHandle, Sect, 2, rc ) 
      
       // Get some values
       WS_GetElement (RespHandle, "text", 1, glLarge2, rc) 
       Log_Error( glLarge2, INFO ) 
      
       WS_GetElement (RespHandle, "user", 1, glLarge2, rc) 
       Log_Error( glLarge2, INFO ) 
       
       WS_EnterElement( RespHandle, "user", 1, rc )
       
       UV_Math( Occur, =, 1 )
       WS_GetElement (RespHandle, "name", Occur , glLarge2, rc) 
       Log_Error( glLarge2, INFO ) 
      
   }
   
   WS_Cleanup (handle)
   WS_Cleanup (RespHandle)

EndSub()

Provide a RESTful Web Service

This TC Start_WS will provide a RESTful web service that does some processing and returns an XML message. The web service table entry looks like this: 'TestRestX', 'REST', 'GET', 'XML', 'http://ibmdc.com/', '', 9072, 30 );
NameWSTypeMethodResponseTypeTargetNamespaceSOAPActionPortTWCS_ Response_ Secs_ Max
'TestRestX''REST''GET''XML''http://ibmdc.com/'''905530
Note that port 9055 is dedicated to this web service for communication between IIS and the TC session that handles this web service. IIS will wait up to 30 seconds after forwarding an incoming request to TC (via port 9055) for that TC session to return a response. Note that a TargetNamespace distinctive (but arbitrary) URL is provided to define the 'tns:' default namespace for the document that is created.

To test this web service, run this from a browser:
http://127.0.0.1/TCWS/TestRestX.tcws/testing.xml?x=ThisIsXValue&y=8.12&zzzzz=ThisIsZValue

Note that some segement of the URI must contain the text extension ".tcws" so that IIS can route the reqeust to Transaction Connection. The ".tcws" extension can be in any segment (so this will also work:
http://127.0.0.1/TCWS/AnotherSegment/TestRestX.tcws/testing.xml?x=ThisIsXValue&y=8.12&zzzzz=ThisIsZValue

// Catch REST request and respond with XML 
// To Test, use this in browser address bar: http://127.0.0.1/TCWS/TestRestX.tcws/testing.xml?x=ThisIsXValue&y=8.12&zzzzz=ThisIsZValue
Start_WS ( "TestRestX", gHandle)

   Declare( RespHandle )
   Declare( rc ) 
   Declare( Method )
   Declare( Seg )       
   Declare( Value )
   Declare( XValue ) 
   Declare( RespHTML )
   Declare( TestResult )  
   Declare( CurrTS )
   
   Set_UV_Data_Part( CurrTS, CURRENT_TIMESTAMP, 0, 0 )  
   
   // Note that an incoming REST request is automatically parsed by TC
   // into an XML document that looks like this, and the current node
   // is set to the RestRequest element.
   // <RestRequest>
   //  <Method>GET</Method>
   //  <Host>127.0.0.1</Host>
   //  <User-Agent>Mozilla/5.0...</User-Agent>
   //  ... other header values ...
   //  <URI_Segment>TCWS</URI_Segment>
   //  <URI_Segment>TestRestX.tcws</URI_Segment> 
   //  <URI_Segment>testing.xml</URI_Segment>        
   //  <QueryString>
   //    <x>ThisIsXValue</x>
   //    <y>8.12</y>
   //    <zzzzz>ThisIsZValue</zzzzz>
   //  </QueryString>
   // </RestRequest>   
   
   // Obtain the incoming Method used by the web service caller.
   // This might be used to decide what kind of action to take.
   WS_GetElement ( gHandle, "Method", Method, rc )   
  
   // Get each URI_Segment value in turn.  There are only
   // 3, so the 4th try will return -1.                                                
   WS_GetElement ( gHandle, "URI_Segment", 1, Seg, rc )   
    
   WS_GetElement ( gHandle, "URI_Segment", 2, Seg, rc )   
       
   WS_GetElement ( gHandle, "URI_Segment", 3, Seg, rc )  
   WS_GetElement ( gHandle, "URI_Segment", 4, Seg, rc )     
   
   // Navigate into the QueryString area
   WS_EnterElement ( gHandle, "QueryString", rc )     
    
      // Obtain each of the expected query string values
      WS_GetElement ( gHandle, "x", XValue, rc )  
        
      WS_GetElement ( gHandle, "y", 1, Value, rc )  
       
      WS_GetElement ( gHandle, "zzzzz", 1, Value, rc )    
      
   WS_LeaveElement( gHandle )            
    
   // Create a response to the request.  Because the ResponseType is 
   // set to 'XML' this creates an empty XML document
   WS_CreateResponse( gHandle, RespHandle ) 
   
   // This creates the first element in the XML response and sets
   // the current node to this element.  
   // Note that the response is formulated around the default 
   // namespace "tns:" (that resolves to http://ibmdc.com/ per the
   // web services table)
   WS_CreateElement ( RespHandle, "tns:Answer", rc )
  
      // Create an element 
      WS_CreateElement( RespHandle, "tns:XvalueIs", rc )
      
      // Set that element
      WS_SetElement( RespHandle, "tns:XvalueIs", 1, XValue, rc )
       
      // Create and set some elements:
      WS_SetElement( RespHandle, "tns:XvalueIs", 2, "AnotherX", rc )
        
      WS_SetElement( RespHandle, "tns:XvalueIs", 3, CurrTS, rc )
       
   WS_LeaveElement( RespHandle )
   
   // Send the response
   WS_SendResponse( RespHandle )
   
   WS_Cleanup ( gHandle )
   WS_Cleanup ( RespHandle )
   
End_WS()


Note that this scriptlet could easily reply with an HTML document or a JSON string:

Logon and Logoff Scripts

After connecting to the host session, or connecting to the database, TC will run the StartLogon script, if it is defined. This gives you an opportunity to initialize user variables or perform other operations that must be done before any transactions/requests are processed.

Likewise, before TC shuts down or terminates the host or database connection, it will run the StartLogff script, if it is defined.

The following is how Logon and Logoff commands blocks can be organized.

  StartLogon ()
  EndLogon ()
 
  StartLogoff ()
  EndLogoff ()
 
  StartKey( F1 )
  EndKey()

SQL Statement Generation

TC has commands that allow you to create general INSERT, UPDATE, and SELECT SQL statements with properly formatted data from your transactions. You do not need to know much about SQL and databases to be up and running with your application. The following sections describe how these SQL statements are created by the commands, and shows the form of the SQL statement.

When you find the need for a more flexible method of creating the SQL statement, you can use the free-form SQL input method, described in Free-Form SQL Statements. The formats shown for the insert, update, and select statements created from commands are a useful quick-reference for creating these types of statements with free-form SQL.

Insert Statement

TC uses the commands Insert_DB_Table, Setup_Insert_Field, and Perform_Insert to create a general INSERT statement of the form:

  INSERT INTO QUALIFIER.TABLENAME                         (1)
    (COLUMN_NAME_1, COLUMN_NAME_2,..., COLUMN_NAME_N)     (2)
  VALUES                                                  (3)
    (VALUE_1, VALUE_2,..., VALUE_N)                       (4)

The command Insert_DB_Table creates line 1 of the statement, while command Setup_Insert_Field creates lines 2, 3, and 4. Setup_Insert_Field can be called multiple times to set up as many as 255 column names with associated values. The values may be constants, data from parts of the transaction, data from user variables, or database special registers (for example, CURRENT TIME, CURRENT DATE, and so forth). Perform_Insert terminates the list of column names and values and causes the SQL statement to be performed.

See Inserting a Record into a Table for an example of using these commands.

Update Statement

The commands Update_DB_Table, Setup_Update_Field, Update_Where, and Perform_Update are used to create a general UPDATE statement of the form:

  UPDATE QUALIFIER.TABLENAME                             (1)
    SET COLUMN_NAME_1 = VALUE_1                          (2)
    SET COLUMN_NAME_2 = VALUE_2                          (3)
    SET COLUMN_NAME_N = VALUE_N                          (N)
  WHERE COLUMN_NAME_X comparison VALUE_X                 (N+1)

The command Update_DB_Table creates line 1 of the statement, while command Setup_Update_Field creates lines 2, 3, and to line N. Setup_Update_Field can be called multiple times to set up as many as 255 column names with associated values. The values can be constants, data from parts of the transaction, data from user variables, data from another column in the row, or database special registers (for example, CURRENT TIME, CURRENT DATE, and so forth). Update_Where creates the last line (N+1), which specifies the row conditions where the columns should be updated. Perform_Update causes the SQL statement to be performed.

See Updating a Record in a Table for an example of using these commands.

Select Statement

The commands Select_From_DB_Table, Select_Column, Select_Where, Select_Having, Select_Group_By, Select_Order_By, and Perform_Select create a general SELECT statement of the form:

  SELECT COLUMN_1, COLUMN_2,... COLUMN_N           (1)
    FROM QUALIFIER.TABLENAME                       (2)
    [WHERE COLUMN_X comparison VALUE_X]            (3)
    [GROUP BY COLUMN_Y]                            (4)
    [HAVING COLUMN_Z comparison VALUE_Z]           (5)
    [ORDER BY COLUMN_W]                            (6)

The command Select_From_DB_Table creates line 2 of the statement, while command Select_Column creates line 1. Select_Column can be called multiple times to set up as many as 255 column names or column operations (for example, SUM, MAX, and so forth). Select_Where creates line 3, which specifies the row conditions where the columns should be selected. Select_Group_By, Select_Having, and Select_Order_By create lines 4, 5, and 6, respectively. All lines in brackets ([]) are optional.

The values can be constants, data from parts of the transaction, data from user variables, or database special registers (for example, CURRENT TIME, CURRENT DATE, and so forth)

Perform_Select causes the SQL statement to be performed.

See Querying the Database Table for an example of using these commands.

Free-Form SQL Statements

You can create and execute any valid SQL statement that can be dynamically performed. If using IBM DB2, refer to the online SQL Reference for guidance on SQL statements and on which commands can and cannot be performed dynamically. If using ODBC to connect to other database types, refer to the documentation provided with the database software. Those commands that cannot be performed dynamically are generally provided for by TC commands such as Commit_Changes and Perform_Fetch.

Using free-form SQL statements is required when any of the following conditions are true:

A free-form SQL statement begins with the command Begin_SQL / Begin_SQL2 / Begin_Select / Begin_Select2 and ends with a End_SQL / End_SQL2 / End_Select / End_Select2. Between the begin and end SQL commands, you can place the text of the SQL statement. You can compose the SQL statement using new lines and blank lines as you desire for readability. TC will concatenate all the data into one long string, discarding extraneous leading and trailing spaces and blank lines.

You cannot have any other TC commands within the begin / end SQL commands. Comments may be included, as long as the entire line is considered a comment; comments at the end of a line containing SQL are considered part of the SQL.
Note:See Limit on SQL Statement Size for important information on the size limitation on your SQL statement.

Only one SQL statement can be enclosed in a Begin_SQL / End_SQL pair (or similar commands). For example, an UPDATE and a INSERT must be separated into 2 free-form SQL sections.

Using User Variables and Transaction Fields in SQL Statements

Your TC scripts will often include SQL statements which will need to change each time the script is run. For example, in a warehouse application, a script may be set up to find out which stock locations contain a certain part number with at least X parts in that location. The part number and quantity desired comes from data in the transaction from the terminal operator.

TC provides a mechanism to do on-the-fly substitution for parts of the SQL statement with data from TC user variables or transaction fields. The SQL statement can include references to user variables by putting the user variable name (or UVn format) directly into the SQL, preceded by a colon. Similarly, you can include references to transaction fields such as TXNFIELD1, TXNFIELD2, ... directly in the SQL, preceded by a colon.

The following example shows how user variables references might be included in the SQL statement:

  // Get the part number string from the transaction
  Append_UV_Xact_Data( UV1, TXNFIELD1, 0,  0 )
  Format_UV( UV1, CHARACTER )
 
  // Get the quantity string from the transaction
  Append_UV_Xact_Data( UV2, TXNFIELD2, 0, 0 )
  Format_UV( UV2, NUMERIC )
 
  Begin_SQL()
 
    SELECT PART_NUMBER, QUANTITY, LOCATION
    FROM MFG.WAREHOUSE
    WHERE PART_NUMBER=:UV1 AND QUANTITY>=:UV2
 
  End_SQL()

When the script is compiled, TC keeps track of all references to user variables and transaction fields. At execution time, these references are replaced by the actual contents of the user variables/transaction fields, producing the actual SQL statement that will be performed.

In the example above, the command Format_UV is used to format the user variables prior to use in the SQL statement because the database requires numeric, character, and time/date values to be in distinct, specific formats.

To make this easier, TC allows the use of 'format specifiers' immediately following user variable/transaction field reference, enclosed in parentheses. The specifier may be one of :

  (C) for CHARACTER
  (N) for NUMERIC
  (T) for TIME
  (D) for DATE
  (S) for TIMESTAMP
  (X) for no formatting
 

Here are some examples:

  :UV10(C)
  :MyUserVar(T)
  :TXNFIELD27(N)

The formatting works as described under command Format_UV, except that the user variable or transaction field data is not directly modified, only the copy of the data placed in the free-form SQL statement is modified.

Using these TC features, the example above can be simplified:

  Begin_SQL()
 
    SELECT PART_NUMBER, QUANTITY, LOCATION
    FROM MFG.WAREHOUSE
    WHERE PART_NUMBER=:TXNFIELD1(C) AND QUANTITY>=:TXNFIELD2(N)
 
  End_SQL()
The SQL statement output is identical with fewer commands.

The epitome of user variable/transaction field substitution in your free-form SQL would be to fully compose the SQL statement at the data collection terminal and create it as a single transaction field:

  // Get the SQL statement from the transaction
  Begin_SQL()
 
    :TXNFIELD1
 
  End_SQL()

:sqlCurrentTime Macro

There is another kind of substitution that TC can do when your SQL statements have to work with more than one database type. TC provides special macros for certain database functions so that it can do substitution for those macros, based on the current database type, when it prepares the SQL statement.

Today there is only one macro like this and it is used for the SQL function that returns the current date and time. This macro, :sqlCurrentTime, can be used in the free-form SQL statement and TC will substitute the appropriate SQL function name based on the database type currently in use. For example, the following SQL works only with DB2:

  Begin_SQL ( )
 
    UPDATE DCERP.LP_INFO
    SET    Locn = :uvtLOCN_TO(C),
           Last_Txn = :uvtTXN_TYPE(C),
           Update_Timestamp = CURRENT TIMESTAMP
    WHERE LP#    = :uvtLP#(C) and
           Branch = :uvgBranch(C)
 
  End_SQL ( Unexpected_Database_Error )

But if we substitute the macro :sqlCurrentTime for CURRENT TIMESTAMP, TC will be able to do the appropriate substitution for this macro to generate SQL that is valid for other database types such as Oracle and SQL Server:

  Begin_SQL ( )
 
    UPDATE DCERP.LP_INFO
    SET    Locn = :uvtLOCN_TO(C),
           Last_Txn = :uvtTXN_TYPE(C),
           Update_Timestamp = :sqlCurrentTime
    WHERE LP#    = :uvtLP#(C) and
          Branch = :uvgBranch(C)
 
  End_SQL ( Unexpected_Database_Error )

TC knows what function name should be substituted based on the value of the keyword CURRENT_TIME_FUNCTION for the current database type definition in the DBTYPE.INI file. For more information about DBTYPE.INI and the keyword CURRENT_TIME_FUNCTION please see DBTYPE.INI.

SQL Statement Lifetimes

TC allows you to perform INSERT or UPDATE statements while maintaining an open SELECT statement with its valid SQL cursor:
    //Fill a packing list table with the part numbers,
    //quantities and item descriptions of everything
    //of record which has been loaded onto a pallet
 
    Begin_SQL()
 
      SELECT  A.ITEM, QUANTITY, DESCRIPTION
        FROM PALLETS A, ITEMS B
      WHERE PALLET_NUMBER=:uvtPallet(N)
      AND A.ITEM = B.ITEM
 
    End_SQL()
 
    //* Clear uvSQLRC and set SQL 100 vector to
    //* point to a routine which will set uvSQLRC
    //* with text "NO ROWS"
    CallSubroutine( PrepForSQL100 )
 
  Get_More:
 
    Perform_Fetch()
 
    //* If we got no SQL 100 error...
   If ( uvSQLRC == "" )
    {
     //* Got a row
     Set_UV_Select_Data( uvs1, 1 )   //* Item
     Set_UV_Select_Data( uvs2, 2 )   //* Qty
     Set_UV_Select_Data( uvs3, 3 )   //* Description
 
 
     //* Insert row into PACKSLIP table
     Begin_SQL()
 
       INSERT INTO PACKSLIP
         ( PALLET_NUM, ITEM, QTY, DESCRIPTION )
       VALUES
         ( :uvtPallet(N), :uvs1(C), :uvs2(C), :uvs3(C) )
 
     End_SQL()
 
     Goto Get_More
    }
 
   //* Got all rows of pallet data and inserted
   //* them with description into PACKSLIP table
   //* Commit now to close the select cursor and
   //* make permanent the new rows in PACKSLIP
   Commit_Changes()
Note that in the example above we do not commit the changes after each row is inserted into the PACKSLIP table -- as soon as you do a Commit_Changes command the database will close your SELECT cursor (you would get an error complaining about attempted use of an obsoleted cursor if you did a commit and then went back and tried to do another fetch).

The last SELECT statement you executed (via an End_SQL / End_SQL2 / End_Select / End_Select2 or Perform_Select command) is the statement which is valid -- any prior SELECT is destroyed as do the new SELECT.

Limit on SQL Statement Size

The size of any individual SQL statement created by the commands or input in a free-form SQL statement is limited to 4,000 characters. This includes the size of data that is brought in from the transaction or from user variables.

Binding to the Database

When TC will be connecting directly to a DB2 database (instead of using an ODBC connection to the database or not using a database at all) it is necessary for TC to 'bind' to the DB2 database before any database operations can be performed.

TC allows you the opportunity to manually perform the database binding. This is sometimes required when only certain users may have authority to perform a bind. There is now a single bind file (TCDB2.BND) that must be bound to all DB2 databases that will be used. (Prior to fix pack E for version 1.40, there were three bind files: XIS.BND, XIS_C.BND, and XISDBCOM.BND).

If you want TC perform the binding for you, you do not need to do anything beyond making sure the installation procedure was followed properly. TC responds to SQL error codes at runtime and automatically performs the SQLBIND and retry the first transaction. The .BND file must be located in the directory defined by the environment variable TC2.


Using ODBC Database Connection(s)

When TC was initially designed, DB2 was the only database type to which TC could connect. Therefore TC defaults to assuming that all database operations will be directly (natively) to DB2.

With fixpack E for version 1.40, support for ODBC connections was added to TC. Version 3.1.0 adds support for simultaneous connection to up to 24 ODBC data sources.

There are several different issues that arise with ODBC connections because the actual database type on the other end of the connection could be anything from DB2 to Oracle to SQL Server ... Although the goal of ODBC is to standardize the interface to many different database types, there are still differences between them that may need to be handled in your TC scripts. For more information about these issues please see Handling Differences Between Database Types When Using ODBC.

Regardless of the database type, because TC is a 32-bit program, it requires a 32-bit ODBC connection; it will not work with a 64-bit ODBC connection.

ODBC Performance and Deadlocks

It is sometimes thought that using ODBC to interface to a database is much slower than interfacing directly to the target database. While there is an extra layer that using ODBC requires, the actual differences in execution time is negligible. In some cases, such as some involving remote connections to databases, the ODBC implementation to that remote database may actually be faster than the native database's implementation of remote access.

TC does a couple of things to maximize performance with ODBC connections:

There is one thing that can seriously degrade performance of an ODBC session if it is turned on -- the option to Trace all ODBC operations. When turned on, every database operation is logged to file which of course slows things down and consumes lots of disk space. This can be a very useful feature when trying to debug a problem. But for use in production, tracing should be turned off.

Whether or not tracing is on is determined by a setting in the ODBC Data Source Administrator settings notebook. This notebook contains a tab labelled Tracing. Make sure the options on the Tracing page are set such that tracing is not active. For more information about bringing up the ODBC Data Source settings notebook, please see Configuring an ODBC Data Source.

As was mentioned above, TC maintains two separate statement handles for processing database operations. This is also necessary in order to allow TC scripts to be able to fetch through a result set that was obtained by doing one select and at the same time do other database operations such as updates or inserts using the other handle. TC does all operations using one handle until a select operation is encountered. After the select operation, TC switches to use the other handle until another select operation is encountered. After the next select TC switches back to the first handle. TC only allows one outstanding select operation by making sure any open cursor is closed before performing a select operation.

Because SQL Server does not support more than one active statement handle per connection, TC actually has to open two separate ODBC connections to the database, one for each statement handle. As a result TC script writers have to be careful not to perform a series of database operations that would cause one handle to block, waiting on the other. The following is a scenario that would result in a deadlock:

  1. An operation is performed to delete all records from a table.

  2. A select operation is performed to fetch records from a different table without first committing the delete operation (this causes TC to switch to using its other handle for subsequent database operations).

  3. Each record in the result set returned by the select is fetched and then inserted into the table that was cleared out in step 1.

Because the delete operation was performed using one handle and that work was not committed, the attempt to insert records into the same table would block because a different handle is being used. In order to resolve this scenario, the delete operation should be committed before the select is performed.

When using an ODBC database connection, TC watches every database operation to see how long it takes. If it finds an operation has taken longer than a certain deadlock timeout, it will assume a deadlock has occurred which will result in TC rolling back any uncommitted database operations and then shutting down.

The deadlock timeout defaults to 1 minute but can be changed to up to 60 minutes using the Deadlock_Timeout command. Please see Deadlock_Timeout.

Also be aware that a particular TC script might become blocked by database operations from other applications, including other TC scripts. So if a deadlock does occur, not only should you examine what the TC script was doing at the time to make sure the contention was not caused by the script itself but you should also check to see whether other TC scripts or other database applications have locked the same rows that the blocking TC script was accessing.

Configuring an ODBC Data Source

If TC is to use ODBC to access databases, then ODBC connections must be created to those databases before TC can access them.

Regardless of the database type, because TC is a 32-bit program it requires a 32-bit ODBC connection; it will not work with a 64-bit ODBC connection.

The database software must be running before TC can access any database; TC will not start the database software itself.

Once the ODBC data source is configured in Windows, your Database/DB command line argument or script command can reference that data source. However, in order to tell TC that this data soure should be accessed via ODBC instead of it being a DB2 data source to access directly, the DBType command line argument or script command must specify ODBC instead of DB2. For more information about the DBTYPE command, please see DBType.


Handling Differences Between Database Types When Using ODBC

ODBC was created as way to standardize the interface to many different database types (e.g. DB2, Oracle, SQL Server, ...). Although many things are standardized, some are not consistent between the different database types. Here are a few examples:

Quite often when a script is being written, it is for one specific database type. In this cases, these differences do not matter. However, if a single script is to work with more than one database type without changes, these differences have to be handled. TC has a few mechanisms available to allow scripts to handle these differences.

DBTYPE.INI

The basis for handling these differences is a file called DBTYPE.INI. This file contains a section for each database type that might be handled. In each section, keywords are used to define how each database type handles certain issues.

To start, TC has to figure out the database type to which it is connected. It asks the ODBC driver for the DBMS name which returns a string such as "DB2/NT", "Oracle 7", "Oracle 8.0", "Microsoft SQL Server", ... TC then maps this string to the appropriate section so that it can figure out the other traits that apply to the current database type.

Before we get into any further discussion, here is a sample of what DBTYPE.INI looks like:

 
  [DB2]
    ALIAS                 = "DB2"
    ALIAS                 = "DB2/NT"
    DATE_TIME_SEPARATOR   = "-"
    DATE_SEPARATOR        = "-"
    TIME_SEPARATOR        = "."
    CURRENT_TIME_FUNCTION = "CURRENT TIMESTAMP"
 
  [Oracle]
    ALIAS                 = "ORACLE*"
    ALIAS                 = "ORCL"
    DATE_TIME_SEPARATOR   = " "
    DATE_SEPARATOR        = "-"
    TIME_SEPARATOR        = ":"
    CURRENT_TIME_FUNCTION = "SYSDATE"
 
  [SQL SERVER]
    ALIAS                 = "Microsoft SQL Server"
    DATE_TIME_SEPARATOR   = " "
    DATE_SEPARATOR        = "-"
    TIME_SEPARATOR        = ":"
    CURRENT_TIME_FUNCTION = "CURRENT_TIMESTAMP"

Each section starts with a name enclosed in square brackets (e.g. [DB2]). This is the name by which TC will know this database type. It is the name that will be assigned to the DBTYPE data part that can be used in an If command (discussed below).

The ALIAS keyword(s) in each section specify the various strings that the ODBC driver might return when TC asks for the DBMS name. TC matches these with the response in order to figure out which section is appropriate - in other words, to which database type it is currently connected.

In order to allow for differences in the responses that the various database types might return as new versions are created, the ALIAS can be used multiple times in a section. Furthermore, the ALIAS string may contain the wild card characters * and ?. The asterisk is used to match any number of characters at the end of the string; it should not be used in the beginning or the middle of the string.

For example, Oracle 7.0 returns the string "Oracle 7" and Oracle 8.0 returns the string "Oracle 8.0". The following ALIAS statement uses a wild card character to match both strings:

  ALIAS = "Oracle*"
This would also match "Oracle 9.0", "Oracle X", etc.

The ? character is used to represent a single character anywhere in the string. For example, the following alias string matches both "Oracle 8.0" and "Oracle 9.0":

  ALIAS = "Oracle ?.0"

However, this would not match "Oracle 7" or "Oracle 10.0". Therefore it is usually better to use the asterisk once you have determined a sufficiently long enough start of the string that would be unique amongst all database types.

The rest of the keywords in a database type section are used to define specific traits of that database type. These keywords are:

DATE_TIME_SEPARATOR

Specifies the character that goes between the date and time in a timestamp string that is generated by TC. TC generates a timestamp string for the Format_UV command when the field_type is TIMESTAMP or when the col_type is TIMESTAMP for the commands Select_Where, Select_Having, Setup_Insert_Field, Setup_Update_Field and Update_Where. TC also generates a timestamp string when using free-form SQL statements and the format specifier (S) is used.

DATE_SEPARATOR

Specifies the character that separates the parts of date string when it is generated by TC. TC generates a date string for the Format_UV command when the field_type is DATE or when the col_type is DATE for the commands Select_Where, Select_Having, Setup_Insert_Field, Setup_Update_Field and Update_Where. TC also generates a date string when using free-form SQL statements and the format specifier (D) is used.

TIME_SEPARATOR

Specifies the character that separates the parts of time string when it is generated by TC. TC generates a time string for the Format_UV command when the field_type is TIME or when the col_type is TIME for the commands Select_Where, Select_Having, Setup_Insert_Field, Setup_Update_Field and Update_Where. TC also generates a time string when using free-form SQL statements and the format specifier (T) is used.

CURRENT_TIME_FUNCTION

Specifies the name of the SQL function used to return the current date and time. For example, in DB2, this function is called "CURRENT TIMESTAMP" and in Oracle it is called "SYSDATE". In a TC script, when writing a free-form SQL statement (using the TC commands Begin_SQL / End_SQL or similar commands), it may be necessary to get the current date/time to insert into a table or to use in some other database operation. If the script containing this free-form SQL statement is to be run against more than one database type (e.g. DB2 and Oracle), then there is a problem trying to create SQL syntax that would be valid for both database types.

To resolve this problem, TC allows the use of a mechanism similar to the user variable substitution that can be done in free-from SQL statements. For more information, please see :sqlCurrentTime Macro.

Adding Support for Other Database types to DBTYPE.INI

If you want to use TC to connect to another database type, via ODBC, other than those that are already defined in DBTYPE.INI, then all that must be done is to add another section to DBTYPE.INI file that is similar to the other sections.

First choose an appropriate name for this new database type. This will go between the square brackets. Be sure the name is unique amongst all the other sections. It can't be longer than 64 bytes.

Next you must define one or more alias strings that map the name for this type to what this database type's ODBC driver will return for the DBMS name. If you are not sure what the ODBC driver will return, you can perform the following steps to figure it out:

  1. First configure an ODBC data source using the ODBC driver for the new database type. For more information about how to define an ODBC data source, refer to Configuring an ODBC Data Source.

  2. If you have an existing TC script that does database operations, change it to use the new ODBC data source and the appropriate user ID and password. And if you did not already do so, make sure the DBTYPE is set to ODBC. Don't worry about what tables are in the database versus what the script references because all TC has to be able to do is to connect to the database on startup.

    If you don't have an existing TC script that does database operations, set one up using the new ODBC data source and the appropriate user ID and password. Also create a simple StartLogon script so that TC has something to compile.

  3. Run the TC script so that it tries to connect to the database. If successful TC will log the message XIS083 that is similar to:
     
      XIS083:Connected to database ODBCTEST running on DB2/NT (02.01.0002)
     
    

    The DBMS name returned by the ODBC driver is the name that follows the words "running on" and comes before the parenthesis that enclose the version number. So in the example above, "DB2/NT" (without the double quotes) is the DBMS name returned by the ODBC driver.

Once you have determined what the ODBC driver will return for the DBMS name you can create the ALIAS statement. Use wildcard characters whenever possible to increase the chance for getting a match - but at the same time make sure the alias does not match any other aliases used for other database type definitions.

Finally add the appropriate values for the other keywords: DATE_TIME_SEPARATOR, DATE_SEPARATOR, TIME_SEPARATOR and CURRENT_TIME_FUNCTION.

If you do not add one or more of these keywords to the database type definition they will default as follows:

  DATE_TIME_SEPARATOR   = "-"
  DATE_SEPARATOR        = "-"
  TIME_SEPARATOR        = "."
  CURRENT_TIME_FUNCTION = ""

Using DBTYPE in an If Command

The DBTYPE.INI file is good for handling those differences between database types that can be resolved by a simple substitution of the proper character or string. However, there are other differences between database types that cannot be resolved with a simple substitution. These are situations where the SQL syntax for complex operations, particularly those involving date and time, is quite different depending on the target database type.

For example, when using DB2, if you wanted to determine the time 30 years prior to the current time, the following syntax would be part of your SQL:

  CURRENT TIMESTAMP - 30 YEARS

However, to do the same thing in Oracle, the following syntax would be part of your SQL:

  ADD_MONTHS(SYSDATE, -360)

To handle situations like these, TC allows the use of the data part DBTYPE. DBTYPE takes the value of the name of the database type from DBTYPE.INI to which TC has determined it is connected. The DBTYPE data part would typically be used in an If command. However, it can be used anywhere other data parts are allowed.

When used in an If command, the comparison must be made to one of the valid database types found in DBTYPE.INI and the comparison operator can only be one of equality or inequality: = == <> or !=. The following example shows how a TC script might handle the differences in syntax just mentioned:

  if (DBTYPE == "DB2")
   {
    Begin_SQL
 
      SELECT name, address from employee
 
      WHERE birthdate < CURRENT TIMESTAMP - 30 YEARS
 
    End_SQL
   }
 
  if (DBTYPE == "ORACLE")
   {
    Begin_SQL
 
      SELECT name, address from employee
 
      WHERE birthdate < ADD_MONTHS(SYSDATE, -360)
 
    End_SQL
   }

TC will only execute one of the above Begin_SQL / End_SQL statements, depending on which database type TC determined was being used. Of course, if neither DB2 nor Oracle was being used, neither statement would be executed.

Note that if you are using multiple ODBC connections, the DBTYPE data part will only tell you the type of the first database that was defined with Database / DB. Thus, the Get_DBType function is available to get the underlying type of any ODBC data source. The above example would need to be modified to first use Get_DBType into a variable, then use the variable in the If/Else code.


How TC Handles SQL Errors

10 SQL Error Handling Actions

When an SQL error occurs as the result of a database operation, TC may perform one of several actions to try to handle the error. The following list describes those actions, giving each a name:

DELAY_AND_RETRY

Gives time for the error condition to clear itself and then retries the script command that just failed. During the database connection phase of TC startup, this action code is one of several that will cause a looping 2 second delay and connection retry.

DELAY_RETRY_INVALIDATE

Similar to DELAY_AND_RETRY, but acknowledges that the database engine has automatically rolled-back changes and closed cursors. TC learns of this and appropriately releases its select data.

FORCE_COMMIT_RETRY

Forces a commit of all pending database operations and then retries the script command that just failed.

LOG_AND_TERMINATE

Logs information about the error that occurred and then ends the TC session.

LOG_RETURN_NO_ERROR

Logs information about the error that occurred but returns to allow the next script command to be performed.

NO_DATA

Logs an error unless a fetch is in progress. In either case, the next script command will be performed.

REBIND_DB

Performs a rebind to the database and then retries the script command that just failed. This is relevant only when TC is connected directly to a DB2 database - instead of using ODBC to connect to a DB2 database or any other database.

RECONNECT_DB

Tries to reconnect to the database (assuming there is currently no connection) and then retries the script command that just failed. During the database connection phase of TC startup, this action code is one of several that will cause a looping 2 second delay and connection retry.

RESET_RECONNECT_DB

Drops the database connection, tries to reconnect and then retries the script command that just failed. During the database connection phase of TC startup, this action code is one of several that will cause a looping 2 second delay and connection retry.

RETURN_NO_ERROR

All went well so simply return to allow the next script command to be performed.

USER_ONERROR

This is not actually an action but instead is used as a way to give an On Error String name to a native code and/or SQLSTATE that is not already handled by TC. (The script command Define_On_Error_String is another way to do this). All defined On Error Strings can be used in On_Error_Goto commands. For information, please see On Error Strings.

RC_DB2.INI and RC_ODBC.INI

TC is told which actions to perform for certain predefined SQL error values via an .INI file. If connecting to a DB2 database directly, TC looks for RC_DB2.INI; but if using ODBC to connect to the database (DB2 or other) then TC looks for RC_ODBC.INI. The appropriate .INI file must be found in the directory defined by the environment variable TC2.

The RC_*.INI files contain a series of lines that map SQL error values to one of the above actions. There are actually two ways that SQL error values can be specified: as a native database code (known as SQLCODE in DB2) or as an SQLSTATE value. It is often the case that the same SQLSTATE value is returned for several similar yet different error conditions whereas the native error code value returned in those situations is unique. For example, when connected to a DB2 database, the SQLSTATE 57011 is returned when an "Out of Application Heap memory' error occurs or when an "Out of Sort Memory" error occurs. However, the native codes for each of these errors is -954 and -955 respectively.

Because the native code is often more granular than the SQLSTATE, TC will look for a match of the native code before looking for a match of the SQLSTATE value. So when an SQL error occurs, TC will search through the table of values that were read from the RC_*.INI file and look for a match of the native code value and if none is found it will then look for a match of the SQLSTATE value. If either match is found, TC will perform the action that is assigned to the error value.

If no match is found, TC acts as if the action was LOG_RETURN_NO_ERROR.

The following are examples from the RC_*.INI files:

 
  // From RC_DB2.INI
 
    100 , SQL02000, NO_DATA             , OE NO DATA
 
   -818 , SQL51003, REBIND_DB           , OE BIND FILE TIMESTAMP CONFLICT
 
   -912 , SQL57033, FORCE_COMMIT_RETRY  , OE MAX LOCKS REACHED
 
   -803 , SQL23505, USER_ONERROR        , OE DUPLICATE RECORD
  -7008 ,         , USER_ONERROR        , OE INCONSISTENT REXX DATA
 
 
  // From RC_ODBC.INI
 
      1 ,         , LOG_RETURN_NO_ERROR , OE SUCCESS WITH INFO
 
    100 ,         , NO_DATA             , OE NO DATA
 
        , SQL08001, DELAY_AND_RETRY     , OE UNABLE TO CONNECT
 
        , SQL23505, USER_ONERROR        , OE DUPLICATE RECORD

Each non-comment line has 4 parameters, delimited by commas:

Other comments about these .INI files:

It was mentioned earlied that the same SQLSTATE value might be returned for several similar yet different error situations. This is actually beneficial if the action that should be performed in all of these situation is the same. Thus a single entry in the .INI file could cover several different errors.

To carry this further, there may be a set of SQLSTATE values that should be handled the same way. In fact, the first two characters of an SQLSTATE value indicate a certain category of error while the last 3 characters indicate a sub-category.

TC allows the SQLSTATE value in the .INI file to be specified with less than the 5 characters that make up a full SQLSTATE value. Furthermore, if desired the characters that are omitted can be padded with asterisks so it is more obvious what is meant. However, characters at the beginning or in the middle of the string cannot be omitted nor can they be replaced with asterisks.

For example, the following lines are all valid and mean the same thing:

       , SQLHYT**, USER_ONERROR        , OE TIMEOUT EXPIRED
       , HYT**,    USER_ONERROR        , OE TIMEOUT EXPIRED
       , SQLHYT  , USER_ONERROR        , OE TIMEOUT EXPIRED
       , HYT     , USER_ONERROR        , OE TIMEOUT EXPIRED
 

If any of the above statements is found in the .INI file, TC would consider it a match when the actual SQLSTATE value returned was either HYT00 or HYT01 (or any other that starts with HYT).

RC_USER.INI

In addition to RC_DB2.INI and RC_ODBC.INI, TC will look for RC_USER.INI for additional instructions about how to handle SQL errors. This file is optional and therefore does not exist when TC is first installed.

Whenever TC is installed or a fix pack is installed, RC_ODBC.INI and RC_DB2.INI will be overwritten to allow additional default handling to be specified and to facilitate support of additional ODBC data source types. So these two default .INI files would not be good place for users to add new instructions for handling SQL errors.

If there are special error situations that need to be handled at a particular installation, RC_USER.INI is the file in which to add lines that describe how those error situations should be handled. RC_USER.INI is read before the other appropriate TC-provided .INI file. Therefore its instructions take precedence over those in the TC-provided .INI file when any return codes are in both files.

If the error situation that occurred is one that TC should be handling in its default .INI files, then that information will ultimately be added to TC's files in its next release. But for immediate resolution of the problem RC_USER.INI can be used.

The format of the contents of RC_USER.INI is the same as the other .INI files described above. There is no need to add all of the codes from the predefined file - only those that are unique or that must override the predefined action.

On Error Strings

As was mentioned above, the fourth parameter on each line in the RC_*.INI file is the optional On Error string parameter. This is intended for use in the On_Error_Goto command which is used in the TC script to be able to override the default action that TC would take for a particular error situation. For more information please see On_Error_Goto.

The On Error String is an up-to-32 character name for an error situation and it is associated with a native code and/or SQLSTATE value that is returned from a database operation. The On Error String must start with the two characters, OE, so that when parsing the On_Error_Goto statement, TC can distinguish it from an SQLSTATE value or native code.

The first parameter of an On_Error_Goto statement specifies the error code that should be handled. This error code can actually be specified in one of three different ways:

The On Error String is actually a more descriptive alias for an SQLSTATE value and/or native code value. As you've seen in the examples from the RC_*.INI files above, each entry includes as the fourth parameter the On Error String which describes exactly what the error is about; if taken by themselves, it is not obvious what is meant by the specific native code value or SQLSTATE value.

While any of the 3 methods above can be used in the On_Error_Goto commands, use of the On Error String provides the most information and is also more flexible than the other 2 methods - particularly if the TC script will be used with more than one database type.

It is possible that the native code/SQLSTATE values associated with a particular On Error String in RC_DB2.INI would be different from the native code/SQLSTATE values for that same On Error String in RC_ODBC.INI. In this case, use of the On Error String instead of the native code/SQLSTATE values in the On_Error_Goto command would allow the script to work properly whether or not TC was connected to DB2 directly (DBTYPE = DB2) or using ODBC to connect to a DB2 or other database (DBTYPE = ODBC).

You'll notice the RC_*.INI files contain one or more entries that have the action parameter set to USER_ONERROR. These entries are in the file in order to give On Error String names to error codes that are not otherwise included in the file because they don't have a specific TC action assigned to them other than the default LOG_RETURN_NO_ERROR. While you could use the native code or SQLSTATE values in the On_Error_Goto command, use of the On Error String is more meaningful and flexible.

If you find there are error situations that your TC scripts need to handle with an On_Error_Goto command and the corresponding error codes are not already specifically mentioned in the RC_*.INI files, you can include the native code or SQLSTATE value directly in the On_Error_Goto command or you can use a new On Error String name, after defining that string.

New On Error String names should be defined in one of two places, the second of which is preferred:

Specifying SQLSTATE values

Your TC scripts and the supporting RC_*.INI files may reference SQLSTATE values in the following cases:

For all of these cases there are a couple of ways to specify the SQLSTATE value. An SQLSTATE value returned from a database operation has a length of 5 characters. The first 2 of those characters indicate a particular class of error and the last 3 of those characters indicate a sub-class. For example:

These are the ways that the SQLSTATE value can be specified:

On occasion it may be desirable to set up error handling such that a single statement takes care of a set of related errors. For this reason, TC supports limited 'wild card' comparisons for the SQLSTATE values. TC allows you to drop 1 or more characters from the end of the SQLSTATE value so that comparisons focus only on the first few characters of the SQLSTATE value that is returned in a particular error situation. You also have the option to include asterisks for those character positions that were dropped. For example, "SQLHYT" is valid and is the the same as "SQLHYT**". However, "SQL*YT00" and "SQLHY**0" are not valid because asterisks are allowed only at the end.

To illustrate the use of truncated codes: if you wanted a single On_Error_Goto statement to handle all error situations that result in the return of any SQLSTATE that starts with HYT and direct the code to the label Handle_Timeout, you would specify the following:

  On_Error_Goto( SQLHYT**, Handle_Timeout )

The use of asterisks or truncated SQLSTATE values is allowed in the .INI files as well as in the On_Error_Goto and Define_On_Error_String scripts commands.


Fatal SQL Errors

There is list of error conditions for which TC is configured to shut down after logging an error to the display and to the error log file. These are errors for which no amount of retrying will resolve the problem. These fatal error conditions are defined in the files RC_DB2.INI and RC_ODBC.INI and are the entries that are assigned the action code LOG_AND_TERMINATE.

If you find that for certain ones of these error conditions TC should do something else instead, you can override TC's behavior by adding entries to RC_USER.INI or by using On_Error_Goto commands at the appropriate place(s) in your scripts. Neither of these methods could have been used prior to fix pack E for the 1.40 version of TC. For a complete discussion about how TC handles error codes and about how you can change that behavior, please see How TC Handles SQL Errors.

Listed below are the fatal error codes (SQLCODEs) currently defined in RC_DB2.INI. These are in effect when TC is configured to connect directly to a DB2 database (DBTYPE = DB2) instead of going through ODBC to a DB2 or other database. Refer to the online Messages Reference for complete details about these errors and possible corrective actions.

SQL Error

Description

SQL0930N

Not enough storage available to process the SQL statement.

SQL0952N

Processing was cancelled because Ctrl-Break was pressed.

SQL0953C

Not enough storage is available in the agent (server) heap to process the statement.

SQL0954C

Not enough storage is available in the application heap to process the statement.

SQL0955C

Not enough storage is available in the sort heap to process the statement.

SQL0956C

Not enough storage is available in the database heap to process the statement.

SQL0957C

Not enough storage is available in the communications heap of the database client or the DDCS/2 machine to process the statement.

SQL0958C

The maximum number of open files has been reached.

SQL0959C

Not enough storage is available in the communications heap of the database server to process the statement.

SQL0960C

The maximum number of files has been reached in the database.

SQL0961C

Not enough storage is available in the remote services heap of the database client or the DDCS/2 machine to process the statement.

SQL0962C

Not enough storage is available in the remote services heap of the server to process the statement.

SQL1004C

Not enough storage on the file system to process the command.

SQL1022C

There is not enough memory available to process the command.

SQL1034C

The database is damaged. The application has been disconnected from the database. All applications processing the database have been stopped.

SQL1042C

An unexpected system error occurred.

SQL1044N

Processing was interrupted.

SQL1086C

An operating system error <error> occurred.

SQL3005N

Processing was interrupted.

Listed below are the fatal error codes (SQLSTATEs) currently defined in RC_ODBC.INI. These are in effect when TC is configured to connect directly to any database (including DB2) via ODBC (DBTYPE = ODBC). Refer to the appropriate documentation for your database software for complete details about these errors and possible corrective actions.

SQLSTATE value

Description

28000

Invalid authorization specification

IM001

Driver does not support this function

IM002

Data source name not found and no default driver specified

IM003

Specified driver could not be loaded

IM004

Driver's SQLAllocHandle on SQL_HANDLE_ENV failed

IM005

Driver's SQLAllocHandle on SQL_HANDLE_DBC failed

IM006

Driver's SQLSetConnectAttr failed

IM007

No data source or driver specified; dialog prohibited

IM009

Unable to load translation DLL

IM012

DRIVER keyword syntax error

IM014

Invalid name of File DSN

IM015

Corrupt file data source


Processing when the Database or Host Is Unavailable

As an option, you can process transactions, remote validation requests, or data requests from DCTs even when the database or host application connection is down. For example, you can immediately respond to a validation request with information that the database is down, rather than force the terminal to wait the full host communications timeout period before it makes the same determination.

By default, TC sessions do not begin processing transactions or requests until they successfully connect to the database and/or host screen. They retry the operation every few seconds until a connection is made and then start processing transactions or requests from the terminals. If you want TC to be able to read transactions or requests and do other processing of your script without benefit of a connection to the database and/or host, put the command Run_Without_Connect (for database) and/or Run_Without_Connect (for host) anywhere in the script file.

For the database connection, if Run_Without_Connect is present TC attempts to connect to the database before allowing any transaction processing to take place, but if the connection cannot be made immediately, other processing is allowed to take place. When there is no connection to the database, any work you try to do with the database yields an error; TC always sets the native code to -1024 and the SQLSTATE value to SQL08003 while a database connection does not exist. The default RC_*.INI files also define the on-error string "OE DB CONNECTION DOES NOT EXIST" for this situation.

In your scripts, use the On_Error_Goto command to route processing of this errors to the handler for this condition (for example, script commands that do whatever is desired when the database is not available). For example:

 
    On_Error_Goto( OE DB CONNECTION DOES NOT EXIST, DB_IS_DOWN )
 
      or
 
    On_Error_Goto( SQL08003, DB_IS_DOWN )
 
      or
 
    On_Error_Goto( -1024, DB_IS_DOWN ) // Should only use this for DB2
 

Note that in Run_Without_Connect mode you should not set up On_Error_Goto statements for any errors that you expect could occur with your database. Instead make sure these errors are defined in RC_ODBC.INI with the appropriate action. When in Run_Without_Connect mode, any errors associated with the actions RESET_RECONNECT_DB or RECONNECT_DB will be handled by TC - doing the appropriate reset and connect - and then TC will convert that and any subsequent errors to the SQL08003 / -1024 error until the database connection is reestablished. Therefore, it is only necessary to set up a single On_Error_Goto statement specifying -1024 or SQL08003 in order to catch any errors that would require a reconnect to the database.

TC automatically tries to connect to the database once every minute. When a connection is finally achieved your script will resume normal processing.

An example of processing a request for a badge validation is included in Verifying a Badge against the Database.

For the host connection there are no automatic re-tries to connect. It is up to your script to attempt a host connection at the appropriate times.


Recommended Design Rules

You can create very functional applications quickly with TC, but following a few guidelines will make them more robust, bug-free, and easy to maintain:

TC User Variable Naming

As you develop an application, it becomes clear that some pieces of data input by the worker on his/her data terminal, columns from database tables and host application data are used over and over -- for example, part numbers, quantities, user IDs, etc.. Rather than use the basic 'UVnn' user variable names in your TC script use the Name_UV command to create named user variables which are used in all areas of the script:

  //* Common pieces of data
  Name_UV( UV1,     tUserID )             // User ID from DCT log-on
  Name_UV( NEXT_UV, gAS400_User )         // User ID to logon to AS/400
  Name_UV( NEXT_UV, gSQLRC )              // Error vector value from SQL command
  ...
The convention shown above illustrates user variables containing data directly from a data collection terminal transaction starting with 't' while data from a database are prefixed with 'g'. Have a common file which is imbedded by multiple TC sessions so names are consistent between scripts.

Use global user variables only where:

In other cases it is best to use locally declared user variables and passed parameters.

Why Use Delimited Transaction Fields

Using semicolon-delimited fields when sending data from a DCT to the TC script is recommended as it makes it easy to add fields, change field lengths, move fields around, and avoid mistake-prone offset/length calculations. See Delimited Transaction Fields for more details.

One of the first tasks of the highest-level TC script routines is to extract the fields of the incoming transaction into named user variables for use throughout the rest of the processing for that transaction. See the example below.

Transaction Version Number

Invariably, requirements for a transaction will change after it has been rolled-out to production. This may require that the transaction format change to accomodate a new field, for example. With a 7 days X 24 hours factory operating many DCTs, it can be impossible to change over the transaction programs in all the DCTs at one time and then time this precisely with the start-up of new TC scripts. This is when it is handy to dedicate one field in every transaction to a version number representing the DCT's transaction program level. In the example in the next section, the first 3 characters of the second field contain a DCT transaction program level which the script can inspect.

Inquiry ID tags

Due to network congestion or interference, with RF controllers and TCP/IP networks it is not unusual to have a response sent by the TC script occasionally take a long time to get delivered back to the DCT which made the inquiry. Unless special steps are taken, the DCT may time-out waiting for the response and go on to doing some other transaction work which results in a new inquiry being sent. If the response to the first inquiry then arrives, you do not want the DCT to mistake this as the answer to the second inquiry. This is where an inquiry ID tag is useful.

Each time the DCT sends a transaction to which it expects an answer (to be delivered into one of its DCT-based user variables over the network), a portion of the data should be used to identify the inquiry and allow it to be matched with an incoming response. The ID tag is a value which the DCT creates and changes every time it sends an inquiry; for example, this might start with the letter 'A'and go though each letter through 'Z' and then repeat. If the DCT sends inquiry 'D' and gets a response with a 'C' (or any other letter) then it discards this response and resumes waiting for the appropriate response.

In the example below, the inquiry ID letter is appended to the DCT transaction program version as the fourth character in field 2. Therefore only the first 3 characters of field 2 are checked when verifying the version. The TC script does not check the inquiry ID letter; however, it will return the

 
  //* Extract delimited fields from incoming transaction
 
  //* First check to make sure it is fully formed from the DCT:
  If ( COUNT_TXNFIELDS #<> "7" )
   {
    //* This transaction should have 7 fields -- don't want to get
    //* a fatal TC error if we try to use a field which does not
    //* exist so handle this error...
    ...Log error, release transaction, and finish routine...
   }
 
  ...
 
  //* The first 3 characters of field 2 are the DCT transaction program version, while
  //* the fourth character is the inquiry ID value.
  Set_UV_Xact_Data( uvtTag, TXNFIELD2, 0, 0 )
 
 
  If ( uvtTag(0, 3) == "100" )
   {
    //* This transaction came from a terminal still running the original set
    //* of transaction programs -- version 1.00
    Set_UV_Xact_Data( uvtUserID, TXNFIELD3, 0, 0 )
    Set_UV_Xact_Data( uvtPart, TXNFIELD4, 0, 0 )
   }
  Else...
 
  (Handle other versions with differing delimited field assignments)
 
  (Process the transaction and set up all but the last user variable response.
 
  //* The final user variable to be set in the terminal will contain the tag that
  //* we received.  The terminal should have cleared its user variable 99 and should
  //* be waiting for user variable 99 to be set.  Once set, the terminal should
  //* ensure that the contents of user variable 99 match the tag that was sent up.
  //* This tag includes the 3-byte version number followed by the inquiry ID byte -
  //* just as it was received by the TC script.
 
   Send_Term_UV_Data( 99, uvtTag )
 

Creating the Script Command File

You use the script command file to tell TC what processing steps to take with each transaction, remote validation request, or data request it receives. The command file is simply an ASCII flat file, created with one of many available text editors on any system.

The command file is compiled by TC each time TC starts up. This compilation ensures that execution time is quick, with minimal amounts of searching and parsing to consume time and resources during production processing. The compiler issues error messages if it detects an error in your scripts.

You can use the command Imbed to imbed separate text files into your primary script file. This is useful when you have common script file construction elements that you want to use in several different overall scripts. The Imbed command allows the use of environment variables in the file path.

If you have used or will use the IMBED command at some point, you may need to to create a single listing file that includes all of the imbedded files. This can make it easier to search through your scripts or to analyze them. New with fix pack D of version 1.4.0 is a utility, Using the Utility IMBEDSCR.EXE to Create a Single Listing File, that can be used to create this listing file.


TC Script Examples

The following examples show how to write the command steps for various common tasks. The [n] markings on the lines direct you to the description of what the line of the command file is doing.

Several examples of common uses for Transaction Connection are included in the next sections. When reading this document in its on-line documentation format, on each example you can bring up hypertext links to explanatory text by double-clicking on the double-asterisk (**) (1) marks located after certain statements of the command scripts. For the hardcopy version, refer to the footnote for the statements.

When creating your command script file, you can copy and paste these examples from the documentation into your script files.

Inserting a Record into a Table

StartFunctionGroup( SHOP_FLOOR )        //[A](**)
(2)
 
    // F1 key transaction inserts a new part number into the database table
 
StartKey( F1 )                        //[B](**)
(3)
 
Insert_DB_Table( PART_NUMBERS )       //[C](**)
(4)
 
Setup_Insert_Field( PART_NUMBER, CHARACTER, TXNDATA, 0, 10) //[D](**)
(5)
Setup_Insert_Field( QUANTITY, NUMERIC, NULL, 0, 0, 0.0)     //[E](**)
(6)
Setup_Insert_Field( UPDATE_TS, TIMESTAMP, TIMESTAMP, 0, 12) //[F](**)
(7)
Perform_Insert ( Insert_Error_1 )   //[G](**)
(8)
 
Commit_Changes(COMMIT_ERROR)        //[H](**)
(9)
Goto End_F1                         //[I](**)
(10)
Insert_Error_1:                       //[J](**)
(11)
 
End_F1:                               //[K](**)
(12)
Release_Xact()                      //[L](**)
(13)
 
EndKey()                              //[M](**)
(14)
 
StartKey( Fn )                        //[N](**)
(15)
 
    ...
 
EndFunctionGroup()                      //[O](**)
(16)

Updating a Record in a Table

StartFunctionGroup( SHOP_FLOOR )         //[A](**)
(17)
 
    // F2 transaction adds quantity from transaction to the
    // current quantity in stock
 
StartKey( F2 )                        //[B](**)
(18)
 
Update_DB_Table( PART_NUMBERS )     //[C](**)
(19)
 
Setup_Update_Field( QUANTITY, NUMERIC, TXNDATA, 10, 8, QUANTITY+) //[D](**)
(20)
Setup_Update_Field( UPDATE_TS, TIMESTAMP, TIMESTAMP, 0, 12)  //[E](**)
(21)
Update_Where( PART_NUMBER, CHARACTER, = , TXNDATA, 0, 10 )   //[F](**)
(22)
 
Perform_Update ( Update_Error_2 )   //[G](**)
(23)
Commit_Changes(COMMIT_ERROR)        //[H](**)
(24)
Goto End_F2                         //[I](**)
(25)
Update_Error_2:                       //[J](**)
(26)
 
End_F2:                               //[K](**)
(27)
Release_Xact()                      //[L](**)
(28)
 
EndKey()                              //[M](**)
(29)
 
 
StartKey( Fn )                        //[N](**)
(30)
      ...
 
 
EndFunctionGroup()                      //[O](**)
(31)

Querying the Database Table

StartFunctionGroup( SHOP_FLOOR )                     //[A](**)
(17)
 
    // F3 transaction asks for current quantity of a part number
 
StartKey( F3 )                                     //[B](**)
(32)
 
Select_From_DB_Table( PART_NUMBERS )             //[C](**)
(33)
 
Select_Column ( QUANTITY )                       //[D](**)
(34)
 
Select_Where( PART_NUMBER, CHARACTER, = , TXNDATA, 0, 10 ) //[E](**)
(35)
 
Perform_Select ( Select_Error_3 )                //[F](**)
(36)
Perform_Fetch( No_such_pn )                      //[G](**)
(37)
Clear_UV(UV1)                                    //[H](**)
(38)
Append_UV_Select_Data( UV1, 1, No_such_pn, 10.3) //[I](**)
(39)
Send_Term_UV_Data( UV1, 10)                      //[J](**)
(40)
 
Goto End_F3                                      //[K](**)
(41)
Select_Error_3:                                    //[L](**)
(42)
      ...
 
Goto End_F3                                      //[K](**)
(41)
 
    No_such_pn:
Append_UV_Kbd_Data( UV1, "Sorry, no such part")  //[M](**)
(43)
 
Send_Term_UV_Data( UV1, 10)                      //[J](**)
(40)
 
End_F3 :                                           //[N](**)
(44)
Release_Xact()                                   //[O](**)
(45)
 
 
EndKey()                                           //[P](**)
(46)
 
StartKey( Fn )                                     //[Q](**)
(47)
      ...
 
EndFunctionGroup()                                   //[R](**)
(48)

Using Free-Form SQL

StartFunctionGroup( SHOP_FLOOR )               //[A](**)
(17)
 
    // F4 transaction asks for current quantity of each of the
    // three part numbers starting with the part number specified
    // in transaction field 1 from the terminal.  This uses
    // TC's automatic scanning of the transaction record for
    // fields delimited by semi-colons
    // (for example, data1;data2;data3;...),
    // taking all data up to the next semi-colon field separator.
 
StartKey( F4 )                              //[B](**)
(49)
Append_UV_Xact_Data( UV1, TXNFIELD1, 0, 0)  //[C](**)
(50)
 
      Format_UV( UV1, NUMERIC )
 
Begin_SQL()                               //[D](**)
(51)
 
SELECT PART_NUMBER, QUANTITY            //[E](**)
(52)
          FROM PART_NUMBERS
          WHERE PART_NUMBER BETWEEN :UV1 AND (:UV1 + 2)
 
End_SQL(SQL_error)                        //[F](**)
(53)
 
Perform_Fetch( Fetch_error )              //[G](**)
(54)
      Set_UV_Kbd_Data( UV1, "Part Num:")
      Append_UV_Select_Data( UV1, 1, No_more_data_4 )
      Append_UV_Kbd_Data( UV1, "  Quantity:")
      Append_UV_Select_Data( UV1, 2, No_more_data_4 )
      Send_Term_UV_Data( UV1, 10)
 
      Perform_Fetch( Fetch_error )
      Set_UV_Kbd_Data( UV1, "Part Num:")
      Append_UV_Select_Data( UV1, 1, No_more_data_4 )
      Append_UV_Kbd_Data( 1, "  Quantity:")
      Append_UV_Select_Data( UV1, 2, No_more_data_4)
      Send_Term_UV_Data( UV1, 11)
 
      Perform_Fetch( Fetch_error )
      Append_UV_Kbd_Data( UV1, "Part Num:")
      Append_UV_Select_Data( UV1, 1, No_more_data_4 )
      Append_UV_Kbd_Data( 1, "  Quantity:")
      Append_UV_Select_Data( UV1, 2, No_more_data_4 )
      Send_Term_UV_Data( UV1, 12)
 
    SQL_error:
No_more_data:                             //[H](**)
(55)
 
Close_Cursor()                            //[I](**)
(56)
      Clear_UV ( UV1 )
Append_UV_Kbd_Data( UV1, "Report Done")   //[J](**)
(57)
      Send_Term_UV_Data( UV1, 13)
 
      Release_Xact()
 
    EndKey()
 
  EndFunctionGroup()

Multiple ODBC Connections

// Note that database connection information must be defined in the script -- not on the
// command line -- when you are using multiple connections!

// Only DBType 'ODBC' allows multiple database connections 
// This one configuration line rules for all database connections
DBType( ODBC )

// Use DB / Database command to indicate which ODBC data sources you want to 
// use in your TC script.  
// The first parameter is the datasource name in Windows ODBC Datasources.
// The second parameter is an optional override alias names by which you will refer to the
// data source in subsequent TC script executable commands.  
// If you do not specify an alias then you will be using the actual Windows data source name in
// your script's executable commands (in effect, the alias is equal to the real name).  
// By specifying an alias which is different from the actual data sourc name you 
// can create multiple connections to the same data source, and thus have multiple
// Selects open to the same database. 

// Datasource 1:  oDCLIBdb2 is an ODBC data source that points to a DB2 database
DB ( oDCLIBdb2 )   

// Datasource 2: This is a second connection to that DB2 database
DB ( oDCLIBdb2, AnotherAliasForDB2 )    

// If needed to override the user credentials that are executing Transaction Connection, 
// specify the user ID and password for a previously-defined DB/Database alias.
// Notice here that when the DB/Database was defined the alias defaulted to the real name.  
// The alias must be used in these commands -- and all other commands EXECEPT DB/Database.  
// You can set the userID and/or password for each data source alias independently.
DBUserid( hornernw, oDCLIBdb2 )
DBPassword( pa55w0rd, oDCLIBdb2 )   // Or DBEncryptedPW can be used

// Datasource 3: A MS SQL Server data source, aliased to SQLServDB 
DB ( oDCLIBsql, SQLServDB )      
  
  
// Test it....  
StartLogon()

 Call DoIt()

EndLogon()


Sub DoIt()

   Declare( DB2_EMPLOYEE )
   Declare( DB2_GROUP ) 
   Declare( YY) 
   Declare( SQL_GEO ) 
   Declare( XX ) 
   Declare( uvName)
   Declare( uvAcro)
   Declare( uvLCL_GBL)
   
  
   // Select from the DB2 datasource, using alias defaulted from real name (Note Begin_SQL and Begin_SQL2 are interchangeable):
   Begin_SQL2()
   
      SELECT EMPLOYEE FROM DCLIB.EMPLGRP
      
   End_SQL2( oDCLIBdb2 )   // <<== Use the new '...2' flavor of End_SQL to indicate    
                           // that first parm is a required DB alias.  The optional 
                           // 2nd parm is the traditional error vector. 
   
   //Select from the same DB2 database, but using a different alias, and thus
   //a different set of connections/cursors/results set, etc. 
   Begin_SQL2()
   
      SELECT WORK_GROUP FROM DCLIB.EMPLGRP
      
   End_SQL2( AnotherAliasForDB2 )       
   
  
   // Cause fetch from Select from oDCLIBdb2 above.  Note ...2 flavor of the command, with
   // alias as required first parm and the traditional optional error vector 
   Perform_Fetch2( oDCLIBdb2, errlbl ) 
    
   // Cause fetch from AnotherAliasForDB2 Select above
   Perform_Fetch2( AnotherAliasForDB2, errlbl ) 
   
   // Use fetched row from oDCLIBdb2 select.  Again, the ...2 flavor of this command
   // requires the data alias as the first parm.
   Set_UV_Select_Data2( oDCLIBdb2, DB2_EMPLOYEE, 1 ) 
   
   // Use fetched row from AnotherAliasForDB2 select     
   Set_UV_Select_Data2( AnotherAliasForDB2, DB2_GROUP, 1 ) 
   
   
   //* Commit/close the selection from  oDCLIBdb2
   Commit_Changes2 ( oDCLIBdb2 )
   
   // Test no commit on 2nd connect to db2 db -- it will be forced closed when the script ends
   
   
   
  
   // Work with SQL Server datasource.
   // Note that user's default database has been configured in SQL Server Studio to be the 
   // desired database (otherwise the database name would be needed in this SQL as a pre-pended
   // schema identifer (e.g. DCLIBsql.dbo.Geographies)

  Begin_SQL()
  
     SELECT NAME FROM dbo.Geographies
     
  End_SQL2( SQLServDB, err2 ) 
  
  Perform_Fetch2( SQLServDB ) 
  
  Set_UV_Select_Data2( SQLServDB, SQL_GEO, 1 )   
  
  // Again, the ...2 suffix flavor of this command requires DB alias as firt parm.
  Close_Cursor2 ( SQLServDB ) 
  
  Commit_Changes2( SQLServDB )       
  
   
  
  err2:
  
  // The 'stick-built' insert sequence is the same for use with 
  // any database alias UNTIL you get to the final Perform_Insert2 -- where
  // you tell it where to actually apply the SQL statement that has been 
  // built-up with the prior commands.  Note you can only 'stick-build' the
  // insert for a single database at a time because of a shared buffer under the covers.
  // Also note that only INSERT is supported -- the stick-built Select and Update do not
  // have a ...2 flavor command and will thus work against the first database defined.
  Insert_DB_Table( dbo.Geographies )
  
  Set_UV_Kbd_Data( uvName, "AFRICA" )
  Set_UV_Kbd_Data( uvAcro, "AF" )
  Set_UV_Kbd_Data( uvLCL_GBL, "LCL" )
  
  Setup_Insert_Field( NAME, CHARACTER, uvName, 0, 0)
  Setup_Insert_Field( ACRONYM, CHARACTER, uvAcro, 0, 0) 
  Setup_Insert_Field( LCL_GBL, CHARACTER, uvLCL_GBL, 0, 0) 
  
  Perform_Insert2( SQLServDB )
  
  Commit_Changes2( SQLServDB ) 

EndSub()



Sub errlbl()

  Log_Error( "error on fetch" )
  
EndSub()

Handling Remote Validation Request

StartVal(BADGES.VAL)                             //[A](**)
(58)
 
    Clear_UV(UV1);
 
Select_From_DB_Table( EMPLOYEES )             //[B](**)
(59)
    Select_Column( FIRST_NAME )
 
    Select_Where( BADGE_NUMBER, CHARACTER, =, TXNDATA, 0, 0)
 
    Perform_Select(SQLerror)
 
Perform_Fetch(No_such_badge)                  //[C](**)
(60)
 
    Append_UV_Kbd_Data( UV1, "Thank you, ")
Append_UV_Select_Data( UV1, 1, No_such_badge) //[D](**)
(61)
 
    Close_Cursor()
 
    // will execute this if badge number was found
Send_Term_UV_Data( UV1, 10 )                  //[E](**)
(62)
    Send_Term_VResp( PASS )
 
    Goto End_badge
  // will branch to here if no such badge
No_such_badge:                                //[F](**)
(63)
 
    Append_UV_Kbd_Data(UV1, "Sorry, your badge number is invalid")
Send_Term_UV_Data( UV1, 10, SYNCH)          //[G](**)
(64)
Send_Term_VResp( FAIL )                     //[H](**)
(65)
 
    Goto End_badge
 
  SQLerror:
 
    Append_UV_Kbd_Data(UV1, "System error #001 -- Call SysOp @ 3-9233")
Send_Term_UV_Data( UV1, 10, SYNCH)          //[G](**)
(64)
Send_Term_VResp( FAIL )                     //[H](**)
(65)
 
  End_badge:
 
  EndVal

Using the Utility IMBEDSCR.EXE to Create a Single Listing File

New with fix pack D is a utility program, IMBEDSCR.EXE, which is useful if your scripts are stored in several command files and you use the IMBED command to link them altogether. IMBEDSCR.EXE allows you to generate a single listing file that includes all of the imbedded files. The listing shows the line number from each imbedded file along with a letter indicating the imbed level of that file (A for the top level, B for the next level, ...)

To generate a single listing file which includes all imbedded files in the listing, issue the following command:

  imbedscr source_file
where 'source_file' is the name of the same script file you would specify when running TC2.EXE.

The output file will have the same 'file name' (before the period) as the input file, but the extension of the output file will be .LST - unless the extension of the input file is already .LST in which case the extension of the output file will be .OUT.

Initially this tool generated a listing file that could not actually be run by TC. But the latest version generates a 'runnable' output file. This might be useful if the set of scripts need to be sent to a colleague to illustrate something or if the set of scripts need to be sent to IBM so that a problem can be replicated.

If you prefer to get a listing with line numbers, then you can add a second parameter, listing, to the command line. For example:

  imbedscr erp_ow.scr listing


Starting Transaction Connection

If your TC scripts will be using any functions that are in the category of Host Screen Interaction Functions, TC requires that Personal Communications (PCOMM) or another provider of the Emulator High Level Language Application Programming Interface (EHLLAPI) functions in ACS3EHAP.DLL be installed prior to running those TC scripts.

Likewise, if your TC scripts will be using any Database Insert/Query/Update Functions, TC requires that the appropriate database software (a database to be accessed via ODBC or IBM DB2, accessed directly) already be installed.

For information about configuring an ODBC data source, please see Configuring an ODBC Data Source.

Also make sure that the session in which TC will be running has the proper access authority in order to be able to perform operations on the databases.

If your scripts will be using any DCConnect API or a mailbox name other than NO_DCCONNECT, then TC requires that DCConnect Toolkit or Server be installed. In this case, TC expects the DCConnect Server to be running before it will run any scripts. Similarly, any TC session will shut itself down when it detects that the DCConnect Server has been shut down.

Starting TC from the OS/2 STARTUP.CMD

If you want a TC session to be started automatically from your STARTUP.CMD file, several things must be done prior to the command that is used to start the TC session:

After including the necessary commands mentioned above, include the command(s) to start the TC session(s). For example:

  start tc2 @ mapicsxa.scr

Note: The TC session(s) can be set up to be started by DCConnect. If that is the case, you do not include in the STARTUP.CMD file any commands for starting TC sessions.

Starting TC from a Command Line

The TC sessions can be started from the command line or in a .CMD file as follows:

  TC2 <script command file> /MAILBOX=<mailbox>|REMOTE_VALIDATION|DATA_REQUEST|NO_DCCONNECT /DB=<database> /CNTLR=<controller id> /APPL=<application> /DBTYPE=NONE|DB2|ODBC
                     /EMULTYPE=NONE|CM|PCOMM /DBUSERID=<user_id> /DBPASSWORD=<password> /TRACE|/NO_DISPLAY /XML_SENDER=<DLL_name:Function_name>
or
  TC2 @ <script command file>

Note 1:The first example above is spread over two lines for typographical reasons only. When supplying the parameters on the command line, they should all be entered on one line.

Note 2:Support for the Talk Thru option (TT) was discontinued after version 3.1.1 of TC.

In the first example for each of the above cases, several parameters are explicitly stated on the command line. Some of the parameters are optional and are explained below. The angle brackets are NOT part of the syntax that should be typed on the command line or in a .CMD file. Parameters for TC are free style and require the keyword to identify the parameter type. All TC keyword parameters are optional and revert to a default value if not entered.

In the second example for each case, the only parameter is the name of the script command file immediately preceded by the '@' character. Using this method the parameters that otherwise would have been defined on the command line are instead defined in the script command file or one that is imbedded by it. The following script commands are used to define the values for these parameters:

 
    mailbox()
    session()
    cntlr()
    application()
    database()
    db()
    emultype()
    dbtype()
    dbuserid()
    dbpassword()
    xml_sender()
 

In all cases, the <script command file> is the name of the script command file for this TC session. This file is a script that instructs the TC session what you want to do with each transaction, validation request or data request. Creating the Script Command File describes how to create your command script file.

Note: Throughout this documentation, the terms 'script file' and 'command file' are used interchangeably.

If specifying the parameters on the command line as indicated previously, the parameters should be specified as follows:

<mailbox>

This is the name of the DCConnect mailbox that this TC session should use when connecting to DCConnect. The name must match exactly, including capitalization, the mailbox name that has been created in DCConnect.

If your TC session is processing validation requests instead of transactions, then you should specify the following keyword:

   REMOTE_VALIDATION

instead of an actual mailbox name. In this case, the TC session determines which validation files should be handled from all of the StartVal commands that are encountered in the script. The application name parameter can be used to override the default application name that the TC session would otherwise use when registering with DCConnect to receive validation requests. The default application name is based on the controller ID.

If your TC session is processing data requests instead of transactions or validation requests, then you should specify the following keyword:

  DATA_REQUEST

instead of an actual mailbox name. In this case, you must specify an application name on the command line, or in the script. The TC session uses that application name when registering itself with DCConnect to handle data requests.

See Transaction, Remote Validation, or Data Request Modes for additional information.

If you want to run a TC session that does not handle transactions, validation requests or data requests, use any of the following keywords:

  NONE
  NO_DCCONNECT
  NO_DCC/2

in place of the mailbox name. (This is also the default if the /MAILBOX parameter is not used on the command line and the mailbox() command is not used anywhere in your script files). This can be useful if your TC session is going to be performing only a simple operation on an interval basis, such as downloading files from an AS/400 twice a day. As an example:

  /MAILBOX=NO_DCCONNECT

<session>

This is the 'short name' of the PCOMM terminal emulation session to which this TC session tries to connect. This is a single character, for example:

  /SESSION=A
If no /SESSION parameter is supplied the session will not attempt to connect to a host screen.

<controllerid>

This is a single character to use as an arbitrary controller identification. This character is used in the name of the error log file, transaction log file, and trace log file that can be generated by each TC session that is running. If the TC session is processing remote validation requests then the controller ID is part of the default application name used when the TC session registers with DCConnect to receive validation requests. Each TC session should be started with a unique controller ID.

This parameter is optional unless multiple TC sessions are running at the same time.

The default controller ID is 'Z'.

<application>

This parameter can be specified if the TC session is processing validation requests or data requests. It is ignored if transactions are being processed.

If the TC session is processing validation requests, the application name specified here overrides the default name that would be based on the controller ID. This name is used by the TC session when it registers with DCConnect to receive validation requests.

If the TC session (i.e. 'server') is processing data requests, the application name is required. This name is used by the TC session when it registers with DCConnect to receive data requests. All terminals or other TC sessions acting as the clients that make the data requests must specify the TC 'server' session's application name in the request. DCConnect uses that application name to route the request to the 'server' application that has registered itself using that name.

The application name can be up to 32 characters long.

<database>

This is the name of the database with which this TC session is working.

The database name can be up to 128 characters and, more importantly, it must match the name of a database that has already been created.

<user_id>

This is the name of a valid user id on the system that is the target of the database connection. This may be 1-127 characters in length.

This provides database user-id and password information to be passed on the database connection. This is analogous to the command line SQL statement: CONNECT TO database USER user_id USING password.

<password>

This is the password which is valid for user_id on the system that is the target of the database connection. password may be 1-127 characters in length.

This provides database user-id and password information to be passed on the database connection. This is analogous to the command line SQL statement: CONNECT TO database USER user_id USING password.

/DBTYPE

This optionally specifies the database type to which TC will be connecting. To indicate that TC will be connecting directly to an IBM DB2 database (instead of using ODBC to connect to it), specify the following keyword:

   DB2

If TC will be using ODBC to connect to the database, including DB2, then use the following keyword:

   ODBC

If you are not going to be doing any database operations in the command scripts, specify the following keyword:

   NONE

If the DBTYPE keyword is not used on the command line or in the scripts, the default will be DB2 if the /DB keyword or Database/DB script commands are used. Otherwise the default is NONE.

For more information about defining the database type in the script files, please see the discussion of the script command DBType.

/EMULTYPE

(TC only ) This optionally specifies the host screen emulation support. To indicate the emulation support you are using specify one of the the following keywords:

   PCOMM  ( Personal Communications )
   CM     ( Communications Manager/2 (OS/2 only) )

Note 2:Support for the Talk Thru option (TT) was discontinued after version 3.1.1 of TC.

If you are not going to be doing any screen emulation operations in the command scripts specify the following keyword:

   NONE

If the EMULTYPE keyword is not used the default will be NONE.

TRACE

This optional parameter is used to turn on execution or compile tracing for debug purposes. Refer to the Trace command for additional information.

If used, this parameter should appear at the end of the parameter list. If TRACE is specified, NO_DISPLAY should not be used.

NO_DISPLAY

This optional parameter is used to improve processing speed by turning off the display of each executed step. Refer to the No_Display_Execute command for additional information.

If used, this parameter should appear at the end of the parameter list. If NO_DISPLAY is specified, TRACE should not be used.

<DLL_name:Function_name>

This parameter is optional but generally necessary when using XML commands.

The default DLL is TCXML.Dll and function is SendXMLMessage.

See XML_Sender for additional information.

Multiple TC Sessions

You can start multiple sessions (instances) of TC. This is useful to:

Each TC session must be started with a unique mailbox; DCConnect does not allow more than one application to request data from the same mailbox.

Each TC session should have a unique controller ID. This ID is used as the 'x' in the TC2ERRx.LOG error log file, TC2TRCx.nnn trace file, and TC2XACx.LOG transaction log file that are opened by each session. If the TC session is handling remote validation requests, the Controller ID is used as part of the default application name used when registering the TC session with DCConnect.

If more than one TC session is handling data requests, each must specify a unique application name.


TC Session Window

Each session of TC runs in its own GUI window. This window provides user controls for viewing current and past operation and error messages, changing operating modes, reviewing operating parameters, and shutting down the session.

When the session is Shutdown, the window remains so that you can view the status of the logoff commands. A second Shutdown must be issued to completely end the TC session (unless the Close_When_Complete script command is used).

Title Bar

The title bar tells you the TC program name and a bit about its operation status. The title bar shows:

  Transaction Connection:  Compiling

during the script compile process. When script is executing, you see:

  Transaction Connection Controller n

with n replaced by the controller ID character you specified on the command line. Note that you can change this text via the Title script command.

When the TC session has completed, the title bar changes to:

  Transaction Connection:  Completed

At this point, you can scroll any of the message boxes to see what was happening prior to the session shutting down, and then double-click on the window icon in the upper-left corner to close the window.

Menu Bar

The Menu Bar across the top of the window provides pull-down menu choices that include:


Stopping Transaction Connection

TC can be stopped by any of several methods:

If the Password command has been used to set a password for the window, you are prompted for this password before you can end the TC session. If there is no password, you are asked to verify that a shutdown is desired.

To give you a chance to review any messages in the TC windows, the TC session stops with the message Completed in the title bar of the window (unless the script command Close_When_Complete is used). Select shutdown/close again to complete the shutdown.

Any non-committed unit of SQL work is rolled back automatically as the session stops. If your script had not caused the last transaction read to be released, this transaction is read again from DCConnect the next time this TC session starts. No automatic transaction release is done upon a session shutdown.


Measuring and Improving Performance of TC Scripts

Execution Performance Timings

A window on the TC screen shows you the sequence of commands as they are executed for each script(assuming Display On is enabled in the TC Window). At the end of the script, a timing report is shown that provides some idea of throughput and what systems are taking the most time.

The Idle time is the amount of time that TC has been waiting for another transaction/request from DCConnect or to wait for the next StartTime, StartInterval or StartTimeout script to execute. When DCConnect has another transaction/request already in the queue, this time is usually negligible. If you see a large value, this indicates there was no transaction/request waiting in the queue, and therefore TC was waiting for this time period for some activity from a terminal or application.

The Tot.Txn.time shows the total time used from when the transaction/request was received from DCConnect or timed event occurred until the script completed. This includes the script's processing time, time spent waiting for the host screen to unlock, database processing time or time for an XML message to be processed.

The External time gives the time taken by database processing and/or time taken waiting for the host application screen to unlock and/or time spent waiting for a reply to an XML message. This is a component of the Tot.Txn.time discussed above.

With tracing turned on, the TC2TRCx.nnn file includes the approximate execution time in milliseconds for each command of the script. This is listed at the left margin of the trace listing file.

Your scripting has programmatic access to the execution time of the last script command/step, the total transaction time, and the external time via the data parts EXECUTION_TIME_LAST, EXECUTION_TIME_TOTAL, and EXECUTION_TIME_EXTERNAL.

Increasing Processing Speed

A sure method of increasing the number of transactions/requests that can be sent to the host each hour is to run multiple parallel sessions to multiple host terminal emulator screens. Each can sign on to unique sessions of the same host application and run identical scripts, with the terminals assigned so as to spread the load around equally. You can have each TC session handle only a specific transaction type from all of the terminals. This allows the host screen to be brought through all the menus required to get to a work screen and then stay there all day. Or, you may find that a combination of these designs is best. To get maximum throughput, you need to run benchmarking experiments to find the optimal number of TC/host sessions.

Execution Information Display

By default, the TC displays each step on the screen as it is executed. This is useful for seeing what is going on, but it does consume substantial processing time. You can improve processing speed by turning off this display using the command No_Display_Execute anywhere in your script command file. In applications where the database work is done quickly, this can increase throughput by as much as 10%. When database processing time is more substantial, the improvement is less.

Prior to version 3.1.0f, when Display mode was in effect, several web service commands (e.g. WS_SendRequest, WS_SendResponse) would show a popup with information about the command. In version 3.1.0f, displaying of these popups has been turned off by default. If there is a need to show these popups, the command WS_DisplayExecutePopups can be added to the scripts.

Multiple TC Sessions

To take advantage of the concurrency capabilities of DB2 and other database types, use several TC sessions processing transactions/requests from DCConnect against the same database, and even the same tables. This takes full advantage of slack time in the database engine when one session is off waiting for a DCConnect function call to return, and so forth. You can have multiple sessions processing the same types of transactions/requests using the same script, with workload divided by assigning physical terminals to one of the several parallel sessions, or you can have each session process specific types of transactions/requests from all terminals, or a combination of these methods.

Database Performance

For best database performance:

If using an ODBC connection to your database and performance is very slow, you may have ODBC tracing turned on. For instructions about how to check whether this option is on, please see Using an ODBC Database Connection.

Sending Data to the Host Screen

Text data being copied to the screen is copied directly to the presentation space, instead of being sent on a key-by-key basis. The only exception to this is when a control key is being sent. When control keys are present in the data stream, the key-by-key method must be used (this is an EHLLAPI restriction). For maximum performance, you would not want to combine a long string with an ENTER key control sequence in a user variable being sent to the host. You should send the string first, then separately send the control key(s). If there are any control characters in the data, TC automatically uses the key-by-key method of sending.

For best performance, especially when sending data to many widely scattered locations on the host display, use the Send_To_Host command rather than any of the other Send_Host... commands.

Multiple DCT Transactions to a Host Screen

TC commands enable you to take multiple transactions from the DCTs and safely and efficiently use them to fill in a multi-entry host application screen. For example, a host screen may have been designed for a human key-punch operator to input a stack of hardcopy time sheets. This screen has many lines to input many sets of start/stop times. For the DCTs, each input of a start/stop time is an individual transaction to DCConnect. You may want to increase raw throughput to a customized host screen by sending multiple, unrelated transactions with each press of the Enter key. The example below shows how commands can be used to transcribe each transaction to a line of the host screen, while keeping the transaction in the DCConnect mailbox until the entire host screen has been accepted. If the host crashes, the transactions can be re-read from DCConnect when the host is active again. A special StartTimeout script allows a partially full host screen to be submitted for processing when it becomes clear there are no more DCConnect transactions to be immediately read.

  Max_Xact_Wait( 2000 )       // Wait up to 2 seconds for another
                              // transaction to come in.  If none,
                              // go ahead and run the StartTimeout script
                              // to send the partial screen
  Multi_Release_Mode          // Setting to allow the next transaction
                              // to be read without need to release
                              // the prior one.
 
  ///////////////////////////////////////////////////////////////
  // Process a transaction from a DCT.
  ///////////////////////////////////////////////////////////////
  StartKey( F1 )
 
    UV_Math( UV1, +, 1 )      // Increment transactions-on-screen
                              // counter, which is also used to
                              // determine which row will be used.
                              // Transactions are written to rows
                              // 5 through 19, column 5.
 
    UV_Math( UV2, =, 4 )      // UV2 is used to calculate the row
    UV_Math( UV2, +, UV1 )    // (4 plus the UV1 value )
 
                              // Copy transaction data to the correct
                              // row, no cursor movement, call subroutine
                              // LOCKED if the field is locked.
    Send_To_Host ( TXNDATA, 0, 15, UV2_VALUE, 5, NONE, LOCKED )
 
    If ( UV1 #= "15" )               // If screen is full, send it all to the
      CallSubroutine( Send_Screen )  // host.
 
  EndKey()
 
  ///////////////////////////////////////////////////////////////
  // The StartTimeout script will send any partial screen of data
  // left when the DCTs become inactive, rather than make the
  // transactions sit there waiting for a whole screen.
  ///////////////////////////////////////////////////////////////
  StartTimeout()
 
    If ( UV1 #= "0" ) // UV1 tells how many transactions are
      Goto ALL_DONE   // currently on the host screen.
                      // If 0, no need to send Enter key
 
    CallSubroutine( Send_Screen )
 
  ALL_DONE:
 
  EndTimeout()
 
  ///////////////////////////////////////////////////////////////
  // This routine sends the screen of transactions and
  // calls another routine to check for edit errors; it
  // releases the transactions from DCConnect mailbox and resets the
  // UV1 counter.
  ///////////////////////////////////////////////////////////////
  StartSubroutine( Send_Screen )
 
    Send_To_Host( ENTER )     // Enter will send all transactions on
                              // the screen to the host.
 
 
    UV_Math( UV1, = , 0 )     // Now there are no transactions on the
                              // screen.
 
    Call_Subroutine( Check_&_Correct_Errors) // Write this routine to check
                              // the screen for any edit errors detected
                              // by the host application, and attempt
                              // to correct them, and log the errors.
 
    Release_Xact()            // Releases transactions from DCConnect mailbox
                            // up through the last one read by TC.
  EndSubroutine()
 
  ///////////////////////////////////////////////////////////////
  // This routine handles the case where the host screen is
  // locked/inhibited when trying to copy data to the screen.
  ///////////////////////////////////////////////////////////////
  StartSubroutine( LOCKED )
 
    ... Use Check_Screen, Check_Cursor, If statements, and so
        forth to determine recovery from host problem.  If
        successful at saving logon and data on the screen
        (for example, removing a sys op message from the screen),
        retry sending this transaction and return.
        Otherwise, Cycle the DCConnect Mailbox connection to
        reset DCConnect mailbox pointers to last released transaction,
        reset the UV1 counter, Cycle the host session, and re-logon.
 
  RESEND_TXN:
    Send_To_Host ( TXNDATA, 0, 15, UV2_VALUE, 5, NONE, LOCKED )
    Goto END_LOCKED_SUBR
 
  CYCLE:
    Cycle_Mailbox()
    UV_Math( UV1, =, 0 )
    Cycle_Session( )
    CallSubroutine( Logon_Subr ) // Same commands as used for StartLogon
 
  END_LOCKED_SUBR:
 
  EndSubroutine()

Testing and Debugging Your Scripts Using the Trace Command

If the command Trace is included anywhere in the command script file, then TC creates a trace file (TC2TRCx.nnn) containing a chronological listing of all commands executed. The number to the left of each trace line represents approximately how many milliseconds each command too to execute (including the substantial time taking to actually log this data). This data is very useful for analysing the impact of your SQL statements on execution time (look at the End_SQL / End_SQL2 / End_Select / End_Select2 or Perform... statements). Included is information on the contents of the user variables at entry to the script, updated values of the user variables after each command that can effect them, the transaction record being processed, and the SQL statement and any error messages logged.
Note:In the user variable listings only non-empty user variables are shown.
If any Trace command is included in the command script file, all execution with that script is in trace mode. To end trace mode, click the On menu item in the Trace pull-down menu. If the Trace command is in the script file, you may want to comment it out so future startups do not come up in trace mode.

The Trace command overrides any No_Display_Execute command in the script file. The expanded execution information is shown in the execution window of the TC window.

Error Log File

All errors encountered by TC are logged into the TC2ERRx.LOG file (where x is the single-character controller ID for the TC session).

Whenever an SQL error is encountered, the SQLSTATE and native code values are logged to the error log as well as the message text returned by DB2 or the ODBC driver. TC will also include the the text of your SQL statement and the data from the transaction that was in progress when the error occurred (data from a remote validation is not logged).

If the SQL error code was one for which you had set a special handling vector with On_Error_Goto, no error logging is done as it is assumed that your recovery code will do what is required.

You can add your own messages to the error log file with the command Log_Error.


Using TC to Generate Reports

Creating Reports from Host Screens

You can create formatted reports from the data on the host screens by utilizing various TC commands. The report can be sent directly to the terminal, written to a disk file, or both. A report on a disk file can be used for audit purposes, processed by another application (see Sending Reports to a DCT), and so forth.

The following example shows how to create a report of the quantity (count) of work items claimed by each worker (as identified by badge number). (This assumes there is some host application capable of showing this result on the screen, given the data provided in a transaction from the DCT).

  StartKey(F2)
 
    // Create a report from host screen listing bin locations
    // where product is stored.  Format the report for printing
    // at the terminal to look like this:
    //
    //    Part Number:  xxxxxxxxxxx
    //    Bin Number     Quantity in Bin
    //    ----------     ---------------
    //    bbbbbbbb       qqqqqqqq
    //    bbbbbbbb       qqqqqqqq
 
    // Take only the first 5 listings on the screen
 
    // Cause any existing report file to be overwritten.
    // The file name will be "REPORT.XYZ", where XYZ is uniquely
    // created from the data collection terminal's physical
    // connection to a communications adapter (X), the line number
    // on that adapter (Y), and the address character of the
    // terminal (Z).
    Clear_UV( UV1 )
    Log_Data(REPORT, UV1, OVERWRITE )
 
    Clear_UV(UV1)
    Clear_UV(UV2)
    Append_UV_Kbd_Data( UV1, "Part Number: ")
    Append_UV_Host_Data( UV1, 5, 25, 7)       // PN on screen
    Append_UV_Kbd_Data( UV1, CRLF)
 
    Append_UV_Kbd_Data( UV1, "Bin Number     Quantity in Bin")
    Append_UV_Kbd_Data( UV1, CRLF)
    Append_UV_Kbd_Data( UV1, "----------     ---------------")
    Append_UV_Kbd_Data( UV1, CRLF)
 
    // Write the report header to disk
    Log_Data ( REPORT, UV1, APPEND )
 
    // Get first 5 lines from host screen, stopping if
    // we hit a blank line (less than 5 available)
    // Bin/Qty data is one lines 10-20 of the host screen,
    // starting in column 10
    // Use
    Clear_UV( UV1 )
    UV_Math ( UV2, =, 10)
 
  LOOP_TOP:
 
    // UV2 will have values 10, 11,...,14, 15
    Append_UV_Host_Data( UV1, UV2_VALUE, 10, 20)
    Append_UV_Kbd_Data( UV1, CRLF)
 
    UV_Math( UV2, +, 1)       // Increment loop counter
 
    If (UV2 #<= "14" )
      Goto LOOP_TOP
 
    // Above loop will put 10 * (20 data + CRLF) = 220
    // characters in UV1, which is less than the 235
    // max for that user variable
    Log_Data ( REPORT, UV1, APPEND )
 
    Release_Xact()
 
  EndKey

Creating Reports from the Database

You can create formatted reports from the database by utilizing various TC commands. The report can be sent directly to the terminal, written to a disk file, or both. A report on a disk file can be used for audit purposes, processed by another application (see Sending Reports to a DCT), and so forth.

The following example shows how to create a report of the quantity (count) of work items claimed by each worker (as identified by badge number) since a time given in a timestamp value in the terminal transaction. The optional format specifier of the Append_UV_Select_Data command is used to maintain a nice columnar alignment in the report.

  StartKey(F2)
 
    // Cause any existing report file to be overwritten.
    // The file name will be "REPORT.XYZ", where XYZ is uniquely
    // created from the data collection terminal's physical
    // connection to a communications adapter (X), the line number
    // on that adapter (Y), and the address character of the
    // terminal (Z).
    Clear_UV( UV1 )
    Log_Data(REPORT, UV1, OVERWRITE )
 
    // Create the SQL statement that counts the number
    // of records resulting after finding only those records
    // created on or after a time specified in the transaction
    // and after grouping those records by the badge number.
    Select_From_DB_Table( LABOR_CLAIMS )
 
    Select_Column( COUNT(*) )
    Select_Column( BADGE )
 
    Select_Where( CLAIM_STAMP, TIMESTAMP, >= , TXNDATA, 0, 12 )
    Select_Group_By( BADGE )
 
    Perform_Select(SQLerror)
 
    // Keep fetching records from the SQL report until
    // the end of the report is reached.
    // Created a formatted user variable with
    // the data from the SQL report, add a carriage return
    // and line feed for readability,
    // append this line to the disk file.
    Fetch_more:
 
    Perform_Fetch(No_more_data_27);
 
    Clear_UV(UV1)
    Clear_UV(UV2)
 
    Append_UV_Kbd_Data( UV1, "BADGE = ")
    Append_UV_Select_Data( UV1, 2, SQLerror, 7 )
    Append_UV_Kbd_Data( UV1, " ; COUNT OF RECORDS = ")
    Append_UV_Select_Data( UV1, 1, SQLerror, 7)
    Append_UV_Kbd_Data( UV1, CRLF)
    Log_Data ( REPORT, UV1, APPEND )
 
    Goto( Fetch_more )
 
  No_more_data_27:
 
    Release_Xact()
 
  EndKey

Sending Reports to a DCT

It is easy to send simple reports to a data collection terminal for printing or displaying. A simple report would have a known and limited size that will fit into the user variable space of the DCT. The terminal clears each user variable that will be used, and then sends the transaction or remote validation request to the TC session through DCConnect. The terminal then watches one of the user variables that serves as a flag indicating that all data from the TC session has now arrived (this user variable may contain useful data, serving as the flag by simply NOT being null). The terminal transaction program uses the TEST and GOTO commands in a tight loop to watch for the flag user variable to be set. When the flag is set, it can proceed to present or print the data from all the user variables, including the flag user variable.

An enhancement to this scenario would be to have a CFR (custom function routine, a user C language extension to the terminal commands) that watches the user variable and watch the clock at the same time to provide a timeout in case the database is inactive or overloaded. In addition, the CFR can verify that when the user variable is eventually set that it contains the proper 'tag' for the transaction that was sent. (see Recommended Design Rules)

More elaborate programming on the DCT can be used to provide for transfer of large amounts of data from the database query into storage on the terminal, and for presentation of this data to the worker (including scrolling and selecting data).


Using One TC Session to Monitor / Control Other TC Sessions and the DCConnect Server

Starting in version 3.1.0d, TC now maintains shared memory that all TC sessions update so that any session can get information about and control other TC sessions. Although any TC session could control / monitor others, it is probably best to have a single TC session serve that function. That session could also act as a web service provider, thus allowing web pages to be set up to control / monitor all TC sessions. The TC commands used to control / monitor other TC sessions are:

In addition to working with other TC sessions, TC has a full set of commands for monitoring and controlling the DCConnect Server, allowing it perform all of the runtime functions that the DCConnect User Interface provides, including: