Visual Basic Interface

This chapter describes functions used by a Visual Basic interface with examples.

1. Overview

Unlike Power Builder, a Visual Basic interface does not exist as a separate module. It is an interface module that defines function prototypes so that a developer can directly call a client library.

Visual Basic interface modules are as follows.

Module Description

atmi.bas

File that defines a prototype for atmi functions.

fdl. Bas

File that defines a prototype for field key functions.

comm.bas

File that defines user macros.

ilewinapi.bas

File that defines functions provided by Windows.

Developers can call the functions provided by a Tmax client library by installing the Visual Basic interface modules. However, be aware that the Visual Basic interfaces send values in a way that is different from other applications. In addition, the Visual Basic interfaces provide users with a Macro (comm.bas) to internally input and output data, instead of allowing them directly manipulate buffers.

Macro provides the following functions.

Function Description

FdlErrorMsg

Displays fberrno in a MsgBox with the provided StrErr message.

FilltpstartBuf

Configures the tpstart_t struct, a buffer that needs to be configured to connect to the Tmax system.

GETCAR

Inserts a string into the CARRAY buffer.

GETCAR_BA

Saves image data in a position of a field specified by a field name and a field index in byte array.

GETCHR

Retrieves a value in a position of the field buffer specified by a field name and by the nth position set by fbchg_tu(), a Tmax FDL function. The value is CHAR type.

GETDOUBLE

Saves double data in a position of the field buffer specified by a field index and field name in dData.

GETFLOAT

Saves single data in a position of the field buffer specified by a field index and a field name in dData.

GETINT

Saves integer data in a position of a field specified by a field index and field name in iData .

GETLONG

Saves long data of a field specified by a field index and a field name as iData.

GETSTR

Saves the data of the string buffer in text.

GETVAR

Retrieves string data in a position of the field buffer specified by a field index and a field name in order to save the data as text.

PUTCAR

Saves the string data in the CARRAY buffer as text.

PUTCAR_BA

Saves byte array of image data in the field buffer according to the field index.

PUTCHR

Saves a value in a field specified by a field name and by the nth position set by fbchg_tu(), a Tmax FDL function.

PUTDOUBLE

Inserts double data in a position of the field buffer specified by a field name and a field index.

PUTFLOAT

Inserts single data in a position of the field buffer specified by a field index.

PUTINT

Inserts integer data in a position of a field buffer specified by a field index.

PUTLONG

Inserts long data in a position of a field buffer specified by a field index.

PUTSTR

Inserts data in a string buffer as text.

PUTVAR

Inserts string data in a position of the field buffer specified by a field index.

TmaxError

Displays a string error that corresponds to tperrno as MsgBox, along with the given StrErr message.

For more information about prototypes and features of atmi and field key functions, refer to Tmax Reference Guide and Tmax Application Development Guide.

2. Functions

2.1. FdlErrorMsg

Displays fberrno in a MsgBox with the provided StrErr message.

  • Prototype

    Sub FdlErrorMsg(StrErr As String)
  • Parameter

    Parameter Description

    StrErr

    Error message.

  • Return value

    Displays a message box.

  • Example

    lret = fbput(ByVal lsendbuf, ByVal lfid, ByVal txtInput.text, ByVal 0)
    If lret = -1 Then
       FdlErrorMsg("fbput")
       error processing
       …
    End If
  • Related functions

    TmaxError()

2.2. FilltpstartBuf

Configures the tpstart_t struct, a buffer that needs to be configured to connect to the Tmax system.

  • Prototype

    Function FilltpstartBuf(sndbufp As Long, startinfop As tpstart_t)
    As Long
  • Parameter

    Parameter Description

    sndbufp

    Buffer to be allocated to the memory by the tpalloc function.

    startinfop

    Variable defined in the tpstart_t type.

  • Example

    Dim lsndbuf  As Integer
    Dim lret  As Integer
    Dim cinfo As tpstart_t
    
    lsndbuf = tpalloc("TPSTART", "", 0)
    If lsndbuf = 0 Then
        error processing
    End If
    
    cinfo.cltname = "tmax" + Chr(0)
    cinfo.usrname = "tmax" + Chr(0)
    cinfo.dompwd = "xamt" + Chr(0)
    cinfo.usrpwd = "batman" + Chr(0)
    cinfo.flags = TPUNSOL_HND
    
    lret = FilltpstartBuf(lsndbuf, cinfo)
    If ret < 0 Then
       error processing
    End If
    
    ret = tpstart(lsndbuf)
    If ret < 0 Then
       error processing
    End If
    …
  • Related functions

    TmaxError()

2.3. GETCAR

Inserts a string into the CARRAY buffer.

  • Prototype

    Function GETCAR(ByVal Carptr&, text As String, Datalen As Long)
    As Long
  • Parameter

    Parameter Description

    Carptr

    Pointer to the FDL.

    text

    Data.

    Datalen

    Length of the data.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lrecvbuf As Long
    Dim text As String
    Dim lret As Long
    Dim lrbuflen As Long
    …
    lsendbuf = tpalloc("CARRAY", "", 1024)
    lrecvbuf = tpalloc("CARRAY", "", 1024)
    …
    lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal DataLen&, lrecvbuf, lrbuflen,
                  ByVal 0)
    …
    'Data length must be set in the CARRAY buffer.
    lret = GETCAR(lsendbuf, text, lrbuflen)
    …
  • Related functions

    GETINT(), GETLONG(), GETDOUBLE(), GETVAR(), GETSTR(), GETFLOAT(), GETSTR(), GETCHR()

2.4. GETCAR_BA

Saves image data in a position of a field specified by a field name and a field index in byte array.

  • Prototype

    Function GETCAR_BA (ByVal Fdlptr&, Field As String, idx As Long,
                        ByRef ByteArray() As Byte, datalen As Long)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    ByteArray

    Data.

    datalen

    Length of the byte array.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim rbuffer(102400) As Byte
    Dim datalen As Long
    …
    lrecvbuf = tpalloc("FIELD", "", 102400)
    …
    lret = PUTCAR_BA(ByVal lsendbuf, "TP_BITMAP", 0, lbuffer, datalen)
    if lret < 0 then
        error processing
        …
    end if
    …
    lret = tpcall(ByVal "FILEUP", ByVal lsendbuf, ByVal datalen&, lrecvbuf,
                 lrbuflen, ByVal 0)
    lblComment.Caption = lblComment.Caption & " -> tpcall : " & lret
    If lret = -1 Then
        error processing
        …
    end If
    …
    lret = GETCAR_BA(ByVal lrecvbuf, "TP_BITMAP", 0, rbuffer, datalen)
    if lret < 0 then
        error processing
        …
    end if
    …
  • Related functions

    GETINT(), GETLONG(), GETDOUBLE(), GETCAR(), GETVAR(), GETFLOAT(), GETSTR(), GETCHR()

2.5. GETCHR

Retrieves a value in a position of the field buffer specified by a field name and by the nth position set by fbchg_tu(), a Tmax FDL function. The value is CHAR type.

  • Prototype

    Function GETCHR(ByVal Fdlptr&, ByVal Field As String, ByVal idx As Integer,
                    ByRef data As String, ByVal datalen As Integer)
    As Integer
  • Parameter

    Parameter Description

    Fldptr

    Pointer to the string buffer.

    Field

    Field name.

    idx

    Field index.

    data

    String data to be stored.

    datalen

    Length of the string data to be stored.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim chr As String
    lsendbuf = fballoc(10, 100)
    Irecvbuf = fballoc(10, 100)
    …
    lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal DataLen&, lrecvbuf, lrbuflen,
                  ByVal 0)
    …
    lret = GETSTR(lrecvbuf, "CHR", 0, chr, 1 )
    …
  • Related functions

    GETINT(), GETLONG(), GETDOUBLE(), GETVAR(), GETSTR(), GETCAR(), GETFLOAT()

2.6. GETDOUBLE

Saves double data in a position of the field buffer specified by a field index and field name in dData.

  • Prototype

    Function GETDOUBLE(ByVal Fdlptr&, Field As String, idx As Long, dData As Double)
    As Long
  • Parameter

    Parameter Description

    Fldptr

    Pointer to the string buffer.

    Field

    Field name.

    idx

    Field index.

    data

    String data to be stored.

    datalen

    Length of the string data to be stored.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim doubledata As Double
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = GETDOUBLE(ByVal lsendbuf, "DOUBLEDATA", 0, doubledata)
    …
  • Related functions

    GETINT(), GETLONG(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()

2.7. GETFLOAT

Saves single data in a position of the field buffer specified by a field index and a field name in dData.

  • Prototype

    Function GETFLOAT (ByVal Fdlptr&, Field As String, idx As Long, dData As Single)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    dData

    Data.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim doubledata As Single
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = GETFLOAT (ByVal lsendbuf, "DOUBLEDATA", 0, doubledata)
    …
  • Related functions

    GETINT(), GETLONG(), GETVAR(), GETCAR(), GETSTR(), GETCHR(), GETDOUBLE()

2.8. GETINT

Saves integer data in a position of a field specified by a field index and field name in iData.

  • Prototype

    Function GETINT(ByVal Fdlptr&, Field As String, idx As Long, iData As Integer)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    iData

    Data.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim intdata As Integer
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    
    lret = GETINT(ByVal lsendbuf, "INTDATA", 0, intdata)
    …
  • Related functions

    GETLONG(), GETDOUBLE(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()

2.9. GETLONG

Saves long data of a field specified by a field index and a field name as iData.

  • Prototype

    Function GETLONG(ByVal Fdlptr&, Field As String, idx As Long, lData As Long)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    iData

    Data.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim longdata As Long
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = GETLONG(ByVal lsendbuf, "LONGDATA", 0, longdata)
    …
  • Related functions

    GETINT(), GETDOUBLE(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()

2.10. GETSTR

Saves the data of the string buffer in text.

  • Prototype

    Function GETSTR(ByVal strptr&, text As String)
    As Long
  • Parameter

    Parameter Description

    strptr

    Pointer to the string buffer.

    text

    Data.

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim text As String
    
    lsendbuf = fballoc(10, 100)
    Irecvbuf = fballoc(10, 100)
    …
    lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal DataLen&, lrecvbuf, lrbuflen,
                  ByVal 0)
    …
    lret = GETSTR(lrecvbuf, text)
    …
  • Related functions

    GETINT(), GETLONG(), GETDOUBLE(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()

2.11. GETVAR

Retrieves string data in a position of the field buffer specified by a field index and a field name in order to save the data as text.

  • Prototype

    Function GETVAR(ByVal Fdlptr&, Field As String, idx As Long, text As String)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    iData

    Data

  • Return value

    Return value Description

    1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = GETVAR(ByVal lsendbuf, "INPUT", 0, txtOutput.text)
    …
  • Related functions

    GETINT(), GETLONG(), GETDOUBLE(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()

2.12. PUTCAR

Saves the string data in the CARRAY buffer as text.

  • Prototype

    Function PUTCAR(ByVal Carptr&, text As String, Datalen As Long)
    As Long
  • Parameter

    Parameter Description

    Carptr

    Pointer to the FDL buffer.

    text

    Data.

    Datalen

    Length of the data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lret As Long
    Dim DataLen As Long
    lsendbuf = tpalloc("CARRAY", "", 1024)
    'The length of the data must be entered in the CARRAY buffer.
    
    DataLen = LenB(txtInput.text)
    
    lret = PUTCAR(ByVal lsendbuf, txtInput.text, DataLen)
    …

    Data can be entered to the string buffer by using the lstrcpy function provided by the system.

    Dim lsendbuf As Long
    Dim lret As Long
    
    lsendbuf = tpalloc("STRING", "", 1024)
    lret = lstrcpy(ByVal lsendbuf, ByVal txtInput.text)
  • Related functions

    PUTINT(), PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR()

2.13. PUTCAR_BA

Saves byte array of image data in the field buffer according to the field index.

  • Prototype

    Function PUTCAR_BA(ByVal Fdlptr&, Field As String, idx As Long, ByteArray()
                       As Byte, datalen As Long)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    ByteArray

    Data.

    datalen

    Length of the byte array.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim iSrc As Integer
    Dim lCopy As Long
    Dim lSize As Long
    Dim lbuffer() As Byte
    Dim datalen As Long
    …
    lsendbuf = tpalloc("FIELD", "", 102400)
    …
    iSrc = FreeFile
    Open ".\nmlogo.bmp" For Binary Access Read As iSrc
    lSize = LOF(iSrc)
    datalen = lSize
    Do
        If lSize > MAX_BUFFER Then
           lSize = lSize - MAX_BUFFER
           lCopy = MAX_BUFFER
        Else
           lCopy = lSize
        End If
    
        ReDim lbuffer(lCopy - 1)
        Get iSrc, , lbuffer
    Loop Until lCopy = lSize
    
    Close iSrc
    
    lret = PUTCAR_BA(ByVal lsendbuf, "TP_BITMAP", 0, lbuffer, datalen)
    if lret < 0 then
        error processing
        …
    end if
    …
  • Related functions

    PUTINT(), PUTLONG(), PUTDOUBLE(), PUTCAR(), PUTVAR(), PUTFLOAT(), PUTSTR(), PUTCHR()

2.14. PUTCHR

Saves a value in a field specified by a field name and by the nth position set by fbchg_tu(), a Tmax FDL function. The CHAR type is used to save the data. If data already exists in the nth field, the data will be changed to the given value. If data does not exist in the nth field, the given data will be automatically added to the field.

  • Prototype

    Function PUTCHR(ByVal Fdlptr&, ByVal Field As String, ByVal idx As Integer,
                    ByRef data As String, ByVal datalen As Integer)
    As Integer
  • Parameter

    Parameter Description

    Fldptr

    Pointer to the string buffer.

    Fieldt

    Field name.

    idx

    Field index.

    data

    String data to be stored.

    datalen

    Length of the string data to be stored.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim chr As String
    
    lsendbuf = fballoc(10, 100)
    chr = "a"
    …
    lret = PUTSTR(lsendbuf, "CHR", 0, chr, 1 )
    …
    Function PUTCHR(ByVal Fdlptr&, ByVal Field As String, ByVal idx As Integer,
                    ByRef data As Char, ByVal datalen As Integer)
  • Related functions

    PUTINT(), PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR()

2.15. PUTDOUBLE

Inserts double data in a position of the field buffer specified by a field name and a field index.

  • Prototype

    Function PUTDOUBLE(ByVal Fdlptr&, Field As String, idx As Long, dData As Double)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    dData

    Data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim doubledata As Double
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = PUTDOUBLE(ByVal lsendbuf, "DOUBLEDATA", 0, doubledata)
    …
  • Related functions

    PUTINT(), PUTLONG(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()

2.16. PUTFLOAT

Inserts single data in a position of the field buffer specified by a field index.

  • Prototype

    Function PUTFLOAT(ByVal Fdlptr&, Field As String, idx As Long, dData As Single)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    dData

    Data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim doubledata As Single
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = PUTFLOAT(ByVal lsendbuf, "DOUBLEDATA", 0, doubledata)
    …
  • Related functions

    PUTINT(), PUTLONG(), PUTVAR(), PUTCAR(), PUTDOUBLE(), PUTSTR(), PUTCHR()

2.17. PUTINT

Inserts integer data in a position of a field buffer specified by a field index.

  • Prototype

    Function PUTINT(ByVal Fdlptr&, Field As String, idx As Long, iData As Integer)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    iData

    Data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim intdata As Integer
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = PUTINT(ByVal lsendbuf, "INTDATA", 0, intdata)
    …
  • Related functions

    PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()

2.18. PUTLONG

Inserts long data in a position of a field buffer specified by a field index.

  • Prototype

    Function PUTLONG(ByVal Fdlptr&, Field As String, idx As Long, lData As Long)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    lData

    Data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim longdata As Long
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = PUTLONG(ByVal lsendbuf, "LONGDATA", 0, longdata)
    …
  • Related functions

    PUTINT(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()

2.19. PUTSTR

Inserts data in a string buffer as text.

  • Prototype

    Function PUTSTR(ByVal strptr&, text As String)
    As Long
  • Parameter

    Parameter Description

    strptr

    Pointer to the string buffer.

    text

    Data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    Dim text As String
    
    lsendbuf = tpalloc("STRING", "", 1024)
    …
    lret = PUTSTR(lsendbuf, text)
    …
  • Related functions

    PUTINT(), PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTCHR()

2.20. PUTVAR

Inserts string data in a position of the field buffer specified by a field index.

  • Prototype

    Function PUTVAR(ByVal Fdlptr&, Field As String, idx As Long, text As String)
    As Long
  • Parameter

    Parameter Description

    Fdlptr

    Pointer to the FDL buffer.

    Field

    Field name.

    idx

    Field index.

    text

    Data.

  • Return value

    Return value Description

    Value other than -1

    Function call is successful.

    -1

    Function call failed.

  • Example

    Dim lsendbuf As Long
    Dim lret As Long
    
    lsendbuf = tpalloc("FIELD ", "", 0)
    …
    lret = PUTVAR(ByVal lsendbuf, "INPUT", 0, txtInput.text)
    …
  • Related functions

    PUTINT(), PUTLONG(), PUTDOUBLE(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()

2.21. TmaxError

Displays a string error that corresponds to tperrno as MsgBox, along with the given StrErr message.

  • Prototype

    Sub TmaxError(StrErr As String)
  • Parameter

    Parameter Description

    StrErr

    Error message.

  • Return value

    Displays a message window.

    image

  • Example

    Dim lsendbuf As Long
    Dim lrecvbuf As Long
    Dim lret As Long
    Dim lrbuflen As Long
    
    lsendbuf = tpalloc("CARRAY", "", 1024)
    lrecvbuf = tpalloc("CARRAY", "", 1024)
    lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal 0, lrecvbuf, lrbuflen, ByVal 0)
    
    If lret = -1 Then
       TmaxError ("tpcall (SVC1)")
    End If
  • Related functions

    FdlErrorMsg()

3. Example Program

A client program sends a service request that was received by a user. A server inserts, updates, inquires, and deletes data from the employee information (EMP) table of the Oracle database as the client requested.

3.1. Program Configuration

Both server and client environments must have been configured to use a client program. TMAXDIR, port number, and server IP are assumed to have been already configured.

The following example files are added as a module in a project.

  • <atmi.bas>

  • <fdl.bas>

  • <comm.bas>

  • <winapi.bas>

Each program consists of the following files.

  • Common programs

    Program File Description

    demo.f

    File that defines a field key buffer.

    tmax

    Library file.

    tmconfig.m

    Tmax environment configuration file.

  • Client programs

    Program File Description

    EmployeeGrid.frm

    Program that shows inquiry results.

    EmployeeGrid.frx

    Program that shows inquiry results.

    EmployeeMgr.frm

    Main program that inquires, updates, deletes, and inserts.

    MSSCCPRJ.SCC

    Source code control file.

    QA_4GL.vbg

    Client program group project file.

    QA_4GL_Sample.exe

    Client program executable file.

    QA_4GL_Sample.vbp

    Client program project file.

    QA_4GL_Sample.vbw

    Client program workspace file.

    Atmi.bas

    File that defines a prototype for atmi functions.

    comm.bas

    User macro definition file

    fdl.bas

    File that defines a prototype for field key functions.

    winapi.bas

    Function definition file provided by Windows.

  • Server program

    Program File Description

    emp_c.mk

    Makefile.

    emp_c.pc

    Server program that provides service. AIX and Oracle 9i are used.

3.2. Program Features

The following describes the features of each program.

  • Client programs

    Function Description

    Tmax connection

    NULL argument is used.

    Buffer type

    An 'fdl' file needs to be created by compiling a FIELD KEY buffer and a struct file.

    Communication mode

    A send buffer and a receive buffer must be specified differently for tpcall().

    Transaction option

    TMS allocates AutoTransaction.

  • Server programs

    Function Description

    Service

    FDLSELECT, FDLINSERT, FDLDELETE, and FDLUPDATE need to be created.

    Database

    Oracle database. Database information is specified in SVRGROUP of a system configuration file.

    Communication type

    A send buffer and a receive buffer must be specified differently for tpcall().

    Transaction option

    TMS allocates AutoTransaction.

3.3. Common Programs

DataBase EMP Table

The following is an example of Tmax EMP database (Oracle) table.

EMPNO          NUMBER            NOT NULL         P1
ENAME          VARCHAR(16)
JOB            VARCHAR(16)
MGR            NUMBER
HIREDATE       DATE
SAL            NUMBER(7,2)
COMM           NUMBER(7,2)
DEPTNO         NUMBER
Tmax EMP Field Table

The following is an example of Tmax EMP field table.

<demo.f>

#For tmax demo employee program
EMPNO             7500                   long         -                        -
ENAME             7501                   string       -                        -
JOB               7502                   string       -                        -
MGR               7503                   long         -                        -
DATE              7504                   string       -                        -
SAL               7505                   float        -                        -
COMM              7506                   float        -                        -
DEPTNO            7507                   long         -                        -
E_TYPE            9009                   long         -                        -
E_CODE            9010                   long         -                        -
E_MSG             9011                   string       -                        -
E_TMP             9012                   long         -                        -
Tmax Environment Configuration

The following shows an example of Tmax environment configuration file.

<tmconfig.m>

*DOMAIN
dom1       SHMKEY = 70000, MAXUSER = 200, MINCLH = 1, MAXCLH = 5,
           TPORTNO = 8888, BLOCKTIME = 200, TXTIME = 200

*NODE
tmax1      TMAXDIR = "/home/tmax",
           APPDIR = "/home/tmax/appbin",
           PATHDIR = "/home/tmax/path",
           TLOGDIR = "/home/tmax/log/tlog",
           SLOGDIR = "/home/tmax/log/slog"
           ULOGDIR = "/home/tmax/log/ulog"

*SVRGROUP
svg1        NODENAME = tmax1,
            DBNAME = ORACLE,
            OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60",
            TMSNAME = svg1_tms

*SERVER
emp_c       SVGNAME = svg1, MIN = 1

*SERVICE
FDLSELECT   VRNAME = emp_c
FDLUPDATE   SVRNAME = emp_c
FDLDELETE   SVRNAME = emp_c
FDLINSERT   SVRNAME = emp_c

3.4. Client Programs

Main Screen Format Design

The following shows a main screen format.

image

The following table shows the components of a main screen format.

Control name Control type Note

EmployeeMgr

Form

Caption="Employee management program"

LabelErr

Label

Caption="Error"

BtnExit

Command button

Caption="Close"

BtnIns

Command button

Caption="Insert"

BtnDel

Command button

Caption="Update"

BtnUdt

Command button

Caption="Query"

BtnSel

Command button

EditName

Text box

EditEmpNo

Text box

EditDept

Text box

EditComm

Text box

EditSal

Text box

EditDate

Text box

EditMgr

Text box

EditJob

Text box

The following example executes a designed main screen format.

EmployeeMgr.frm Source
Option Explicit

Private Sub BtnDel_Click()

    Dim Isendbuf As Long
    Dim Irecvbuf As Long
    Dim Irbuflen As Long
    Dim Iret As Long
    Dim text As String
    Dim value As Long
    Dim dvalue As Double
    Dim svalue As Single
    Dim tx_b As Integer
    Dim txbool As Integer 'If a transaction begins, 1 is returned. Otherwise 0 is returned.'

    ' tpstart '
    tmaxStart

    'Initializes the option to begin a transaction'
    txbool = 0

    If EditEmpNo.text = "" Then
        MsgBox "Enter the emloyee number."
        tmaxEnd
        Exit Sub
    End If

    value = Trim(EditEmpNo.text)


    ' Allocate a buffer to send data '
    Isendbuf = fballoc(100, 1024)
    If Isendbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Isendbuf)
        tmaxEnd
        Exit Sub
    End If

    ' Allocate a buffer to receive data '
    Irecvbuf = fballoc(100, 1024)
    If Irecvbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Irecvbuf)
        tmaxEnd
        Exit Sub
    End If

    Iret = PUTLONG(ByVal Isendbuf, "EMPNO", 0, value)
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Initiate a transaction '
    Iret = tx_begin
    txbool = 1
    If Iret < 0 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Request for an inquiry service '
    Iret = tpcall(ByVal "FDLDELETE", ByVal Isendbuf, ByVal 0, Irecvbuf,
                  Irbuflen, ByVal 0)

    LabelErr.Caption = "sbuf = " & Isendbuf & ", rbuf = " & Irecvbuf

    If Iret = -1 Then
        TmaxError ("tpcall(SVC1)")
        ViewErr (Irecvbuf)
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Save a transaction '
    Iret = tx_commit
    If Iret < 0 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    Else
        txbool = 1
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

End Sub

Private Sub BtnExit_Click()
    End
End Sub

Private Sub BtnIns_Click()

    Dim Isendbuf As Long
    Dim Irecvbuf As Long
    Dim Irbuflen As Long
    Dim Iret As Long
    Dim text As String
    Dim value As Long
    Dim dvalue As Double
    Dim svalue As Single
    Dim lenL As Long
    Dim txbool As Integer ' If a transaction begins, 1 is returned. Otherwise 0 is returned '

    ' tpstart '
    tmaxStart

    ' Initializes the option to begin a transaction '
    txbool = 0

    If EditEmpNo.text = "" Then
        MsgBox "Enter the employee number."
        tmaxEnd
        Exit Sub
    End If

    ' Allocate a buffer to send data. '
    Isendbuf = fballoc(100, 1024)
    If Isendbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Isendbuf)
        tmaxEnd
        Exit Sub
    End If

    ' Allocate a buffer to receive data. '
    Irecvbuf = fballoc(100, 1024)
    If Irecvbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Irecvbuf)
        tmaxEnd
        Exit Sub
    End If

    Iret = PUTLONG(ByVal Isendbuf, "EMPNO", 0, Trim(EditEmpNo.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTVAR(ByVal Isendbuf, "ENAME", 0, Trim(EditName.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTVAR(ByVal Isendbuf, "JOB", 0, Trim(EditJob.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTLONG(ByVal Isendbuf, "MGR", 0, Trim(EditMgr.text))
    If Iret = -1 Then    ' Initiate a transaction '
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTVAR(ByVal Isendbuf, "DATE", 0, Trim(EditDate.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    svalue = Trim(EditSal.text)
    ' The definition of fbput and fbget_fldkey functions are specified in the comm.bas file. '
    ' The fbget_fldkey function converts a field name to a key value. '
    Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("SAL"), svalue, ByVal lenL)
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' The below comment can function the same as its subsequent statement. '
    'svalue = Trim(EditComm.text)
    'Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("COMM"), svalue, ByVal lenL)
    'If Iret = -1 Then
    '    FdlErrorMsg ("fbput")
    '    Exit Sub
    'End If

    ' Functions the same as the above comment. '
    Iret = PUTFLOAT(ByVal Isendbuf, "COMM", 0, Trim(EditComm.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If


    Iret = PUTLONG(ByVal Isendbuf, "DEPTNO", 0, Trim(EditDept.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Initiate a transaction '
    Iret = tx_begin
    txbool = 1
    If Iret < 0 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Request for the updated service '
    Iret = tpcall(ByVal "FDLINSERT", ByVal Isendbuf, ByVal 0, Irecvbuf,
                  Irbuflen, ByVal 0)

    LabelErr.Caption = "sbuf = " & Isendbuf & ", rbuf = " & Irecvbuf

    If Iret = -1 Then
        TmaxError ("tpcall(SVC1)")
        ViewErr (Irecvbuf)
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Save a transaction '
    Iret = tx_commit
    If Iret < 0 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    Else
        txbool = 1
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

End Sub
' Function that displays an error related to Oracle. '
' Event handler that appears when the search button is clicked. '
Private Sub BtnSel_Click()

    Hide
    ' Shows the search result window. '
    EmployeeGrid.Show

End Sub
' Event handler that appears when the Update button is clicked. '
Private Sub BtnUdt_Click()

    Dim Isendbuf As Long
    Dim Irecvbuf As Long
    Dim Irbuflen As Long
    Dim Iret As Long
    Dim text As String
    Dim value As Long
    Dim dvalue As Double
    Dim svalue As Single
    Dim lenL As Long
    Dim txbool As Integer ' If a transaction begins, 1 is returned. Otherwise 0 is returned. '

    ' tpstart '
    tmaxStart

    ' Option to begin a transaction '
    txbool = 0

    If EditEmpNo.text = "" Then
        MsgBox "Enter the password number."
        tmaxEnd
        Exit Sub
    End If

    ' Allocate a buffer to send data. '
    Isendbuf = fballoc(100, 1024)
    If Isendbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Isendbuf)
        tmaxEnd
        Exit Sub
    End If

    ' Allocate a buffer to receive data. '
    Irecvbuf = fballoc(100, 1024)
    If Irecvbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Irecvbuf)
        tmaxEnd
        Exit Sub
    End If

    Iret = PUTLONG(ByVal Isendbuf, "EMPNO", 0, Trim(EditEmpNo.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTVAR(ByVal Isendbuf, "ENAME", 0, Trim(EditName.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTVAR(ByVal Isendbuf, "JOB", 0, Trim(EditJob.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTLONG(ByVal Isendbuf, "MGR", 0, Trim(EditMgr.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTVAR(ByVal Isendbuf, "DATE", 0, Trim(EditDate.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If


    svalue = Trim(EditSal.text)
    ' Declare Function fbput Lib "TMAX4GL.DLL"
        (ByVal pFBUF As Long, ByVal fieldid As Long, pbuffer As Any,
         ByVal Fieldlen As Long) As Long
    Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("SAL"), svalue, ByVal lenL)
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    svalue = Trim(EditComm.text)
    Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("COMM"), svalue, ByVal lenL)
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    Iret = PUTLONG(ByVal Isendbuf, "DEPTNO", 0, Trim(EditDept.text))
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Begin a transaction '
    Iret = tx_begin
    txbool = 1
    If Iret < 0 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Requst for the updated service '
    Iret = tpcall(ByVal "FDLUPDATE", ByVal Isendbuf, ByVal 0, Irecvbuf, Irbuflen,
                  ByVal 0)

    LabelErr.Caption = "sbuf = " & Isendbuf & ", rbuf = " & Irecvbuf

    If Iret = -1 Then
        TmaxError ("tpcall(SVC1)")
        ViewErr (Irecvbuf)
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Save a transaction '
    Iret = tx_commit
    If Iret < 0 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    Else
        txbool = 1
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If


End Sub
Private Sub ExitSub(txbool As Integer, Isendbuf As Long, Irecvbuf As Long)
    If txbool = 1 Then
        tx_rollback
    End If

    ' Release an allocated buffer '
    Call fbfree(ByVal Isendbuf&)
    Call fbfree(ByVal Irecvbuf&)

    ' Function to execute tpend '
    tmaxEnd

    Exit Sub

End Sub
' tpstart '
Private Sub tmaxStart()
    Dim ret As Integer

    ' Retrieve the environment configuration file. '
    ' It is defined in the atmi.bas file. '
    ' Declare Function tmaxreadenv Lib "TMAX4GL.DLL" (ByVal envfile As String,
                                                      ByVal label As String)
                                                      As Long '
    ' For the detailed information, refer to "Tmax Reference Guide".'
    ret = tmaxreadenv("C:\tmax.env", "aix5l389")
    If ret < 0 Then
        TmaxError ("tmaxreadenv")
        Exit Sub
    End If

    ret = tpstart(ByVal 0&)
    If ret = -1 Then
        LabelErr.Caption = "tpstart error = " & gettperrno()
        TmaxError ("tpstart")
        Exit Sub
    Else
        LabelErr.Caption = "tpstart return value = " & ret & " tpstart success"
    End If

End Sub
' tpend '
Private Sub tmaxEnd()
    Dim ret As Integer
    ret = tpend()
    If ret = -1 Then
        LabelErr.Caption = "tpend error = " & gettperrno()
        TmaxError ("tpend")
        Exit Sub
    Else
        LabelErr.Caption = "tpreturn return value = " & ret
    End If

End Sub
Oracle Error Display

The following figure is an Oracle error message display screen.

image

The following example shows the environment configuration necessary to execute an Oracle error message display screen.

' Funtion that displays Oracle error messages '
Private Sub ViewErr(ByVal a As Long)

    'E_TYPE          9009    long    -   -
    'E_CODE          9010    long    -   -
    'E_MSG           9011    string  -   -
    'E_TMP           9012    long    -   -

    Dim typeL, codeL, tmpL As Long
    Dim msgS As String
    Dim Iret As Integer

    ' Refer to Tmax FDL Reference Guide. '
    ' The funtions are defined in comm.bas. '
    Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TYPE"), 0, typeL, 0)
    If Iret = -1 Then
        FdlErrorMsg ("fbget_tu")
        Exit Sub
    End If

    Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_CODE"), 0, codeL, 0)
    If Iret = -1 Then
        FdlErrorMsg ("fbget_tu")
        Exit Sub
    End If

    Iret = GETVAR(ByVal a, "E_MSG", 0, msgS)
    If Iret = -1 Then
        TmaxError ("ViewErr, GETVAR, E_MSG")
        Exit Sub
    End If

    Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TMP"), 0, tmpL, 0)
    If Iret = -1 Then
        FdlErrorMsg ("fbget_tu")
        Exit Sub
    End If
    ' Show error messages in a messge box. '
    MsgBox ("Error Type : " & typeL & " ,Code : " & codeL & " ,Message :
            " & msgS & " ,Tmp : " & tmpL)

End Sub
Employee Inquiry Screen

The following figure shows an employee inquiry screen format.

image

The following table shows the components of an inquiry screen format.

Control name Control type Property to update

EmployeeGrid

Form

Caption="List of employee information"

InfoText

Text box

MultiLine=True

BtnReturn

Command button

Caption="Return"

The following example executes a designed inquiry screen format.

EmployeeGrid.frm Source LabelErr

Option Explicit
' Close the inquiry window. '
Private Sub BtnReturn_Click()
    Hide
    EmployeeMgr.Show

End Sub
' Function that shows the inquiry results when the Inquire button is clicked. '
Private Sub Form_Activate()

Dim Isendbuf As Long
    Dim Irecvbuf As Long
    Dim Irbuflen As Long
    Dim Iret As Integer
    Dim text As String
    Dim value As Long
    Dim dvalue As Double
    Dim svalue As Single
    Dim lenL As Long
    Dim initS, outputS As String
    Dim empnoS, enameS, jobS, mgrS, dateS, salS, commS, deptnoS As String
    Dim cntL As Long
    Dim eNo As Long
    Dim txbool As Integer ' If a transaction begins, 1 is returned. Otherwise 0 is returned. '

    ' tpstart '
    tmaxStart

    ' Initialize an option to begin a transaction '
    txbool = 0

    initS = vbCrLf & vbTab & vbTab & vbTab & "***** Query Results *****"
           & vbCrLf & vbTab & "==================================================="
           & vbCrLf & vbTab & "Employee Number Name Position Manager Data Hired Salary COMM Dept."
           & vbCrLf & vbTab & "==================================================="
           & vbCrLf & vbCrLf

    If EmployeeMgr.EditEmpNo.text = "" Then
        MsgBox "Enter the employee number."
        Hide
        EmployeeMgr.Show
        Exit Sub
    End If

    ' Allocate a buffer to send data '
    Isendbuf = fballoc(100, 1024)
    If Isendbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Isendbuf)
        tmaxEnd
        Exit Sub
    End If

    ' Allocate a buffer to receive data '
    Irecvbuf = fballoc(100, 1024)
    If Irecvbuf = Null Then
        TmaxError ("fballoc")
        Call fbfree(Irecvbuf)
        tmaxEnd
        Exit Sub
    End If

    ' Retreive an employee number from the employee management page. '
    eNo = Trim(EmployeeMgr.EditEmpNo.text)
    Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("EMPNO"), eNo, ByVal lenL)
    If Iret = -1 Then
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    ' Request for inquiry service '
    Iret = tpcall(ByVal "FDLSELECT", ByVal Isendbuf, ByVal 0, Irecvbuf, Irbuflen,
                  ByVal 0)
    If Iret = -1 Then
        ViewErr (Irecvbuf)
        Call ExitSub(txbool, Isendbuf, Irecvbuf)
    End If

    cntL = fbkeyoccur(ByVal Irecvbuf, ByVal fbget_fldkey("EMPNO"))

    Dim i As Long

    For i = 0 To cntL - 1
        Iret = GETLONG(ByVal Irecvbuf, "EMPNO", i, value)
        If Iret = -1 Then
            TmaxError ("GETLONG(EMPNO)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        empnoS = value

        Iret = GETVAR(ByVal Irecvbuf, "ENAME", i, text)
        If Iret = -1 Then
            TmaxError ("GETVAR(ENAME)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        enameS = text

        Iret = GETVAR(ByVal Irecvbuf, "JOB", i, text)
        If Iret = -1 Then
            TmaxError ("GETVAR(JOB)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        jobS = text

        Iret = GETLONG(ByVal Irecvbuf, "MGR", i, value)
        If Iret = -1 Then
            TmaxError ("GETLONG(MGR)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        mgrS = value

        Iret = GETVAR(ByVal Irecvbuf, "DATE", i, text)
        If Iret = -1 Then
            TmaxError ("GETVAR(DATE)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        dateS = text

        ' Retreive float data from SAL data field. '
        ' The function is defined in comm.bas. '
        Iret = fbget_tu(ByVal Irecvbuf, ByVal fbget_fldkey("SAL"), i, svalue, 0)
        If Iret = -1 Then
            FdlErrorMsg ("fbget_tu")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        salS = svalue

        Iret = GETFLOAT(ByVal Irecvbuf, "COMM", i, svalue)
        If Iret = -1 Then
            TmaxError ("GETFLOAT(COMM)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        commS = svalue

        Iret = GETLONG(ByVal Irecvbuf, "DEPTNO", i, value)
        If Iret = -1 Then
            TmaxError ("GETLONG(DEPTNO)")
            Call ExitSub(txbool, Isendbuf, Irecvbuf)
        End If
        deptnoS = value & vbCrLf

        outputS = outputS & "       " & empnoS & vbTab & enameS & vbTab & jobS
                                      & vbTab & mgrS & vbTab & dateS & vbTab
                                      & salS & vbTab & commS & vbTab & deptnoS

    Next i

    InfoText.text = initS & outputS
    ' Displays returned data in the text box '
    LabelErr.Caption = "SAL = " & dvalue

    Call ExitSub(txbool, Isendbuf, Irecvbuf)

End Sub

Private Sub ExitSub(txbool As Integer, Isendbuf As Long, Irecvbuf As Long)
    If txbool = 1 Then
        tx_rollback
    End If

    ' Release the allocated buffer '
    Call fbfree(ByVal Isendbuf&)
    Call fbfree(ByVal Irecvbuf&)

    ' Function that executes tpend '
    tmaxEnd

    Exit Sub

End Sub

' tpstart '
Private Sub tmaxStart()
    Dim ret As Integer

    ' Retreive the environment configuration file. '
    ' It is defined in the atmi.bas file. '
    ' Declare Function tmaxreadenv Lib "TMAX4GL.DLL"(ByVal envfile As String,
                                                    ByVal label As String) As Long '
    ' For the detailed information, refer to "Tmax Reference Guide". '
    ret = tmaxreadenv("C:\tmax.env", "aix5l389")
    If ret < 0 Then
        TmaxError ("tmaxreadenv")
        Exit Sub
    End If

    ret = tpstart(ByVal 0&)
    If ret = -1 Then
        LabelErr.Caption = "tpstart error = " & gettperrno()
        TmaxError ("tpstart")
        Exit Sub
    Else
        LabelErr.Caption = "tpstart return value = " & ret & " tpstart success"
    End If

End Sub
' tpend '
Private Sub tmaxEnd()
    Dim ret As Integer
    ret = tpend()
    If ret = -1 Then
        LabelErr.Caption = "tpend error = " & gettperrno()
        TmaxError ("tpend")
        Exit Sub
    Else
        LabelErr.Caption = "tpreturn return value = " & ret
    End If
End Sub
' Function that displays Oracle errors '
Private Sub ViewErr(ByVal a As Long)

'E_TYPE          9009    long    -   -
'E_CODE          9010    long    -   -
'E_MSG           9011    string  -   -
'E_TMP           9012    long    -   -

    Dim typeL As Long
    Dim codeL As Long
    Dim msgS As String
    Dim tmpL As Long
    Dim Iret As Integer

    Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TYPE"), 0, typeL, 0)

    If Iret = -1 Then
        FdlErrorMsg ("fbget_tu")
        Exit Sub
    End If
    Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_CODE"), 0, codeL, 0)
    If Iret = -1 Then
        FdlErrorMsg ("fbget_tu")
        Exit Sub
    End If

    Iret = GETVAR(ByVal a, "E_MSG", 0, msgS)
    Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TMP"), 0, tmpL, 0)
    If Iret = -1 Then
        FdlErrorMsg ("fbget_tu")
        Exit Sub
    End If
    MsgBox ("Error Type : " & typeL & " ,Code : " & codeL & " ,Message : "&msgS&",
            Tmp : " & tmpL)
End Sub

3.5. Server Programs

Service Programs

The following is an example of service program.

<emp_c.pc>

#include <stdio.h>
#include <ctype.h>
#include <tuxinc/macro.h>
#include "../../fdl/demo_fdl.h"

EXEC SQL include sqlca.h;
EXEC SQL INCLUDE ORACA;
EXEC ORACLE  OPTION (ORACA=YES);
EXEC ORACLE  OPTION (RELEASE_CURSOR=YES);

#define INP   1
#define ORA   2
#define TMX   3
#define APP   4

EXEC SQL begin declare section;
int   h_empno;
char  h_ename[11];
char  h_job[10];
int   h_mgr;
char  h_date[11];
float h_sal;
float h_comm;
int   h_deptno;
EXEC SQL end declare section;

void svc_error(long type, long err_code, char *msg, long tmp);

FDLINSERT( TPSVCINFO *msg )
{
    FBUF *rcvbuf;
    int i, occurrence;
    rcvbuf = (FBUF *)msg->data;
    h_empno = h_mgr = h_sal = h_comm = h_deptno = 0;

    memset(h_ename, 0x00, sizeof(h_ename));
    memset(h_job, 0x00, sizeof(h_job));
    memset(h_date, 0x00, sizeof(h_date));

    occurrence = fbkeyoccur(rcvbuf, EMPNO);

    for (i=0; i< occurrence; i++){
         fbget_tu(rcvbuf, EMPNO, i, (char *)&h_empno, 0);
         fbget_tu(rcvbuf, MGR,   i, (char *)&h_mgr, 0);
         fbget_tu(rcvbuf, SAL,   i, (char *)&h_sal, 0);
         fbget_tu(rcvbuf, COMM,  i, (char *)&h_comm, 0);
         fbget_tu(rcvbuf, DEPTNO,i, (char *)&h_deptno, 0);
         fbget_tu(rcvbuf, ENAME, i, (char *)h_ename, 0);
         fbget_tu(rcvbuf, JOB  , i, (char *)h_job, 0);
         fbget_tu(rcvbuf, DATE , i, (char *)h_date, 0);

         EXEC SQL INSERT
         INTO emp(empno, ename, job, mgr, hiredate, sal,comm, deptno)
         VALUES (:h_empno, :h_ename, :h_job, :h_mgr,
                 to_date(:h_date,'yyyymmdd'), :h_sal, :h_comm, :h_deptno );
     }

     if(sqlca.sqlcode != 0)
        goto LB_DBERROR;

     EXEC SQL WHENEVER SQLERROR
        goto LB_DBERROR;

     tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L);

     LB_DBERROR :
         EXEC SQL WHENEVER SQLERROR CONTINUE;
         svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0);
}


FDLDELETE( TPSVCINFO *msg )
{
     FBUF *rcvbuf;
     int i, occurrence;

     rcvbuf = ( FBUF *)msg->data;
     occurrence = fbkeyoccur(rcvbuf, EMPNO);

     for (i=0; i< occurrence; i++){
          fbget_tu (rcvbuf, EMPNO, i, (char *)&h_empno , 0);

          EXEC SQL DELETE
          FROM emp
          WHERE empno = :h_empno;
     }
     if(sqlca.sqlcode != 0)
        goto LB_DBERROR;

     EXEC SQL WHENEVER SQLERROR
        goto LB_DBERROR ;

     EXEC SQL WHENEVER NOT FOUND
        goto LB_DBERROR ;

     tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L);

     LB_DBERROR :
        EXEC SQL WHENEVER SQLERROR CONTINUE;
        svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0);
}

FDLSELECT( TPSVCINFO *msg )
{
      FBUF *rcvbuf;
      FLDLEN fldlen;
      int i=0, ROWMEM=200, CHKROW=500;
      rcvbuf = (FBUF *)msg->data;

      if((rcvbuf=(FBUF *)tprealloc((char *)rcvbuf,ROWMEM*CHKROW))==NULL) {
          rcvbuf=(FBUF *)msg->data;
          goto LB_TMAXERROR ;
       }

       h_empno = h_mgr = h_sal = h_comm = h_deptno = 0;

       memset( h_ename, 0x00, sizeof( h_ename ) );
       memset( h_job, 0x00, sizeof( h_job ) );
       memset( h_date, 0x00, sizeof( h_date ) );

       fbget_tu( rcvbuf, EMPNO, 0, (char *)&h_empno, &fldlen);

       EXEC SQL DECLARE DB_CUR CURSOR FOR
       SELECT  nvl(empno,0), nvl(ename,' '), nvl(job,' '),
               nvl(to_char(hiredate,'yyyymmdd'),' '),  nvl(mgr,0),
               nvl(sal,0), nvl(comm,0), nvl(deptno,0)
       FROM  emp
       WHERE empno >= :h_empno-50 AND empno <= :h_empno+50;
       EXEC SQL OPEN DB_CUR;

       if(sqlca.sqlcode != 0)
          goto LB_DBERROR;

       EXEC SQL WHENEVER SQLERROR
          goto LB_DBERROR ;
       EXEC SQL WHENEVER NOT FOUND
          Do break ;

       while(1) {
          EXEC SQL FETCH DB_CUR
          INTO    :h_empno,
                  :h_ename,
                  :h_job,
                  :h_date,
                  :h_mgr,
                  :h_sal,
                  :h_comm,
                  :h_deptno;
          fbchg_tu(rcvbuf, EMPNO,  i,(char *)&h_empno, 0);
          fbchg_tu(rcvbuf, MGR,    i,(char *)&h_mgr, 0);
          fbchg_tu(rcvbuf, SAL,    i,(char *)&h_sal, 0);
          fbchg_tu(rcvbuf, DEPTNO, i,(char *)&h_deptno, 0);
          fbchg_tu(rcvbuf, COMM,   i,(char *)&h_comm, 0);
          fbchg_tu(rcvbuf, ENAME,  i,(char *)h_ename, 0);
          fbchg_tu(rcvbuf, JOB,    i,(char *)h_job, 0);
          fbchg_tu(rcvbuf, DATE,   i,(char *)h_date, 0);

          i++;
       }
       if (i < 1) goto LB_DBERROR;

       EXEC SQL CLOSE DB_CUR;
       tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L);

       LB_DBERROR :
            EXEC SQL WHENEVER SQLERROR CONTINUE;
            EXEC SQL CLOSE DB_CUR ;
            svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0L) ;

       LB_TMAXERROR :
            EXEC SQL WHENEVER SQLERROR CONTINUE;
            EXEC SQL CLOSE DB_CUR;
            svc_error(TMX, tperrno, "", 0L);
}

FDLUPDATE( TPSVCINFO *msg )
{
       FBUF *rcvbuf ;
       int i, occurrence;
       rcvbuf = (FBUF *)msg->data;
       h_empno = h_mgr = h_sal = h_comm = h_deptno = 0;

       memset( h_ename, 0x00, sizeof( h_ename ) );
       memset( h_job, 0x00, sizeof( h_job ) );
       memset( h_date, 0x00, sizeof( h_date ) );

       occurrence = fbkeyoccur(rcvbuf, EMPNO);

       for (i=0; i< occurrence; i++){
            fbget_tu ( rcvbuf, EMPNO, i, (char *)&h_empno, 0);
            fbget_tu ( rcvbuf, ENAME, i, (char *)h_ename, 0);
            fbget_tu ( rcvbuf, JOB, i, (char *)h_job, 0);
            fbget_tu ( rcvbuf, MGR, i, (char *)&h_mgr, 0);
            fbget_tu ( rcvbuf, SAL, i, (char *)&h_sal, 0);
            fbget_tu ( rcvbuf, COMM, i, (char *)&h_comm,0);
            fbget_tu ( rcvbuf, DEPTNO, i, (char *)&h_deptno,0);
            fbget_tu ( rcvbuf, DATE, i, (char *)h_date, 0);

            EXEC SQL UPDATE emp
            SET ename = nvl(:h_ename, ename),
                job   = nvl(:h_job, job),
                mgr   = :h_mgr,
                hiredate  = nvl(to_date(:h_date,
                                'yyyymmdd'),hiredate),
                sal   = :h_sal,
                comm  = :h_comm,
                deptno = :h_deptno
            WHERE empno = :h_empno;

            if(sqlca.sqlcode != 0)
               goto LB_DBERROR;

            EXEC SQL WHENEVER SQLERROR
               goto LB_DBERROR;

            EXEC SQL WHENEVER NOT FOUND
               goto LB_DBERROR;
       }
       tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L);

       LB_DBERROR :
            EXEC SQL WHENEVER SQLERROR CONTINUE;
            svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0L) ;
}

/*********************************************************************
 * Error Processing: If an error occurs in a service routine, the error is entered to the buffer and sent to the client.
 ********************************************************************/
void svc_error(long type, long err_code, char *msg, long tmp) {
        FBUF *transf;
        char *svcname;
        char err_msg[100];
        char temp[100];
        int i = 0;

        printf("type     ==>[%ld]\n", type);
        printf("err_code ==>[%ld]\n", err_code);
        printf("msg      ==>[%s]\n",  msg);
        strcpy(err_msg, msg);

        if ((transf = (FBFR *)tpalloc("FML", NULL, 0)) == NULL) {
             printf("tpalloc failed! errno = %d\n", tperrno);
        }

        switch(type) {
             case INP:
                  switch(err_code) {
                         case -1000:
                               strcpy(err_msg,"The user is not authorized.");
                               break;
                         default:
                               strcpy(err_msg,
                                      "Input error message is not registered.");
                  }
                  break;
             case ORA:
                  if (strlen(err_msg)== 0)
                      strcpy(err_msg, sqlca.sqlerrm.sqlerrmc);
                      break;
             case TMX:
                  if (strlen(err_msg)== 0)
                      strcpy(err_msg, tpstrerror(tperrno));
                      break;
             case APP:
                  if (strlen(err_msg)== 0) {
                      /* Sets an error message if * err_mssg="" is specified. ******/
                      switch(err_code) {
                            case -500:            /* SYSTEM Error */
                                  strcpy(err_msg,"File creation error.");
                                  break;
                            case -502:
                                  strcpy(err_msg,"Failed to call an internal service.");
                                  break;
                            case -504:
                                  strcpy(err_msg, "Socket communication error.");
                                  break;
                            case -505: /* Displays 'processing error if the application is updated by another transaction.*/
                                    /* "[%s] has been updated by another application after an inquiry is performed.
                                    \n\nQuery again and process it.": Processed in a client*/
                                strcpy(err_msg, "does not exist.");
                                    break;
                            case -5002:
                                    strcpy(err_msg, "Contact to the computer center.");
                                    break;
                            default:
                                    strcpy(err_msg,
                                 "Application Error Message is not registered.");
                        }
                   }
                   break;
            }

            /* ROLLBACK */
            EXEC SQL WHENEVER SQLERROR CONTINUE;
            EXEC SQL ROLLBACK;

            fbchg_tu ( transf, E_TYPE, i, (char *)&type,0);
            fbchg_tu ( transf, E_CODE, i, (char *)&err_code,0);
            fbchg_tu ( transf, E_MSG, i, (char *)err_msg,0);
            fbchg_tu ( transf, E_TMP, i, (char *)&tmp,0);

            tpreturn(TPFAIL, 0, (char *)transf, 0L, 0L);
}
Makefile

The following example creates an emp_c.pc source as a Tmax application.

<emp_c.mk>

include $(ORACLE_HOME)/precomp/lib/env32.mk
ORALIBDIR = $(LIBHOME)
ORALIB = -L/home/oracle/OraHome/lib32/ -lclntsh  -lld -lm `cat
          /home/oracle/OraHome/lib32/sysliblist`  -lm  -lc_r -lpthreads
TARGET = emp_c
APOBJS = emp_c.o
NSDLOBJ = $(TMAXDIR)/lib/sdl.o
#CC
CC=cc

#Oracle
LIBS = -lsvr -loras

OBJS = $(APOBJS) $(SVCTOBJ)
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  = -q32 -O -I$(TMAXDIR)
LDFLAGS = -brtl
APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svct
TMAXLIBDIR  = $(TMAXDIR)/lib
 #
.SUFFIXES : .c

.c.o:
     $(CC) $(CFLAGS) $(LDFLAGS) -c $<

all: $(TARGET)

$(TARGET): $(OBJS)
     $(CC) $(CFLAGS) $(LDFLAGS) -L$(TMAXLIBDIR) -o $(TARGET)
     -L$(ORALIBDIR) $(ORALIB) $(OBJS) $(LIBS) $(NSDLOBJ)
     mv $(TARGET) $(TMAXDIR)/appbin

$(APOBJS): $(TARGET).pc
     proc iname=emp_c include=$(TMAXDIR)
     define=__LINUX_ORACLE_PROC__
     $(CC) $(CFLAGS) $(LDFLAGS) -c $(TARGET).c

$(SVCTOBJ):
     touch $(SVCTDIR)/$(TARGET)_svctab.c
     $(CC) $(CFLAGS) $(LDFLAGS) -c $(SVCTDIR)/$(TARGET)_svctab.c
#
clean:
     -rm -f *.o core $(TARGET) $(TARGET).lis