Logo Search packages:      
Sourcecode: maxdb-7.5.00 version File versions

Script_SQLPacket.c

/*
 * @filename:    vin28.c
 * @purpose:    "Interface to SQL packet"
 * @release:    7.2
 *
 * @copyright:  (c) 2000-2004 SAP AG"



    ========== licence begin  GPL
    Copyright (c) 2000-2004 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end



 */

#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdio.h>

#include "heo102.h"
#include "heo03.h"
#include "hsp26.h"
#include "hsp30.h"
#include "hsp77.h"
#include "hsp78_0.h"
#include "hsp100.h"
#include "Scripting/Script_SQLPacket.h"

/*----------------------------------------*/


/*#if COMPILEMODE_MSP00 >= QUICK_MSP00*/
/* quick fix for PTS 1104718*/
/*#define ASSERT_DBG(cond)        ((cond) ? (void) 0 : \*/
/*            sqlk_assert (assertionFailed_esp00, __LINE__, __FILE__, #cond))*/
/*#else*/

#define ASSERT_DBG(cond)        0

/*#endif*/

/*static const char i28_applicationName [4] = "CON";*/
/*static const char i28_applicationVersion [6] = "70200";*/

#define SQLTRACE (session->tracer)

externPascal void s40glint (
    tsp00_Number    * num,
    tsp00_Int4        pos,
    int               len,
    tsp00_Int4      * dest,
    tsp00_NumError  * res);

externPascal void s41plint (
    tsp00_Number    * num,
    tsp00_Int4        pos,
    int               len,
    int               frac,
    tsp00_Int4        source,
    tsp00_NumError  * nrc);

externPascal void s43pstr (
    tsp00_Number    * num,
    tsp00_Int4        pos,
    int               len,
    int               frac,
    char            * source,
    tsp00_Int4        spos,
    int               slen,
    tsp00_NumError  * res);

externPascal void s44egchr (
    void            * buf,
    tsp00_Int4        pos,
    integer           len,
    integer           frac,
    void            * dest,
    tsp00_Int4        dpos,
    integer         * dlen,
    tsp00_DecimalPresentation *decimal,
    tsp00_NumError  * res);

externPascal void s45stoi4 (
    tsp00_Int4      * val,
    void            * buf,
    int               pos,
    int               len,
    tsp00_NumError  * res);

/* ------------------------------- */
/* specification private functions */
/* ------------------------------- */
static void     i28_fetchcmd
    ( tin01_sql_session * session,
      tin01_cstr          fetchCmd,
      int                fetchVars );
/* ------------------------------- */
static void     i28_reset
    ( tin01_sql_session * session,
      tin01_bool          initClientInfo );
/* ------------------------------- */
static void     i28_machinfo
    ( tsp00_CodeType    * code_type,
      tsp00_SwapKind    * swap_kind,
      char             * termid);
/* ------------------------------- */
void            i28pnull
    ( tin01_sql_session * session,
      int                sqllen,
      tsp00_Int4           bufpos);
/* ------------------------------- */
tsp01_CommErr i28receive
    ( tin01_sql_session      * pSession );
/* ------------------------------- */
tsp01_CommErr i28request
    ( tin01_sql_session * session);
/* ------------------------------- */
void            i28callsql
    ( tin01_sql_session * session,
      tsp01_CommErr  * comm_error);
/* ------------------------------- */
void i28pascalstring
      ( char               * target,
        int                  targetlen,
        const char         * source,
        int                  sourcelen );
/* ------------------------------- */
void i28cleanup_session
      ( tin01_sql_session   * session);
/* ------------------------------- */


#define UNICODE_CLIENT(session) (M_IS_UNICODE((session)->code_type))
/*
 *
 *#define UNICODE_CLIENT(session) (((session)->code_type == CSP_UNICODE)||((session)->code_type == CSP_UNICODE_SWAP))
 */
/**\
--------------------------------------MF__ MOD__ chapter packet handling
\**/

#define PACKETFIELD(packet,field)      (packet->variant.C_2.field##_F)
#define PACKETINFO(packet,field)       (packet->sp1_header.field)
#define SEGMFIELD(segment,field)       (segment->variant.C_1.field##_F)
#define SEGMINFO(segment,field)        (segment->variant.C_3.field##_F)
#define SENDINFO(segment,field)        (segment->variant.C_3.field##_F)
#define RECINFO(segment,field)         (segment->variant.C_4.field##_F)
#define PARTINFO(part, field)          (part->variant.C_2.field##_F)
#define PARTDATA(part)                 ((char *)&part->variant.C_1.sp1p_buf_F)
#define EMPTYSET_MIN01                     0
#define M_WARNINGSET(set)               (*(tsp00_Int2*)&set)

tsp1_segment   *
i28firstsegment (
    tsp1_packet * packet)
{
    /* ROUTINE_DBG_MSP00 ("i28firstsegment"); */
    return &PACKETFIELD (packet, sp1_segm);
}

/*----------------------------------------*/

tsp1_segment   *
i28nextsegment (
    tsp1_segment * segment)
{
    /* ROUTINE_DBG_MSP00 ("i28nextsegment"); */
    s26next_segment (&segment);
    return segment;
}

/*----------------------------------------*/

tsp1_segment   *
i28_lastsegment (
    tsp1_packet * packet)
{
    /* ROUTINE_DBG_MSP00 ("i28_lastsegment"); */
    int             segmentCount;
    int             i;
    tsp1_segment   *segment;

    segmentCount = packet->sp1_header.sp1h_no_of_segm;
    segment = i28firstsegment (packet);
    for (i = 0; i < segmentCount - 1; ++i) {
        segment = i28nextsegment (segment);
    }
    return segment;
}

/*----------------------------------------*/

tsp1_segment   *
i28advsegment (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28advsegment"); */
    session->segment = i28nextsegment (session->segment);
    return session->segment;
}

/*----------------------------------------*/

tsp1_segment   *
i28newsegment (
    tin01_sql_session * session,
    tsp1_cmd_mess_type_Enum messType)
{
    /* ROUTINE_DBG_MSP00 ("i28newsegment"); */
    s26first_segment_init (session->send_packet, sp1sk_cmd,
        &session->segment);
    SENDINFO (session->segment, sp1c_mess_type) = messType;
    SENDINFO (session->segment, sp1c_sqlmode) = session->sqlMode;
    return session->segment;
}

/*----------------------------------------*/

tsp1_part      *
i28firstpart (
    tsp1_segment * segment)
{
    /* ROUTINE_DBG_MSP00 ("i28firstpart"); */
    return &SEGMFIELD (segment, sp1p_part);
}

/*----------------------------------------*/

tsp1_part      *
i28nextpart (
    tsp1_part * part)
{
    /* ROUTINE_DBG_MSP00 ("i28nextpart"); */
    s26nextpart (&part);
    return part;
}

/*----------------------------------------*/

tsp1_part      *
i28advpart (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28advpart"); */
    session->part = i28nextpart (session->part);
    return session->part;
}

/*----------------------------------------*/

tin01_bool
i28findpart (
    tin01_sql_session * session,
    tsp1_part_kind_Enum requiredKind)
{
    /* ROUTINE_DBG_MSP00 ("i28findpart"); */
    /* Find Part return it in session->part */
    if (session->part != NULL) {
        if (PARTINFO (session->part, sp1p_part_kind) == requiredKind) {
            return true;
        }
    }
    s26find_part (session->segment, requiredKind, &session->part);
    return (session->part != NULL);
} /* i28findpart */

/*----------------------------------------*/

tin01_bool
i28_findpart (
    tin01_sql_session * session,
    tsp1_part_kind_Enum requiredKind,
    tsp1_part        ** found_part)
{
    /* ROUTINE_DBG_MSP00 ("i28_findpart"); */
    /* Find Part without changing session->part */
    if (session->part != NULL) {
        if (PARTINFO (session->part, sp1p_part_kind) == requiredKind) {
            *found_part = session->part;
            return true;
        }
    }
    s26find_part (session->segment, requiredKind, found_part);
    return (*found_part != NULL);
} /* i28_findpart */

/*----------------------------------------*/

tsp1_part      *
i28newpart (
    tin01_sql_session * session,
    tsp1_part_kind_Enum partKind)
{
    /* ROUTINE_DBG_MSP00 ("i28newpart"); */
    if (SENDINFO (session->segment, sp1s_no_of_parts) > 0)
        s26finish_part (session->send_packet, session->part);
    s26new_part_init (session->send_packet, session->segment, &session->part);
    ASSERT_DBG (session->part != NULL);
    PARTINFO (session->part, sp1p_part_kind) = partKind;
    return session->part;
}

/*----------------------------------------*/

void
i28closesend (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28closesend"); */
    int partOffset;

    ASSERT_DBG (session->buildingCommand);
    s26finish_part (session->send_packet, session->part);
    partOffset = (char *) session->part
        - (char *) & PACKETFIELD (session->send_packet, sp1_segm);
    PACKETINFO (session->send_packet, sp1h_varpart_len) =
        partOffset + PARTINFO (session->part, sp1p_buf_len);
}

/*----------------------------------------*/

void
i28resetpackets (
    tin01_sql_session * session,
    tin01_bool forCommand)
{
    /* ROUTINE_DBG_MSP00 ("i28resetpackets"); */
    tsp1_packet    *packet;

    session->buildingCommand = forCommand;
    if (forCommand)
        packet = session->send_packet;
    else
        packet = session->rec_packet;
    session->segment = &PACKETFIELD (packet, sp1_segm);
    if (forCommand) {
        session->part = &SEGMFIELD (session->segment, sp1p_part);
    }
    else {
        session->part = NULL;
    }
}

/*----------------------------------------*/

void
i28clearpacketref (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28clearpacketref"); */
    session->send_packet = NULL;
    session->rec_packet = NULL;
    session->segment = NULL;
    session->part = NULL;
}

/*----------------------------------------*/

void
i28initpacketref (
    tin01_sql_session * session,
    tsp1_packet * packet,
    tin01_bool forCommand)
{
    /* ROUTINE_DBG_MSP00 ("i28initpacketref"); */
    session->buildingCommand = forCommand;
    if (packet == NULL)
        i28clearpacketref (session);
    else {
        if (forCommand) {
            session->send_packet = packet;
            session->rec_packet = NULL;
        }
        else
            session->rec_packet = packet;
        session->segment = i28firstsegment (packet);
        session->part = i28firstpart (session->segment);
    }
}

/*----------------------------------------*/

void
i28initsession (
    tin01_sql_session * session,
    tsp1_packet * packet)
{
    /* ROUTINE_DBG_MSP00 ("i28initsession"); */

    memset (&session->xuser, '\0', sizeof (session->xuser));
    session->xuser.xu_cachelimit = -1;
    session->xuser.xu_timeout = -1;
    session->xuser.xu_isolation = -1;
    session->reference = 0;
    session->is_connected = false;
    session->inUse = false;
    session->buildingCommand = false;
    i28_machinfo (&session->code_type, &session->swap_kind,
        (char *) session->senderid);
    i28initpacketref (session, packet, true);
    session->sqlMode = sp1sm_session_sqlmode;
    session->more_data = NULL;
    session->switch_possible = true;
    session->new_session = true;
    session->as_utility = false;
    session->space_option = false;
}

/*----------------------------------------*/

void
i28unicodeclient (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28unicodeclient"); */
    ASSERT_DBG (!session->is_connected);
    session->code_type = csp_unicode;
}

/*----------------------------------------*/

int
i28adabasmode (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28adabasmode"); */
    int             result;

    result = session->sqlMode;
    session->sqlMode = sp1sm_internal;
    return result;
}

/*----------------------------------------*/

int
i28sessionmode (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28sessionmode"); */
    int             result;

    result = session->sqlMode;
    session->sqlMode = sp1sm_session_sqlmode;
    return result;
}

/*----------------------------------------*/

int
i28oldmode (
    tin01_sql_session * session,
    int oldMode)
{
    /* ROUTINE_DBG_MSP00 ("i28oldmode"); */
    int             result;

    result = session->sqlMode;
    session->sqlMode = oldMode;
    return result;
}

/*----------------------------------------*/

void
i28initprocreply (
    tin01_sql_session * session)
{
    i28_reset (session, true);
    i28newsegment (session, sp1m_dbs);
    SEGMINFO (session->segment, sp1s_segm_kind) = sp1sk_procreply;
}

/*----------------------------------------*/

void
i28seterrorinfo  (
    tin01_sql_session * session,
    int                 errorCode,
    const char *        errorMessage,
    int                 messageLen)
{
    RECINFO (i28_lastsegment (session->rec_packet), sp1r_returncode) = errorCode;
    i28newpart (session, sp1pk_errortext);
    if (messageLen == -1) {
        messageLen = strlen (errorMessage);
    }
    i28addpartdata (session, errorMessage, messageLen);
    
}

/**\
--------------------------------------MF__ MOD__ chapter high level sql
\**/

void
i28initadbs (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28initadbs"); */
    i28_reset (session, true);
    i28newsegment (session, sp1m_dbs);
    i28newpart (session, sp1pk_command);
}

/*----------------------------------------*/

void
i28initparse (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28initparse"); */
    i28_reset (session, true);
    i28newsegment (session, sp1m_parse);
    i28newpart (session, sp1pk_command);
}

/*----------------------------------------*/

void
i28initexecute (
    tin01_sql_session * session,
    tin01_parseid pid)
{
    /* ROUTINE_DBG_MSP00 ("i28initexecute"); */
    i28_reset (session, true);
    i28newsegment (session, sp1m_execute);
    i28newpart (session, sp1pk_parsid);
    memcpy (PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len),
        pid, sizeof (tin01_parseid));
    PARTINFO (session->part, sp1p_buf_len) += sizeof (tin01_parseid);
    /* i28newpart (session, sp1pk_data); */
}

/*----------------------------------------*/

void
i28initspecial (
    tin01_sql_session * session,
    tsp1_cmd_mess_type_Param messType)
{
    /* ROUTINE_DBG_MSP00 ("i28initspecial"); */
    i28_reset (session, true);
    i28newsegment (session, messType);
    i28newpart (session, sp1pk_command);
}

/*----------------------------------------*/

void
i28initoutargs (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28initoutargs"); */
    i28_reset (session, false);
    s26first_segment_init (session->send_packet, sp1sk_return,
        &session->segment);
    i28newpart (session, sp1pk_data);
}

/*----------------------------------------*/
static int
i28sqlrequest (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28sqlrequest"); */
  tsp00_Int2         result       = cin01_db_ok;

  if (!session->is_connected) {
    TRACE_MIN01 (4, SQLTRACE, "No connection: command skipped");
    result = cin01_db_not_accessible;
    return result;
  } /* end if */

  ASSERT_DBG (session->is_connected);
  session->rec_packet = NULL;
  i28closesend (session);
  IFTRACE_MIN01 (4, j96dumppacket (session, "REQUEST", SQLTRACE));

  if (i28request (session) != commErrOk_esp01) {
    result = cin01_db_not_accessible;
  } /* end if */

  return result;
} /* end i28sqlrequest */

/*----------------------------------------*/
static int
i28sqlreceive (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28sqlreceive"); */
  tsp01_CommErr  comm_error;
  tsp00_Int2         result       = cin01_db_ok;

  comm_error = i28receive (session);
  i28lasterr_on (session);

  if ((int) comm_error != commErrOk_esp01) {
    result = cin01_db_not_accessible;
  } else {
    i28resetpackets (session, false);
    IFTRACE_MIN01 (4, j96dumppacket (session, "RECEIVE", SQLTRACE));
    result = RECINFO (i28_lastsegment (session->rec_packet), sp1r_returncode);

/*    result = RECINFO (i28_lastsegment (session->rec_packet), returncode);*/
  } /* end if */

  return result;

} /* end i28sqlreceive */

/*----------------------------------------*/

int
i28sql (
    tin01_sql_session * session,
    tin01_sqlresult * sqlresult)
{
    /* ROUTINE_DBG_MSP00 ("i28sql"); */
    tsp01_CommErr  comm_error;
    tsp00_Int2        result;
    tsp1_packet    *send_packet = session->send_packet;
    tsp1_segment   *segment;
    int             msglen;

    if (sqlresult == NULL)
        sqlresult = &(session->lasterr.sqlresult);
    if (!session->is_connected) {
        TRACE_MIN01 (4, SQLTRACE, "No connection: command skipped");
        result = cin01_db_not_accessible;
        if (sqlresult != NULL) {
            sqlresult->returnCode = result;
            M_WARNINGSET (sqlresult->warnings) = EMPTYSET_MIN01;
            sqlresult->errorPos = 0;
            sqlresult->rowCount = 0;
            MEMCPY_MIN01 (sqlresult->sqlstate, "I8888");
            sqlresult->sqlmsg[0] = '\0';
        }
        return result;
    }
    ASSERT_DBG (session->is_connected);
    session->rec_packet = NULL;
    i28closesend (session);
    IFTRACE_MIN01 (4, j96dumppacket (session, "REQUEST", SQLTRACE));
    i28callsql (session, &comm_error);
    if ((int) comm_error != commErrOk_esp01) {
        result = cin01_db_not_accessible;
        /* session->is_connected = false; lower level routines try reconnect */
        if (sqlresult != NULL) {
            sqlresult->returnCode = result;
            M_WARNINGSET (sqlresult->warnings) = EMPTYSET_MIN01;
            sqlresult->errorPos = 0;
            sqlresult->rowCount = 0;
            MEMCPY_MIN01 (sqlresult->sqlstate, "I8888");
            sqlresult->sqlmsg[0] = '\0';
        }
    }
    else {
        i28resetpackets (session, false);
        IFTRACE_MIN01 (4, j96dumppacket (session, "RECEIVE", SQLTRACE));
        segment = i28_lastsegment (session->rec_packet);
        result = RECINFO (segment, sp1r_returncode);
        /* to lasterr, only store errors: */
        if ((sqlresult != NULL) &&
            ((result != cin01_db_ok) ||
                (sqlresult != &(session->lasterr.sqlresult)))) {
            sqlresult->returnCode = result;
            M_WARNINGSET(sqlresult->warnings) = M_WARNINGSET
                (RECINFO (segment, sp1r_extern_warning));
            sqlresult->errorPos = RECINFO (segment, sp1r_errorpos);
            if (result == cin01_db_row_not_found) {
                sqlresult->rowCount = 0;
            }
            else {
                sqlresult->rowCount = i28resultcount (session);
            }
            MEMCPY_MIN01 (sqlresult->sqlstate, RECINFO (segment, sp1r_sqlstate));
            if (result != cin01_db_ok) {
                if (i28findpart (session, sp1pk_errortext)) {
                    memcpy (sqlresult->sqlmsg, PARTDATA (session->part),
                        sizeof (sqlresult->sqlmsg) - 1);
                    msglen = PARTINFO (session->part, sp1p_buf_len);
                    sqlresult->sqlmsg[msglen] = '\0';
                }
            }
        }
    }
    return result;
}

/*----------------------------------------*/

static void
i28_reset (
    tin01_sql_session * session,
    tin01_bool initClientInfo)
{
    /* ROUTINE_DBG_MSP00 ("i28_reset"); */
    tsp1_packet_header *header;
    /*
     * init packet
     */
    if (!session->buildingCommand)
        i28resetpackets (session, true);
    header = &session->send_packet->sp1_header;
    if (initClientInfo) {
        header->sp1h_mess_code = session->code_type;
        header->sp1h_mess_swap = session->swap_kind;
        header->sp1h_filler2 = 0;

        memcpy (header->sp1h_appl_version, session->senderid,
            sizeof (session->senderid));
    } /* end if*/
    header->sp1h_filler1 = 0;
    header->sp1h_no_of_segm = 1;
}

/*----------------------------------------*/

void
i28pcmd (
    tin01_sql_session * session,
    tin01_cstr cmd,
    int len)
{
    /* ROUTINE_DBG_MSP00 ("i28pcmd"); */
    tsp1_packet    *send_packet = session->send_packet;
    char           *target;

    ASSERT_DBG (send_packet != NULL);
    if (len == UNDEF_SP00)
        len = strlen (cmd);
    target = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    memcpy (target, cmd, len);
    PARTINFO (session->part, sp1p_buf_len) += len;
}

/*----------------------------------------*/

void
i28pcmdf (
    tin01_sql_session * session,
    tin01_cstr cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28pcmdf"); */
    va_list         args;
    int             bytecnt;
    char           *cmdBuf;
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    va_start (args, cmd);
    cmdBuf = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    bytecnt = vsprintf (cmdBuf, cmd, args);
    va_end (args);
    if (bytecnt < 0)
        return;
    PARTINFO (session->part, sp1p_buf_len) += bytecnt;
}

/*----------------------------------------*/

void
i28pusercmd (
    tin01_sql_session * session,
    tin01_cstr cmd,
    int len)
{
    /* ROUTINE_DBG_MSP00 ("i28pusercmd"); */
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    if (len == UNDEF_SP00)
        len = strlen (cmd);
    memcpy (PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len),
        cmd, len);
    PARTINFO (session->part, sp1p_buf_len) += len;
}

/*----------------------------------------*/

static void
i28_inc_buflen (
    tin01_sql_session * session,
    tsp00_Int4 bufpos,
    int sqllen)
{
    /* ROUTINE_DBG_MSP00 ("i28_inc_buflen"); */
    int newlen = bufpos + sqllen;

    /* old: PARTINFO (session->part, sp1p_buf_len) += sqllen + 1; */
    if (PARTINFO (session->part, sp1p_buf_len) < newlen)
        PARTINFO (session->part, sp1p_buf_len) = newlen;
}

/*----------------------------------------*/

int
i28parg (
    tin01_sql_session * session,
    const tin01_byte * arg,
    int varlen,  /* in bytes */
    int sqllen,  /* in bytes */
    tsp00_Int4 bufpos,
    char defByte)
{
    /* ROUTINE_DBG_MSP00 ("i28parg"); */
    int             mvlen;
    tin01_byte      *bufaddr;
    int             maxlen;
    tsp1_packet    *send_packet = session->send_packet;

    if (arg == NULL) {
        i28pnull (session, sqllen, bufpos);
        return cin01_db_ok;
    }
    --sqllen;                   /* because of defined byte */
    ASSERT_DBG (send_packet != NULL);
    /*
     * IFTRACE_MIN01(4, j99tprintf (SQLTRACE, "
     * arg: "PFMT"; varlen: %d; sqllen: %d; bufpos: %ld; %s\n",
     * arg, varlen, sqllen, bufpos, ischar?"is char":"is tin01_byte" ));
     */
    bufaddr = (tin01_byte *) (PARTDATA (session->part) + bufpos - 1);
    *bufaddr++ = defByte;
    maxlen = sqllen;
    if (varlen < sqllen)
        mvlen = varlen;
    else
        mvlen = sqllen;
    memcpy (bufaddr, arg, mvlen);

    if (maxlen > mvlen) {
        memset (bufaddr + mvlen, defByte, maxlen - mvlen);
    }
    i28_inc_buflen (session, bufpos, sqllen);
    return cin01_db_ok;
}

/*----------------------------------------*/

int
i28putUCS2 (
    tin01_sql_session * session,
    const tin01_byte * arg,
    const tsp77encoding * srcEncoding,
    int varlen,  /* in bytes */
    int sqllen,  /* in bytes */
    tsp00_Int4 bufpos)
{
    /* ROUTINE_DBG_MSP00 ("i28parg"); */
    int             mvlen;
    tin01_byte      *bufaddr;
    int             maxlen;
    tsp1_packet    *send_packet = session->send_packet;
    tsp78ConversionResult convResult;
    tsp00_Uint4 bytesWritten;
    tsp00_Uint4 bytesParsed;
    int         result;

    if (arg == NULL) {
        i28pnull (session, sqllen, bufpos);
        return cin01_db_ok;
    }
    --sqllen;                   /* because of defined byte */
    ASSERT_DBG (send_packet != NULL);
    bufaddr = (tin01_byte *) (PARTDATA (session->part) + bufpos - 1);
    *bufaddr++ = ' ';
    convResult = sp78convertString (
        sp77encodingUCS2Native, bufaddr, sqllen, &bytesWritten, false,
        srcEncoding, arg, varlen, &bytesParsed);
    if ((convResult == sp78_Ok) && (bytesWritten < sqllen)) {
        void * fillTarget = bufaddr + bytesWritten;
        unsigned int remainingLen = sqllen - bytesWritten;
        sp77encodingUCS2Native->fillString (&fillTarget, &remainingLen,
            remainingLen, ' ');
    }
    i28_inc_buflen (session, bufpos, sqllen);
    if (convResult == sp78_Ok) {
        result = cin01_db_ok;
    }
    else {
        result = -817;
    }
    return result;
}

/*----------------------------------------*/

void
i28pnull (
    tin01_sql_session * session,
    int sqllen,
    tsp00_Int4 bufpos)
{
    /* ROUTINE_DBG_MSP00 ("i28pnull"); */
    tin01_byte           *bufaddr;
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    bufaddr = (tin01_byte *) (PARTDATA (session->part) + bufpos - 1);
    *bufaddr = (tin01_byte) csp_undef_byte;
#if !defined (FAST)
    memset (bufaddr + 1, '\0', sqllen - 1);
#endif
    i28_inc_buflen (session, bufpos, sqllen);
}

/*----------------------------------------*/

void
i28ppw (
    tin01_sql_session * session,
    tsp00_CryptPw pw,
    char defbyte)
{
    /* ROUTINE_DBG_MSP00 ("i28ppw"); */
    tin01_byte           *bufaddr;
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    bufaddr = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    *bufaddr = defbyte;
    memcpy (bufaddr + 1, pw, sizeof (tsp00_CryptPw));
    PARTINFO (session->part, sp1p_buf_len) += sizeof (tsp00_CryptPw) + 1;
}

/*----------------------------------------*/

void
i28gparseid (
    tin01_sql_session * session,
    tin01_parseid pid)
{
    /* ROUTINE_DBG_MSP00 ("i28gparseid"); */
    tsp1_packet    *rec_packet = session->rec_packet;
    tin01_bool           found;

    ASSERT_DBG (rec_packet != NULL);
    found = i28findpart (session, sp1pk_parsid);
    if (found) {
        memcpy (pid, PARTDATA (session->part), sizeof (tin01_parseid));
    }
    else {
        memset (pid, '\0', sizeof (tin01_parseid));
        pid[mxin1_parseid - 2] = csp1_p_use_adbs;
    }
}

/*----------------------------------------*/

int
i28paramcount (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28paramcount"); */
    if (i28findpart (session, sp1pk_shortinfo))
        return PARTINFO (session->part, sp1p_arg_count);
    else {
        /*
         * currently, no hostvars -> no shortinfo part
         */
        return 0;
    }
}

/*----------------------------------------*/

tsp1_param_info *
i28gparaminfo (
    tin01_sql_session * session,
    int i)
{
    /* ROUTINE_DBG_MSP00 ("i28gparaminfo"); */
    tsp1_param_info *paramInfo;

    ASSERT_DBG (session->rec_packet != NULL);
    /* ASSERT_DBG (j02between (i, 0, i28paramcount (session) - 1));*/
    i28findpart (session, sp1pk_shortinfo);
    paramInfo = (tsp1_param_info *) (void*) PARTDATA (session->part);
    return paramInfo + i;
}

/*----------------------------------------*/

tsp00_Int4
i28nameslen (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28nameslen"); */
    i28findpart (session, sp1pk_columnnames);
    return PARTINFO (session->part, sp1p_buf_len);
}

/*----------------------------------------*/

tin01_cstr
i28colnames (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28colnames"); */
    i28findpart (session, sp1pk_columnnames);
    return PARTDATA (session->part);
}

/*----------------------------------------*/

tin01_bool
i28garg (
    tin01_sql_session * session,
    tin01_byte * arg,
    int varlen,
    int sqllen,
    tsp00_Int4 bufpos)
{
    /* ROUTINE_DBG_MSP00 ("i28garg"); */
    int             mvlen;
    unsigned char  *bufaddr;
    tsp1_packet    *rec_packet = session->rec_packet;

    ASSERT_DBG (rec_packet != NULL);
    if (varlen < sqllen)
        mvlen = varlen;
    else
        mvlen = sqllen;
    bufaddr = (unsigned char *) (PARTDATA (session->part) + bufpos - 1);
    if (*bufaddr == (unsigned char) csp_undef_byte)
        return false;
    memcpy (arg, bufaddr + 1, mvlen);
    return true;
}

/*----------------------------------------*/

tin01_byte           *
i28argaddr (
    tin01_sql_session * session,
    tsp00_Int4 bufpos)
{
    /* ROUTINE_DBG_MSP00 ("i28argaddr"); */
    unsigned char  *bufaddr;
    tin01_byte           *byteaddr;
    tin01_byte           *result;
    tsp1_packet    *rec_packet = session->rec_packet;

    ASSERT_DBG (rec_packet != NULL);
    ASSERT_DBG (PARTINFO (session->part, sp1p_part_kind) == sp1pk_data);
    byteaddr = PARTDATA (session->part) + bufpos - 1;
    bufaddr = (unsigned char *) byteaddr;
    if (*bufaddr == (unsigned char) csp_undef_byte)
        result = NULL;
    else
        result = byteaddr + 1;
    return result;
}

/*----------------------------------------*/

tsp00_Int4
i28resultcount (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28resultcount"); */
    tsp00_Int4        result = UNDEF_SP00;
    tin01_byte      *number;
    tsp00_NumError   res;
    tsp1_part      *part_ptr;

    if (i28_findpart (session, sp1pk_resultcount, &part_ptr)) {
        number = PARTDATA (part_ptr) + 1;
        s40glint ((tsp00_Number*)number, 1,
                (PARTINFO (part_ptr, sp1p_buf_len) - 2) * 2, &result, &res);
    }
    return result;
} /* i28resultcount */

/*----------------------------------------*/

static void
i28_machinfo (
    tsp00_CodeType *code_type,
    tsp00_SwapKind *swap_kind,
    char          *termid)
{
    /* ROUTINE_DBG_MSP00 ("i28_machinfo"); */
    tsp00_Int4        i234;
    char             *c234;
    tsp100_VersionID0 VersionID0;

    *code_type = csp_ascii;
    i234 = 1;
    c234 = (char *) &i234;
    if (c234[3] == 1)
        (*swap_kind) = sw_normal;
    else if (c234[0] == 1)
        (*swap_kind) = sw_full_swapped;
    else
        (*swap_kind) = sw_part_swapped;

    sp100_GetVersionID ( VersionIDType0_esp100, s100buildnumberEx, &VersionID0 );

    sprintf(termid, "%01d%02d%02d",
                    (int) VersionID0.MajorVersion_sp100,
                    (int) VersionID0.MinorVersion_sp100,
                    (int) VersionID0.CorrLevel_sp100);
    memcpy (termid + sizeof (tsp00_C5), csp_comp_db_manager, sizeof (tsp00_C3));
}

/*----------------------------------------*/

int
i28adbs (
    tin01_sql_session * session,
    tin01_cstr cmd)
{
    /* ROUTINE_DBG_MSP00 ("i28adbs"); */
    i28initadbs (session);
    SENDINFO (session->segment, sp1c_with_info) = true;
    i28pcmd (session, cmd, UNDEF_SP00);
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28adbs_noinfo (
    tin01_sql_session * session,
    tin01_cstr cmd,
    bool withCommit)
{
    /* ROUTINE_DBG_MSP00 ("i28adbs_noinfo"); */
    i28initadbs (session);
    i28pcmd (session, cmd, UNDEF_SP00);
    if (withCommit) {
        session->segment->variant.C_3.sp1c_commit_immediately_F = true;
    }
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28adbsf (
    tin01_sql_session * session,
    tin01_cstr cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28adbsf"); */
    va_list         args;
    int             bytecnt;
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    va_start (args, cmd);
    i28initadbs (session);
    bytecnt = vsprintf (PARTDATA (session->part), cmd, args);
    va_end (args);
    if (bytecnt < 0)
        return UNDEF_SP00;
    PARTINFO (session->part, sp1p_buf_len) = bytecnt;
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28adbsinfof (
    tin01_sql_session * session,
    tin01_cstr cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28adbsinfof"); */
    va_list         args;
    int             bytecnt;
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    va_start (args, cmd);
    i28initadbs (session);
    SENDINFO (session->segment, sp1c_with_info) = true;
    bytecnt = vsprintf (PARTDATA (session->part), cmd, args);
    va_end (args);
    if (bytecnt < 0)
        return UNDEF_SP00;
    PARTINFO (session->part, sp1p_buf_len) = bytecnt;
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28adbs_describe (
    tin01_sql_session * session,
    tin01_parseid       pid)
{
    /* ROUTINE_DBG_MSP00 ("i28adbs_describe"); */
    int             bytecnt;
    tsp1_packet    *send_packet = session->send_packet;

    TRACEF_MIN01 (7, (SQLTRACE, "i28adbs_describe\n"));
    ASSERT_DBG (send_packet != NULL);
    i28initadbs (session);
    bytecnt = sprintf (PARTDATA (session->part), "%s", "DESCRIBE ");

    if (bytecnt < 0)
        return UNDEF_SP00;
    PARTINFO (session->part, sp1p_buf_len) = bytecnt;

    i28newpart (session, sp1pk_data);
    memcpy (PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len),
        pid, sizeof (tin01_parseid));
    PARTINFO (session->part, sp1p_buf_len) += sizeof (tin01_parseid);
    TRACEF_MIN01 (7, (SQLTRACE, "<-i28adbs_describe rc : i28sql\n"));
    return i28sql (session, NULL);
}   /* i28adbs_describe */

/*----------------------------------------*/


#define c_max_try  5

static int
i28_parse (
    tin01_sql_session * session,
    tin01_cstr cmd,
    tin01_c_sqlca * sqlca,
    tin01_bool internal)
{
    /* ROUTINE_DBG_MSP00 ("i28_parse"); */
    int             rc;
    int             paramCount;

    if (sqlca->inUse)
        return cin01_db_ok;
    i28initparse (session);
    if (internal)
        SENDINFO (session->segment, sp1c_producer) = sp1pr_internal_cmd;
    i28pcmd (session, cmd, UNDEF_SP00);
    rc = i28sql (session, NULL);
    if (rc == cin01_db_ok) {
        i28gparseid (session, sqlca->pid);
        paramCount = i28paramcount (session);
        if (paramCount > sqlca->varCount)
            paramCount = sqlca->varCount;
/*            rc = -1200; */        /* too few values */
/*        else { */
            sqlca->paramCount = paramCount;
            if (paramCount > 0) {
                tsp1_param_info *pinfo = i28gparaminfo (session, 0);
                int              i;

                for (i = 0; i < paramCount; ++i, ++pinfo) {
                    memcpy (&sqlca->hostVar [i].pinfo, pinfo,
                            sizeof (tsp1_param_info));
                }
            }
            sqlca->inUse = true;
/*        } */
    }
    return rc;
}

/*----------------------------------------*/

static          int
i28_put_num_string (
    tin01_sql_session * session,
    char *arg,
    tsp1_param_info * paramInfo)
{
    /* ROUTINE_DBG_MSP00 ("i28_put_num_string"); */
    tsp00_NumError   res;
    int             frac;

    frac = paramInfo->sp1i_frac;
    switch (paramInfo->sp1i_data_type) {
        case dfloat:
        case dvfloat:
            frac = -1;
            /* fall through */
        case dinteger:
        case dsmallint:
        case dfixed:
            {
                tsp00_Number num;

                s43pstr (&num, 1, paramInfo->sp1i_length, frac,
                    arg, 1, strlen(arg), &res);
                if (res != num_ok)
                    return cin01_db_invalid_number;
                return i28parg (session, (char *) num,
                    paramInfo->sp1i_in_out_len,
                    paramInfo->sp1i_in_out_len,
                    paramInfo->sp1i_bufpos, csp_defined_byte);
            }
     default:
            SWITCH_ERROR_DBG_MIN00 ("data type %d not yet implemented",
                paramInfo->sp1i_data_type );
            break;
    }
    return cin01_db_ok;
}

/*----------------------------------------*/

static          int
i28_put_bool_string (
    tin01_sql_session * session,
    char             * arg,
    int                datalen,
    tsp1_param_info  * paramInfo)
{
    /* ROUTINE_DBG_MSP00 ("i28_put_bool_string"); */
   char            BoolVal;
   tsp00_C20         Temp;
   tsp00_Int4        NumVal;
   tsp00_NumError   res;
   int             i;

   if (datalen == UNDEF_SP00)
      datalen = strlen(arg);
   strncpy ((char *) Temp, arg, datalen);
   Temp [datalen] = '\0';
   for (i = 0; i < datalen; ++i) {
       Temp [i] = (char) toupper (Temp [i]);
   }

   if (strcmp ((char *) Temp, "true") == 0)
      BoolVal = '\1';
   else if (strcmp ((char *) Temp, "false") == 0)
      BoolVal = '\0';
   else {
       s45stoi4 (&NumVal, arg, 1, strlen (arg), &res);
       if (res != num_ok)
          return cin01_db_invalid_number;
       if (NumVal == 0)
          BoolVal = '\0';
      else
          BoolVal = '\1';
   }
   return i28parg (session, &BoolVal, 1, paramInfo->sp1i_in_out_len,
      paramInfo->sp1i_bufpos, csp_defined_byte);
}

/*----------------------------------------*/

static          int
i28_inarg (
    tin01_sql_session * session,
    tin01_c_hostvar * hostVar)
{
    /* ROUTINE_DBG_MSP00 ("i28_inarg"); */
    int             datalen;
    void           *dataptr;
    unsigned char   defByte = csp_undef_byte;
    tsp1_param_info *paramInfo = &hostVar->pinfo;

    if (hostVar->addr == NULL) {
        i28pnull (session, paramInfo->sp1i_length, paramInfo->sp1i_bufpos);
        return cin01_db_ok;
    }
    switch (paramInfo->sp1i_data_type) {
        case dfixed:
        case dfloat:
        case dvfloat:
        case dsmallint:
        case dinteger:
            if (hostVar->c_type != cin01_c_charp) {
                SWITCH_ERROR_DBG_MIN00 ("Numeric sql type %d not implemented "
                    "for nonstring C type ", paramInfo->sp1i_data_type);
                break;
            }
            return i28_put_num_string (session, (char*)hostVar->addr, paramInfo);
            break;
       case dboolean:
           /* put boolean value */
            if (hostVar->c_type != cin01_c_charp) {
                SWITCH_ERROR_DBG_MIN00 ("%s not implemented "
                    "for nonstring C type ", "boolean");
                break;
           }
           return i28_put_bool_string
                      (session, (char*)hostVar->addr, (int) hostVar->len, paramInfo);
           break;
        case dchb:
        case dvarcharb:
           defByte = csp_defined_byte;
           /* fall through */
        case dcha:
        case dche:
        case dvarchara:
        case dvarchare:
        case ddate:
        case dtime:
        case dtimestamp:
        case dunicode:
            /* put string value */
            if (hostVar->c_type == cin01_c_charpp)
                dataptr = *(char **) hostVar->addr;
            else
                dataptr = hostVar->addr;
            if (hostVar->len >= 0)
                datalen = (int) hostVar->len;
            else {
                datalen = strlen ((char*)dataptr);
            }
            if (defByte == csp_undef_byte) {
            /* sp1_data_type is not a BYTE type  */
                defByte = csp_defined_byte;
            }
             return i28parg (session, (char*)dataptr, datalen,
                paramInfo->sp1i_in_out_len,
                paramInfo->sp1i_bufpos, defByte);
             break;
        default:
            SWITCH_ERROR_DBG_MIN00 ("sql type not supported %d",
                (int) paramInfo->sp1i_data_type);
            break;
    }
    return cin01_db_ok;
}

/*----------------------------------------*/

static int
i28_inargs (
    tin01_sql_session * session,
    tin01_c_sqlca * sqlca)
{
    /* ROUTINE_DBG_MSP00 ("i28_inargs"); */
    int             i;
    tin01_bool           hasDataPart = false;
    int             rc;

    i28initexecute (session, sqlca->pid);
    for (i = 0; i < sqlca->paramCount; ++i) {
        if (sqlca->hostVar [i].pinfo.sp1i_io_type != sp1io_output) {
            if (!hasDataPart) {
                i28newpart (session, sp1pk_data);
                hasDataPart = true;
            }
            rc = i28_inarg (session, &sqlca->hostVar[i]);
            if (rc != cin01_db_ok)
                return rc;
        }
    }
    return cin01_db_ok;
}

/*----------------------------------------*/

static          tsp00_Int4
i28_get_num_param (
    void *addr,
    tsp1_param_info * paramInfo)
{
    /* ROUTINE_DBG_MSP00 ("i28_get_num_param"); */
    tsp00_NumError   res;
    tsp00_Int4        resval;

    s40glint ((tsp00_Number*)addr, 1,
        paramInfo->sp1i_in_out_len,
        &resval, &res);
    return resval;
}

/*----------------------------------------*/

static void
i28_num_param_to_string (
    char *DestStr,
    void *addr,
    tsp1_param_info * paramInfo)
{
    /* ROUTINE_DBG_MSP00 ("i28_num_param_to_string"); */
    int len;
    tsp00_DecimalPresentation decimal;
    tsp00_NumError res;

    decimal.thousand_token = 'N';
    decimal.zero_point = '.';
    s44egchr (addr, 1,
        paramInfo->sp1i_in_out_len,
        paramInfo->sp1i_frac, DestStr, 1, &len,
        &decimal, &res);
    DestStr [len] = '\0';
}

/*----------------------------------------*/

tin01_byte           *
i28_longargaddr (
    tin01_sql_session * session,
    tsp1_param_info * paramInfo)
{
    /* ROUTINE_DBG_MSP00 ("i28_longargaddr"); */
    unsigned char  *bufaddr;
    tsp00_LongDescriptor *descriptor;
    tin01_byte           *byteaddr;
    tin01_byte           *result;
    tsp1_packet    *rec_packet = session->rec_packet;

    ASSERT_DBG (rec_packet != NULL);
    ASSERT_DBG (paramInfo->sp1i_length == sizeof (tsp00_LongDescriptor));
    ASSERT_DBG (PARTINFO (session->part, sp1p_part_kind) == sp1pk_data);
    byteaddr = PARTDATA (session->part) + paramInfo->sp1i_bufpos - 1;
    bufaddr = (unsigned char *) byteaddr;
    if (*bufaddr == (unsigned char) csp_undef_byte)
        return NULL;
    descriptor = (tsp00_LongDescriptor *)(byteaddr + 1);
    result = PARTDATA (session->part) + descriptor->variant.C_false.ld_valpos_F - 1;
    paramInfo->sp1i_length = descriptor->variant.C_false.ld_vallen_F;
    return result;
}

/*----------------------------------------*/

static int
i28_get_stringvalue (
    tin01_sql_session    * session,
    tsp1_param_info     * paramInfo,
    tin01_c_hostvar      * hostVar,
    void                * addr)
{
    /* ROUTINE_DBG_MSP00 ("i28_get_stringvalue"); */
    int       datalen; /* bytewise */
    char    * hostbuf;

    TRACEF_MIN01 (5, (session->tracer, "i28_get_stringvalue; input value:\n"));
    IFTRACE_MIN01 (5, j99hexbuf (addr, 0,
        paramInfo->sp1i_length * sizeof (tin01_unichar),
        10, session->tracer));
    datalen = s30klen (addr, ' ', paramInfo->sp1i_length);
    if (hostVar->c_type == cin01_c_charpp) {
        hostbuf = (char *) malloc (datalen + 1);
        ASSERT_DBG (NOT_NULL_MIN01 (hostbuf));
        *((void **) hostVar->addr) = hostbuf;
    }
    else
        hostbuf = (char*) hostVar->addr;
    memcpy (hostbuf, addr, datalen);
    hostbuf[datalen] = '\0';
    return cin01_db_ok;
}

/*----------------------------------------*/

static int
i28_outarg (
    tin01_sql_session * session,
    tin01_c_hostvar * hostVar)
{
    /* ROUTINE_DBG_MSP00 ("i28_outarg"); */
    void           *addr;
    char           *hostbuf;
    tsp1_param_info * paramInfo = &hostVar->pinfo;
    int             rc = cin01_db_ok;

    switch (paramInfo->sp1i_data_type) {
        case dstra:
        case dstre:
        case dstrb:
        case dstrdb:
            addr = i28_longargaddr (session, paramInfo);
            break;
        default:
            addr = i28argaddr (session, paramInfo->sp1i_bufpos);
            break;
    }
    if (addr == NULL) {
        hostVar->is_null = true;
        return rc;
    }
    else
        hostVar->is_null = false;
    switch (paramInfo->sp1i_data_type) {
        case dfixed:
        case dfloat:
        case dvfloat:
        case dsmallint:
        case dinteger:
            switch (hostVar->c_type) {
                case cin01_c_short:
                    *((short *) hostVar->addr) =
                        (short) i28_get_num_param (addr, paramInfo);
                    break;
                case cin01_c_ushort:
                    *((unsigned short *) hostVar->addr) =
                        (unsigned short) i28_get_num_param (addr, paramInfo);
                    break;
                case cin01_c_int:
                    *((int *) hostVar->addr) =
                        (int) i28_get_num_param (addr, paramInfo);
                    break;
                case cin01_c_uint:
                    *((unsigned int *) hostVar->addr) =
                        (unsigned int) i28_get_num_param (addr, paramInfo);
                    break;
                case cin01_c_long:
                    *((long *) hostVar->addr) =
                        i28_get_num_param (addr, paramInfo);
                    break;
                case cin01_c_ulong:
                    *((unsigned long *) hostVar->addr) =
                        (unsigned long) i28_get_num_param (addr, paramInfo);
                    break;
                case cin01_c_charp:
                    i28_num_param_to_string ((char*) hostVar->addr, addr, paramInfo);
                    break;
                default:
                    SWITCH_ERROR_DBG_MIN00 ("FIXED to hostvar type %d not supported",
                        (int) hostVar->c_type);
                    break;
            }
            break;
        case dcha:
        case dche:
        case dchb:
        case dunicode:
        case dvarchara:
        case dvarchare:
        case dvarcharb:
        case ddate:
        case dtime:
        case dtimestamp:
        case dstra:
        case dstre:
        case dstrb:
        case dstrdb:
            rc = i28_get_stringvalue (session, paramInfo, hostVar, addr);
            break;
        case dboolean:
           {
               const char *result;
               hostbuf = (char*) hostVar->addr;
               if (hostVar->c_type == cin01_c_charp) {
                   if (*((char *)addr))
                       result = "true";
                   else
                       result = "false";

                   strcpy (hostbuf, result);
               }
               else {
                   SWITCH_ERROR_DBG_MIN00 ("boolean not supported for C type %d",
                       (int) hostVar->c_type);
               }
               break;
           }
        default:
            SWITCH_ERROR_DBG_MIN00 ("sql type not supported %d",
                (int) paramInfo->sp1i_data_type);
            break;
    }
    return rc;
}

/*----------------------------------------*/

static int
i28_outargs (
    tin01_sql_session * session,
    tin01_c_sqlca * sqlca)
{
    /* ROUTINE_DBG_MSP00 ("i28_outargs"); */
    int             i;
    int             rc = cin01_db_ok;

    i28findpart (session, sp1pk_data);
    for (i = 0; i < sqlca->paramCount; ++i) {
        if ((int) sqlca->hostVar [i].pinfo.sp1i_io_type != sp1io_input) {
            rc = i28_outarg (session, &sqlca->hostVar[i]);
            if (rc != cin01_db_ok)
                return rc;
        }
    }
    return rc;
}

/*----------------------------------------*/

static          tin01_bool
i28_try_again (
    int rc)
{
    /* ROUTINE_DBG_MSP00 ("i28_try_again"); */
    tin01_bool           result;

    switch (rc) {
        case -8:               /* parse again */
        case 500:              /* wait for lock release */
        case 700:              /* timeout */
            result = true;
            break;
        default:
            result = false;
            break;
    }
    return result;
}

/*----------------------------------------*/

int
i28sqlcmd (
    tin01_sql_session * session,
    tin01_c_sqlca * sqlca,
    tin01_cstr cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28sqlcmd"); */
    va_list         args;
    int             rc;
    int             trycnt = 0;
    tin01_bool      try_again = true;
    int             i;

    do {
        rc = i28_parse (session, cmd, sqlca, false);
        if (rc == cin01_db_ok) {
            va_start (args, cmd);
            for (i = 0; i < sqlca->varCount; ++i) {
                sqlca->hostVar[i].addr = va_arg (args, void *);
            }
            va_end (args);
            rc = i28_inargs (session, sqlca);
            if (rc == cin01_db_ok)
                rc = i28sql (session, NULL);
            if (rc == cin01_db_ok) {
                rc = i28_outargs (session, sqlca);
            }
        }
        if (i28_try_again (rc)) {
            try_again = true;
            sqlca->inUse = false;
        }
        else
            try_again = false;
        ++trycnt;
    }
    while (try_again && (trycnt < c_max_try));
    return rc;
}

/*----------------------------------------*/

int
i28sqlcmdArr (
    tin01_sql_session * session,
    tin01_c_sqlca * sqlca,
    tin01_cstr cmd,
    char *args[])
{
    /* ROUTINE_DBG_MSP00 ("i28sqlcmdArr"); */
    int             rc;
    int             trycnt = 0;
    tin01_bool           try_again = true;
    int             i;

    do {
        rc = i28_parse (session, cmd, sqlca, false);
        if (rc == cin01_db_ok) {
            for (i = 0; i < sqlca->varCount; ++i) {
                sqlca->hostVar[i].addr = args[i];
            }
            rc = i28_inargs (session, sqlca);
            if (rc == cin01_db_ok)
                rc = i28sql (session, NULL);
            if (rc == cin01_db_ok) {
                rc = i28_outargs (session, sqlca);
            }
        }
        if (i28_try_again (rc)) {
            try_again = true;
            sqlca->inUse = false;
        }
        else
            try_again = false;
        ++trycnt;
    }
    while (try_again && (trycnt < c_max_try));
    return rc;
}

/*----------------------------------------*/

int
i28internalcmd (
    tin01_sql_session * session,
    tin01_c_sqlca * sqlca,
    tin01_cstr cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28internalcmd"); */
    va_list         args;
    int             rc;
    int             trycnt = 0;
    tin01_bool       try_again = true;
    int             i;

    do {
        rc = i28_parse (session, cmd, sqlca, true);
        if (rc == cin01_db_ok) {
            va_start (args, cmd);
            for (i = 0; i < sqlca->varCount; ++i) {
                sqlca->hostVar[i].addr = va_arg (args, void *);
            }
            va_end (args);
            rc = i28_inargs (session, sqlca);
            if (rc == cin01_db_ok)
                rc = i28sql (session, NULL);
            if (rc == cin01_db_ok) {
                rc = i28_outargs (session, sqlca);
            }
        }
        if (i28_try_again (rc)) {
            try_again = true;
            sqlca->inUse = false;
        }
        else
            try_again = false;
        ++trycnt;
    }
    while (try_again && (trycnt < c_max_try));
    return rc;
}

/*----------------------------------------*/

int
i28longiolen (
    int d_type,
    int len)
{
    /* ROUTINE_DBG_MSP00 ("i28longiolen"); */
    int             result;

    switch (d_type) {
        case dfixed:
        case dfloat:
        case dvfloat:
        case dsmallint:
        case dinteger:
            result = ((len + 1) / 2) + 1;
            break;
        case dboolean:
            result = 1;
            break;
        default:
            result = len;
            break;
    }
    return result + 1;
}

/*----------------------------------------*/

void
i28errmsg (
    tin01_sql_session * session,
    tsp00_C256c       * errbuf)
{
    /* ROUTINE_DBG_MSP00 ("i28errmsg"); */

    (*errbuf)[0] = '\0';

    if (session->rec_packet != NULL) {
        if (RECINFO (session->segment, sp1r_returncode) != cin01_db_ok) {
            int     msglen;
            char    *errbuffer;

            if (i28findpart(session, sp1pk_errortext)) {
                errbuffer = PARTDATA (session->part);
                msglen = s30klen (errbuffer, ' ', (int) PARTINFO (session->part, sp1p_buf_len));

                if (msglen > sizeof (*errbuf))
                    msglen = sizeof (*errbuf);

                memcpy (*errbuf, errbuffer, msglen);
                (*errbuf)[msglen] = '\0';
            } /* end if */
        } /* end if */
    }else{
        if (session->lasterr.lasterr_on){
            size_t minlen = sizeof (*errbuf);

            if(minlen>sizeof(tsp00_ErrText)-1)
                minlen = sizeof(tsp00_ErrText)-1;

            memcpy(*errbuf, session->lasterr.errtext, minlen);
            (*errbuf)[minlen] = '\0';
        } /* end if */
    } /* end if */

} /* end i28errmsg */

/*----------------------------------------*/

int
i28droppid (
    tin01_sql_session * session,
    tin01_parseid pid)
{
    /* ROUTINE_DBG_MSP00 ("i28droppid"); */
    tsp1_packet    *send_packet = session->send_packet;

    ASSERT_DBG (send_packet != NULL);
    i28initadbs (session);
    i28pcmd (session, "DROP PARSEID", UNDEF_SP00);
    i28newpart (session, sp1pk_parsid);
    memcpy (PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len),
        pid, sizeof (tin01_parseid));
    PARTINFO (session->part, sp1p_buf_len) += sizeof (tin01_parseid);
    return i28sql (session, NULL);
}

/*----------------------------------------*/

#define c_layerstr_len   20
#define c_routinename_len 16

int
i28switch (
    tin01_sql_session * session,
    tin01_cstr trace,
    tin01_cstr test)
{
    /* ROUTINE_DBG_MSP00 ("i28switch"); */
    tsp00_Int2        result;

    if (!session->switch_possible) {
        return cin01_db_ok;
    }
    i28_reset (session, true);
    i28newsegment (session, sp1m_switch);
    i28newpart (session, sp1pk_command);
    i28pascalstring (PARTDATA (session->part), c_layerstr_len, trace, UNDEF_SP00);
    i28pascalstring (PARTDATA (session->part) + c_layerstr_len,
        c_layerstr_len, test, UNDEF_SP00);
    PARTINFO (session->part, sp1p_buf_len) = 2 * c_layerstr_len;
    result = i28sql (session, NULL);
    if (result != cin01_db_ok) {
        /* next time be quiet */
        TRACE_MIN01 (4, SQLTRACE, "SWITCH disabled after failure\n");
        session->switch_possible = false;
    }
    return result;
}

/*----------------------------------------*/

int
i28switchlimit (
    tin01_sql_session * session,
    tin01_cstr trace,
    tin01_cstr test,
    tin01_cstr start,
    tin01_cstr stop,
    int limit)
{
    /* ROUTINE_DBG_MSP00 ("i28switchlimit"); */
    tsp00_Int2 result;
    int pos = 0;
    unsigned char buf [2];

    if (!session->switch_possible) {
        return cin01_db_ok;
    }
    i28_reset (session, true);
    i28newsegment (session, sp1m_switchlimit);
    i28newpart (session, sp1pk_command);
    i28pascalstring (PARTDATA (session->part), c_layerstr_len, trace, UNDEF_SP00);
    pos += c_layerstr_len;
    i28pascalstring (PARTDATA (session->part) + pos,
        c_layerstr_len, test, UNDEF_SP00);
    pos += c_layerstr_len;
    i28pascalstring (PARTDATA (session->part) + pos,
        c_routinename_len, start, UNDEF_SP00);
    pos += c_routinename_len;
    i28pascalstring (PARTDATA (session->part) + pos,
        c_routinename_len, stop, UNDEF_SP00);
    pos += c_routinename_len;
    PARTINFO (session->part, sp1p_buf_len) = pos;
    buf [0] = limit / 256;
    buf [1] = limit % 256;
    i28pcmd (session, (const char *) buf, sizeof (buf));
    result = i28sql (session, NULL);
    if (result != cin01_db_ok) {
        /* next time be quiet */
        TRACE_MIN01 (4, SQLTRACE, "SWITCH disabled after failure\n");
        session->switch_possible = false;
    }
    return result;
}

/*----------------------------------------*/

int
i28buflimit (
    tin01_sql_session * session,
    int limit)
{
    /* ROUTINE_DBG_MSP00 ("i28buflimit"); */
    tsp00_Int2        result;
    unsigned char buf [2];

    if (!session->switch_possible) {
        return cin01_db_ok;
    }
    i28_reset (session, true);
    i28newsegment (session, sp1m_buflength);
    i28newpart (session, sp1pk_command);
    buf [0] = limit / 256;
    buf [1] = limit % 256;
    i28pcmd (session, (const char *) buf, sizeof (buf));
    result = i28sql (session, NULL);
    if (result != cin01_db_ok) {
        /* next time be quiet */
        TRACE_MIN01 (4, SQLTRACE, "SWITCH disabled after failure\n");
        session->switch_possible = false;
    }
    return result;
}

/*----------------------------------------*/

static int
i28_minmaxbuf (
    tin01_sql_session * session,
    tsp1_cmd_mess_type_Enum messKind)
{
    /* ROUTINE_DBG_MSP00 ("i28_minmaxbuf"); */
    tsp00_Int2        result;

    if (!session->switch_possible) {
        return cin01_db_ok;
    }
    i28_reset (session, true);
    i28newsegment (session, messKind);
    i28newpart (session, sp1pk_command);
    result = i28sql (session, NULL);
    if (result != cin01_db_ok) {
        /* next time be quiet */
        TRACE_MIN01 (4, SQLTRACE, "SWITCH disabled after failure\n");
        session->switch_possible = false;
    }
    return result;
}

/*----------------------------------------*/

int
i28minbuf (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28minbuf"); */

    return i28_minmaxbuf (session, sp1m_minbuf);
}

/*----------------------------------------*/

int
i28maxbuf (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28maxbuf"); */

    return i28_minmaxbuf (session, sp1m_maxbuf);
}

/*----------------------------------------*/

/**\
--- ----------------------------------MF__ MOD__ high level select
    Here some functions providing a interface for execute select
    statements and retrieve the results
\**/

/*----------------------------------------*/

#define cin28_cont_cont "CONTINUE\n"
#define cin28_cont_end  "END     \n"
#define cin28_cont_len  (strlen(cin28_cont_end))
#define cin28_min_len   10
#define cin28_nulltext  "(null)"

/*----------------------------------------*/

/* checks if a data type of the db is a string type
   (for seting of string delimiter sin the result) */
static tin01_bool
i28_isstring (tsp00_DataType aDataType)
{
    /* ROUTINE_DBG_MSP00 ("i28_isstring"); */

  tin01_bool bRc = false;

  switch(aDataType) {
    /* Had I hit all data types??? */
    case dcha:
    case dche:
    case dchb:
    case dunicode:
    case dvarchara:
    case dvarchare:
    case dvarcharb:
    case ddate:
    case dtime:
    case dtimestamp:
    case dstra:
    case dstre:
    case dstrb:
    case dstrdb:
      bRc = true;
  } /* end switch */

  return bRc;

} /* end i28_isstring */

/*----------------------------------------*/

/* calculates a approximate length of one result record */
static int
i28_rowlen (
    tin01_sql_session  * session)
{
    /* ROUTINE_DBG_MSP00 ("i28_rowlen"); */

    int               nParamCount = 0,
                      i           = 0,
                      nRowLen     = 0;
    tsp1_param_info * pParamInfo  = NULL;

    /**/

    /* get some infos */
    pParamInfo = i28gparaminfo(session, 0);
    nParamCount = i28paramcount(session);

    /* calculate approximate rowlen */
    for (i = 0; i < nParamCount; i++) {
      nRowLen = nRowLen + ((pParamInfo[i].sp1i_length < cin28_min_len) ? pParamInfo[i].sp1i_length : cin28_min_len);
    } /* end for */

    /**/

    return nRowLen;

} /* end i28_rowlen */

/*----------------------------------------*/

/* gets the selected records in the result buffer until
   nResultLen is reached
   (at first in the result buffer a keyword (END or CONTINUE)
   will indicate whether the end of result is reached or not) */
static int
i28_fetchnext (
    tin01_sql_session  * session,
    char              * pResult,
    long                nResultLen,
    char                cFieldSep,
    char                cStringDel,
    char                cRecSep)
{
    /* ROUTINE_DBG_MSP00 ("i28_fetchnext"); */

    int               rc          = cin01_db_ok,
                      i           = 0,
                      nParamCount = 0,
                      nRowLen     = i28_rowlen(session);
    tsp1_param_info * pParamInfo  = NULL;
    char            * pCurrent    = pResult;
    char            * pContinue   = NULL;
    tin01_c_hostvar    aHostVar;

    /**/

    *pResult = 0;

    /* place for end/continue mark */
    pContinue = pCurrent;
    pCurrent  = pCurrent + cin28_cont_len;

    while ((rc == cin01_db_ok) && (pCurrent - pResult + nRowLen < nResultLen) ) {

      /* get some infos */
      pParamInfo = i28gparaminfo(session, 0);
      nParamCount = i28paramcount(session);

      i28findpart (session, sp1pk_data);
      for (i = 0; i < nParamCount; i++) {

        /* set string delimiter */
        if (i28_isstring(pParamInfo[i].sp1i_data_type) && cStringDel != 0) {
          *pCurrent++ = cStringDel;
        } /* end if */

        /* fill hostvar struct */
        memset(&aHostVar, 0, sizeof(aHostVar));
        aHostVar.len = -1;
        aHostVar.c_type = cin01_c_charp;
        memcpy(&(aHostVar.pinfo), &pParamInfo[i], sizeof(tsp1_param_info));
        aHostVar.addr = pCurrent;
        *((char *) (aHostVar.addr)) = 0;

        /* read value */
        rc = i28_outarg (session, &aHostVar);

        /* check for <NULL> */
        if (aHostVar.is_null) {
          /* skip string delimiter */
          if (i28_isstring(pParamInfo[i].sp1i_data_type) && cStringDel != 0) {
            pCurrent--;
          } /* end if */
          strcpy(pCurrent, cin28_nulltext);
        } /* end if */

        pCurrent = pCurrent + strlen(pCurrent);

        /* set string delimiter */
        if (i28_isstring(pParamInfo[i].sp1i_data_type) && !aHostVar.is_null  && cStringDel != 0) {
          *pCurrent++ = cStringDel;
        } /* end if */

        if (cFieldSep != 0) {
          *pCurrent++ = cFieldSep;
        } /*end if */
      } /* end for */

      /* skip last field separator */
      if (cFieldSep != 0) {
        pCurrent--;
      } /*end if */
      if (cRecSep != 0) {
        *pCurrent++ = cRecSep;
      } /*end if */

      /* next row */
      i28_fetchcmd (session, "FETCH NEXT", nParamCount);
      SENDINFO (session->segment, sp1c_with_info) = true;
      rc =  i28sql (session, NULL);
    } /* end while */

    /* handle end/continue mark */
    if (rc == cin01_db_ok) {
      strncpy(pContinue, cin28_cont_cont, cin28_cont_len);
    } else if (rc == cin01_db_row_not_found) {
      strncpy(pContinue, cin28_cont_end, cin28_cont_len);
      rc = cin01_db_ok;
    } /* end if */

    /* skip last record separator */
    if (cRecSep != 0) {
      pCurrent--;
    } /* end if */

    *pCurrent = 0;

    return rc;

} /* end i28_fetchnext */

/*----------------------------------------*/

static int
i28_fetchnice (
    tin01_sql_session  * session,
    char               * pResult,
    char               * pCurrent,
    char               * pContinue,
    long               nResultLen,
    bool               bOneRowResult,
    long               nMaxNameLen,
    int                nRowLen,
      bool               bDataOnly)
{
    /* ROUTINE_DBG_MSP00 ("i28_fetchnice"); */

    int               rc          = cin01_db_ok;
    int               i           = 0;
    int               nParamCount = 0;
/*    int               nRowLen     = i28_rowlen(session);*/
    tsp1_param_info * pParamInfo  = NULL;
    tin01_c_hostvar   aHostVar;

    char              nLen        = 0;
/*    char              nMaxLen     = 0;*/
    short              nMaxLen     = 0;

    /**/

    while ((rc == cin01_db_ok) &&
           (pCurrent - pResult + nRowLen < nResultLen)) {

      /* get some infos */
      tin01_cstr pNames = i28colnames(session);

      pParamInfo  = i28gparaminfo(session, 0);
      nParamCount = i28paramcount(session);

      i28findpart (session, sp1pk_data);
      for (i = 0; i < nParamCount; i++) {

        nLen = *pNames;
        pNames++;

        if (bOneRowResult) {
          memcpy(pCurrent, pNames, nLen);
          pCurrent += nLen;
          memset(pCurrent, 32, nMaxNameLen - nLen);
          pCurrent += (nMaxNameLen - nLen);
          strcpy(pCurrent, " = ");
          pCurrent = pCurrent + strlen(pCurrent);
         }

        pNames += nLen;

        nMaxLen = nLen;
        if (pParamInfo[i].sp1i_length > nLen) {
          nMaxLen = pParamInfo[i].sp1i_length;
        }

        /* fill hostvar struct */
        memset(&aHostVar, 0, sizeof(aHostVar));
        aHostVar.len = -1;
        aHostVar.c_type = cin01_c_charp;
        memcpy(&(aHostVar.pinfo), &pParamInfo[i], sizeof(tsp1_param_info));
        aHostVar.addr = pCurrent;
        *((char *) (aHostVar.addr)) = 0;

        /* read value */
        rc = i28_outarg (session, &aHostVar);

        /* check for <NULL> */
        if (aHostVar.is_null) {
          strcpy(pCurrent, " "); /* cin28_nulltext */
        }

        nLen = strlen(pCurrent);

        pCurrent = pCurrent + nLen;

        memset(pCurrent, 32, nMaxLen - nLen);
        pCurrent += (nMaxLen - nLen);

        if (bOneRowResult) {
          *pCurrent++ = '\n';
        } else {
          if (i < (nParamCount -1 )) {
            *pCurrent++ = ' ';
            *pCurrent++ = '|';
            *pCurrent++ = ' ';
          }
        }
      }

      if (!bOneRowResult) {
        *pCurrent++ = '\n';
      }

      /* next row */
      i28_fetchcmd (session, "FETCH NEXT", nParamCount);
      SENDINFO (session->segment, sp1c_with_info) = true;
      rc =  i28sql (session, NULL);

    } /* end while */

    /* handle end/continue mark */
      if (!bDataOnly) {
      if (rc == cin01_db_ok) {
        strncpy(pContinue, cin28_cont_cont, cin28_cont_len);
        } else if (rc == cin01_db_row_not_found) {
        strncpy(pContinue, cin28_cont_end, cin28_cont_len);
        rc = cin01_db_ok;
        } /* end if */
      }

    *pCurrent = 0;

    return rc;
} /* end i28_fetchnice */

/*----------------------------------------*/

int
i28selectnice (
    tin01_sql_session  * session,
    tin01_cstr           cmd,
    char               * pResult,
    long                 nResultLen,
    bool                 bOneRowResult,
    bool                 bDesc,
      bool                 bDataOnly)
{
    /* ROUTINE_DBG_MSP00 ("i28selectnice"); */

    int               rc           = cin01_db_ok;
    int               i            = 0;
    int               j            = 0;
    int               nParamCount  = 0;
    tin01_cstr        pNames       = NULL;
    char            * pCurrent     = pResult;
    char            * pContinue    = NULL;
    char            * pHeader      = NULL;
    char              nLen         = 0;
    char              nMaxNameLen  = 0;
/*    char              nMaxParamLen = 0;*/
    short             nMaxParamLen = 0;
    tsp1_param_info * pParamInfo   = NULL;
/*  char              nMaxLen      = 0;*/
    short             nMaxLen      = 0;
    int               nRowLen      = 0;

    char              szDesc[255];

    /**/

    *pResult = 0;

    pContinue = pCurrent;
      if (!bDataOnly) {
            pCurrent  = pCurrent + cin28_cont_len;
      }
    pHeader   = pCurrent;

    /* prepare statement execution */
    i28initadbs (session);
    SENDINFO (session->segment, sp1c_with_info) = true;
    i28pcmd (session, cmd, UNDEF_SP00);

    /* execute statement */
    rc = i28sql (session, NULL);

    if (rc == cin01_db_ok) {

      pParamInfo  = i28gparaminfo(session, 0);
      nParamCount = i28paramcount(session);
      pNames      = i28colnames(session);

      if (bDesc) {
        for (i = 0; i < nParamCount; i++) {

          szDesc[0] = '\0';

          if (bOneRowResult) {
            strcat(szDesc, "SS");
          }

          for (i = 0; i < nParamCount; i++) {
            switch (pParamInfo[i].sp1i_data_type) {
              case dfixed:
              case dfloat:
              case dvfloat:
              case dsmallint:
              case dinteger:
                strcat(szDesc, "N");
                break;
              case dcha:
              case dche:
              case dchb:
              case dunicode:
              case dvarchara:
              case dvarchare:
              case dvarcharb:
              case dstra:
              case dstre:
              case dstrb:
              case dstrdb:
                strcat(szDesc, "S");
                break;
              case ddate:
              case dtime:
              case dtimestamp:
                strcat(szDesc, "D");
                break;
            case dboolean:
                strcat(szDesc, "B");
                break;
            default:
                strcat(szDesc, "-");
                break;
            }
          }
          strcat(szDesc, "\n");
          strcpy(pCurrent, szDesc);
          pCurrent += strlen(pCurrent);
        }
      }

      for (i = 0; i < nParamCount; i++) {

        nLen = *pNames;

        if (pParamInfo[i].sp1i_length > nMaxParamLen) {
          nMaxParamLen = pParamInfo[i].sp1i_length;
        }

        if (bOneRowResult) {
          if (nLen > nMaxNameLen) {
            nMaxNameLen = nLen;
          }
          pNames += (nLen + 1);
        } else {
          nMaxLen = nLen;
          if (pParamInfo[i].sp1i_length > nLen) {
            nMaxLen = pParamInfo[i].sp1i_length;
          }
          pNames++;
          memcpy(pCurrent, pNames, nLen);
          pCurrent += nLen;
          memset(pCurrent, 32, nMaxLen - nLen);
          pCurrent += (nMaxLen - nLen);
          if (i < (nParamCount - 1)) {
            strcpy(pCurrent, " | ");
          } else {
            strcpy(pCurrent, "\n\n");
          }
          pCurrent += strlen(pCurrent);
          pNames += nLen;
        }
      }

      if (bOneRowResult) {
        strcpy(pCurrent, "Name");
        pCurrent += strlen(pCurrent);
        memset(pCurrent, 32, nMaxNameLen - 4);
        pCurrent += (nMaxNameLen - 4);
        strcpy(pCurrent, " | Value");
        pCurrent += strlen(pCurrent);
        memset(pCurrent, 32, nMaxParamLen - 5);
        pCurrent += (nMaxParamLen - 5);
        strcpy(pCurrent, "\n\n");
        pCurrent += strlen(pCurrent);
      }

      if (!bOneRowResult) {
        nRowLen = strlen(pHeader) - 1;
      }

        if (bDataOnly) {
        pCurrent = pHeader;
        }

    }

    /* get first row */
    if (rc == cin01_db_ok) {
      i28_fetchcmd (session, "FETCH FIRST", nParamCount);
      SENDINFO (session->segment, sp1c_with_info) = true;
      rc =  i28sql (session, NULL);
    }

    /* analyze rows */
    if (rc == cin01_db_ok) {
      rc = i28_fetchnice(session, pResult, pCurrent, pContinue, nResultLen, bOneRowResult, nMaxNameLen, nRowLen, bDataOnly);
    }

    if (rc == cin01_db_row_not_found) {
      rc = cin01_db_ok;
    }

    return rc;
} /* end i28selectnice */

int
i28fetchnice (
    tin01_sql_session  * session,
    char               * pResult,
    long               nResultLen)
{
    /* ROUTINE_DBG_MSP00 ("i28fetchnice"); */

    int               rc          = cin01_db_ok;
    int               i           = 0;
    int               j           = 0;
    int               nParamCount = 0;
    tin01_cstr        pNames      = NULL;
    char            * pCurrent    = pResult;
    char            * pContinue   = NULL;
    char            * pHeader     = NULL;
    char              nLen        = 0;
    char              nMaxNameLen = 0;
    tsp1_param_info * pParamInfo  = NULL;
/*  char              nMaxLen     = 0;*/
    short             nMaxLen     = 0;
    int               nRowLen     = 0;

    /**/

    *pResult = 0;

    pContinue = pCurrent;
    pCurrent  = pCurrent + cin28_cont_len;
    pHeader   = pCurrent;

    pParamInfo  = i28gparaminfo(session, 0);
    nParamCount = i28paramcount(session);
    pNames      = i28colnames(session);

    for (i = 0; i < nParamCount; i++) {
      nLen = *pNames;

      nMaxLen = nLen;
      if (pParamInfo[i].sp1i_length > nLen) {
        nMaxLen = pParamInfo[i].sp1i_length;
      }
      pNames++;
      memcpy(pCurrent, pNames, nLen);
      pCurrent += nLen;
      memset(pCurrent, 32, nMaxLen - nLen);
      pCurrent += (nMaxLen - nLen);
      if (i < (nParamCount - 1)) {
        strcpy(pCurrent, " | ");
      } else {
        strcpy(pCurrent, "\n\n");
      }
      pCurrent += strlen(pCurrent);
      pNames += nLen;
    }

    nRowLen = strlen(pHeader) - 1;

    /* get next row */
    i28_fetchcmd (session, "FETCH NEXT", nParamCount);
    SENDINFO (session->segment, sp1c_with_info) = true;
    rc = i28sql (session, NULL);

    /* analyze rows */
    if (rc == cin01_db_ok) {
      rc = i28_fetchnice(session, pResult, pCurrent, pContinue, nResultLen, false, nMaxNameLen, nRowLen, false);
    }

    /**/

    return rc;
} /* end i28fetchnice */


/*----------------------------------------*/

/* puts infos about the result of the select statement
   into the result buffer
   at the moment (1998-04-20 - BV)  only the field names */
int
i28selectinfo (
    tin01_sql_session  * session,
    tin01_cstr           cmd,
    char              * pResult,
    char                cFieldSep)
{
    /* ROUTINE_DBG_MSP00 ("i28selectinfo"); */

    int               rc          = cin01_db_ok,
                      i           = 0,
                      j           = 0,
                      nParamCount = 0;
    tin01_cstr         pNames      = NULL;
    char            * pCurrent    = pResult;
    char              nLen        = 0;

    /**/

    *pResult = 0;

    /* prepare statement execution */
    i28initadbs (session);
    SENDINFO (session->segment, sp1c_with_info) = true;
    SENDINFO (session->segment, sp1c_producer) = sp1pr_internal_cmd;
    i28pcmd (session, cmd, UNDEF_SP00);

    /* execute statement */
    rc = i28sql (session, NULL);

    /* analyze result */
    if (rc == cin01_db_ok) {

      /* get some infos */
      nParamCount = i28paramcount(session);
      pNames      = i28colnames(session);

      /* get columns */
      for (i = 0; i < nParamCount; i++) {
        nLen = *pNames++;
        for (j = 0; j < nLen; j++) {
          *pCurrent++ = *pNames++;
        } /* end for */
        if (cFieldSep != 0) {
          *pCurrent++ = cFieldSep;
        } /* end if */
      } /* end for */
      /* skip last field separator */
      if (cFieldSep != 0) {
        pCurrent--;
      } /* end if */
    } /* end if */

    *pCurrent = 0;

    return rc;
} /* end i28selectinfo */

/*----------------------------------------*/

/* execute a select statement and call i28_fetchnext
   for retrieving (the first part) of the result
   (try to execute a non select statement will produce an error
   in the kernel) */
int
i28select (
    tin01_sql_session  * session,
    tin01_cstr           cmd,
    char              * pResult,
    long                nResultLen,
    char                cFieldSep,
    char                cStringDel,
    char                cRecSep)
{
    /* ROUTINE_DBG_MSP00 ("i28select"); */

    int rc = cin01_db_ok;

    /**/

    *pResult = 0;

    /* prepare statement execution */
    i28initadbs (session);
    SENDINFO (session->segment, sp1c_with_info) = true;
    SENDINFO (session->segment, sp1c_producer) = sp1pr_internal_cmd;
    i28pcmd (session, cmd, UNDEF_SP00);

    /* execute statement */
    rc = i28sql (session, NULL);

    /* get first row */
    if (rc == cin01_db_ok) {
      i28_fetchcmd (session, "FETCH FIRST", i28paramcount(session));
      SENDINFO (session->segment, sp1c_with_info) = true;
      rc =  i28sql (session, NULL);
    } /* end if */

    /* analyze rows */
    if (rc == cin01_db_ok) {
      rc = i28_fetchnext(session, pResult, nResultLen, cFieldSep, cStringDel, cRecSep);
    } /* end if */

   return rc;
} /* end i28select */

/*----------------------------------------*/

/* retrieve the next part of a result. no open select
   in the session will produce an error */
int
i28fetch (
    tin01_sql_session  * session,
    char              * pResult,
    long                nResultLen,
    char                cFieldSep,
    char                cStringDel,
    char                cRecSep)
{
    /* ROUTINE_DBG_MSP00 ("i28fetch"); */

    int rc = cin01_db_ok;

    /**/

    *pResult = 0;

    /* get next row */
    i28_fetchcmd (session, "FETCH NEXT", i28paramcount(session));
    SENDINFO (session->segment, sp1c_with_info) = true;
    rc =  i28sql (session, NULL);

    /* analyze rows */
    if (rc == cin01_db_ok) {
      rc = i28_fetchnext(session, pResult, nResultLen, cFieldSep, cStringDel, cRecSep);
    } /* end if */

    /**/

    return rc;
} /* end i28fetch */

/*----------------------------------------*/

int
i28record (
    tin01_sql_session  * session,
    tin01_cstr           cmd)
{
  /* ROUTINE_DBG_MSP00 ("i28record"); */

  int rc = cin01_db_ok;

  /**/

  /* prepare statement execution */
  i28initadbs (session);
  SENDINFO (session->segment, sp1c_with_info) = true;
  SENDINFO (session->segment, sp1c_producer) = sp1pr_internal_cmd;
  i28pcmd (session, cmd, UNDEF_SP00);

  /* execute statement */
  rc = i28sql (session, NULL);

  /* get first row */
  if (rc == cin01_db_ok) {
    i28_fetchcmd (session, "FETCH FIRST", i28paramcount(session));
    SENDINFO (session->segment, sp1c_with_info) = true;
    rc =  i28sql (session, NULL);
  } /* end if */

  /**/

  return rc;
} /* end i28record */

/*----------------------------------------*/

int
i28nextrecord (
    tin01_sql_session  * session)
{
  /* ROUTINE_DBG_MSP00 ("i28nextrecord"); */

  int rc = cin01_db_ok;

  /**/

  /* get next row */
  i28_fetchcmd (session, "FETCH NEXT", i28paramcount(session));
  SENDINFO (session->segment, sp1c_with_info) = true;
  rc =  i28sql (session, NULL);

  /**/

  return rc;
} /* end i28nextrecord */

/*----------------------------------------*/

int
i28fieldvalue (
    tin01_sql_session  * session,
    const tsp00_Int4     nField,
    tin01_c_hostvar    * pHostvar,
    const char           cStringQuote)

{
  /* ROUTINE_DBG_MSP00 ("i28fieldvalue"); */

  int               rc          = cin01_db_ok;
  tsp1_param_info * pParamInfo  = NULL;
  int               nParamCount = 0;
  char            * pChar       = (char *) pHostvar->addr;
  /**/

  pParamInfo  = i28gparaminfo(session, 0);
  nParamCount = i28paramcount(session);

  if (nParamCount >= nField) {
    memcpy(&(pHostvar->pinfo), &pParamInfo[nField - 1], sizeof(tsp1_param_info));
    i28findpart (session, sp1pk_data);

    /* handle strings*/
    if (i28_isstring(pHostvar->pinfo.sp1i_data_type) && cStringQuote != 0) {
      *pChar = cStringQuote;
      ++pChar;
      pHostvar->addr = pChar;
    } /* end if*/

    /* read value */
    rc = i28_outarg (session, pHostvar);

    /* handle strings*/
    if (i28_isstring(pHostvar->pinfo.sp1i_data_type) && cStringQuote != 0) {
      if (rc == cin01_db_ok) {
        pChar[strlen(pChar)    ] = cStringQuote;
        pChar[strlen(pChar) + 1] = 0;
      } /* end if*/

      --pChar;
      pHostvar->addr = pChar;
    } /* end if*/
  } else {
    rc = cin01_db_invalid_number;
  } /* end if*/

  /**/

  return rc;
} /* end i28fieldvalue */

/*----------------------------------------*/

/**\
--- ----------------------------------MF__ MOD__ chapter special cases
    The following routines serve very specific needs.
    They are included so that clients don't need the
    internal structure of segments and parts
\**/

char           *
i28outargsbuf (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28outargsbuf"); */
    i28findpart (session, sp1pk_data);
    return PARTDATA (session->part);
}

/*----------------------------------------*/

char           *
i28argsbuf (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28argsbuf"); */
    return PARTDATA (session->part);
}

/*----------------------------------------*/

void
i28argsbuflen (
    tin01_sql_session * session,
    int buflen)
{
    /* ROUTINE_DBG_MSP00 ("i28argsbuflen"); */
    PARTINFO (session->part, sp1p_buf_len) = buflen;
}

/*----------------------------------------*/

tsp00_Int4
i28packetlen (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28packetlen"); */
    return s26packet_len (session->send_packet);
}

/*----------------------------------------*/

static void
i28_puttermid (
    tin01_sql_session * session,
    tsp00_TermId termid)
{
    /* ROUTINE_DBG_MSP00 ("i28_puttermid"); */
    char           *target;
    tsp1_packet    *packet = session->send_packet;

    target = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    *target = csp_defined_byte;
    ++target;
    memcpy (target, termid, sizeof (tsp00_TermId));
    PARTINFO (session->part, sp1p_buf_len) += 1 + sizeof (tsp00_TermId);
}

/*----------------------------------------*/

static void
i28_connectOptions (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28_sqlmode"); */
    if (isalpha (session->xuser.xu_sqlmode[0]) != '\0') {
        i28pcmdf (session, " SQLMODE %.*s",
            sizeof (session->xuser.xu_sqlmode), (char *) session->xuser.xu_sqlmode);
    }
    if (session->xuser.xu_cachelimit != -1) {
        i28pcmdf (session, " CACHELIMIT %d ", session->xuser.xu_cachelimit);
    }
    if (session->xuser.xu_timeout != -1) {
        i28pcmdf (session, " TIMEOUT %d ", session->xuser.xu_timeout);
    }
    if (session->xuser.xu_isolation != -1) {
        i28pcmdf (session, " ISOLATION LEVEL %d ", session->xuser.xu_isolation);
    }
    if (session->space_option) {
        i28pcmd (session, " SPACE OPTION", -1);
    }
}

/*----------------------------------------*/

void
i28connectcommand (
    tin01_sql_session * session,
    tsp00_TermId termid)
{
    /* ROUTINE_DBG_MSP00 ("i28connectcommand"); */
    session->buildingCommand = false;
    i28initadbs (session);
    SENDINFO (session->segment, sp1c_producer) = sp1pr_internal_cmd;
    i28pcmdf (session, "CONNECT \"%.*s\" IDENTIFIED by :PW",
        sizeof (session->xuser.xu_user), (char *) session->xuser.xu_user);
    i28_connectOptions (session);
    i28newpart (session, sp1pk_data);
    i28ppw (session, session->xuser.xu_password, csp_defined_byte);
    i28_puttermid (session, termid);
}

/*----------------------------------------*/

void
i28tablebuffer (
    tin01_sql_session * session,
    char **tablebuffer,
    tsp00_Int4 * buflen)
{
    /* ROUTINE_DBG_MSP00 ("i28tablebuffer"); */
    tsp1_packet    *rec_packet = session->rec_packet;

    tin01_bool           partFound;

    ASSERT_DBG (rec_packet != NULL);
    partFound = i28findpart (session, sp1pk_conv_tables_returned);
    ASSERT_DBG (partFound);
    *tablebuffer = PARTDATA (session->part);
    *buflen = PARTINFO (session->part, sp1p_buf_len);
}

/*----------------------------------------*/

char           *
i28cmdbuf (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28cmdbuf"); */
    return PARTDATA (session->part);
}

/*----------------------------------------*/

char           *
i28getpart (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28getpart"); */
    return PARTDATA (session->part);
}

/*----------------------------------------*/

void
i28extendpart (
    tin01_sql_session * session,
    int lendiff)
{
    /* ROUTINE_DBG_MSP00 ("i28extendpart"); */
    PARTINFO (session->part, sp1p_buf_len) += lendiff;
}

/*----------------------------------------*/

tsp00_Int4
i28partlen (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28partlen"); */
    return PARTINFO (session->part, sp1p_buf_len);
}

/*----------------------------------------*/

tsp00_Int4
i28bytesfree (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28bytesfree"); */
    return PARTINFO (session->part, sp1p_buf_size)
        - PARTINFO (session->part, sp1p_buf_len) - 4;
}

/*----------------------------------------*/

void
i28addpartdata (
    tin01_sql_session * session,
    const void *data,
    int len)
{
    /* ROUTINE_DBG_MSP00 ("i28addpartdata"); */
    memcpy (PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len),
        data, len);
    PARTINFO (session->part, sp1p_buf_len) += len;
    ASSERT_DBG (PARTINFO (session->part, sp1p_buf_len)
        <= PARTINFO (session->part, sp1p_buf_size));
}

/*----------------------------------------*/

tsp1_param_info *
i28allocparaminfos (
    tin01_sql_session * session,
    int paramCount)
{
    /* ROUTINE_DBG_MSP00 ("i28allocparaminfos"); */
    i28_reset (session, true);
    i28newsegment (session, sp1m_parse);
    i28newpart (session, sp1pk_shortinfo);
    PARTINFO (session->part, sp1p_arg_count) = (tsp00_Int2) paramCount;
    PARTINFO (session->part, sp1p_buf_len) = paramCount * sizeof (tsp1_param_info);
    return (tsp1_param_info *) PARTDATA (session->part);
}

/*----------------------------------------*/

void
i28newnamepart (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28newnamepart"); */
    i28newpart (session, sp1pk_columnnames);
    PARTINFO (session->part, sp1p_arg_count) = 0;
}

/*----------------------------------------*/

void
i28addname (
    tin01_sql_session * session,
    tin01_cstr name)
{
    /* ROUTINE_DBG_MSP00 ("i28addname"); */
    int             namelen;
    char           *buf;

    ASSERT_DBG (PARTINFO (session->part, sp1p_part_kind) == sp1pk_columnnames);
    namelen = strlen (name); /* physical, not logical */
    buf = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    buf[0] = (char) namelen;
    memcpy (buf + 1, name, namelen);
    PARTINFO (session->part, sp1p_buf_len) += namelen + 1;
    ++PARTINFO (session->part, sp1p_arg_count);
}

/*----------------------------------------*/

tin01_bool
i28hello (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28hello"); */
    i28_reset (session, true);
    i28newsegment (session, sp1m_hello);
    i28sql (session, NULL);
    return session->is_connected;
}

/*----------------------------------------*/

#define c_intostr " Into ?"
#define c_intolen 7
#define c_varstr ", ?"
#define c_varlen 3

static void
i28_fetchcmd (
    tin01_sql_session * session,
    tin01_cstr fetchCmd,
    int fetchVars)
{
    /* ROUTINE_DBG_MSP00 ("i28_fetchcmd"); */
    char           *cmdBuf;
    int             fetchLen;
    int             additional;

    i28initadbs (session);
    fetchLen = strlen (fetchCmd);
    cmdBuf = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    memcpy (cmdBuf, fetchCmd, fetchLen);
    cmdBuf += fetchLen;
    memcpy (cmdBuf, c_intostr, c_intolen);
    --fetchVars;
    cmdBuf += c_intolen;
    additional = fetchLen + c_intolen + (fetchVars * c_varlen);
    while (fetchVars > 0) {
        memcpy (cmdBuf, c_varstr, c_varlen);
        cmdBuf += c_varlen;
        --fetchVars;
    }
    PARTINFO (session->part, sp1p_buf_len) += additional;
}

/*----------------------------------------*/

int
i28fetchcmd (
    tin01_sql_session * session,
    tin01_cstr fetchCmd,
    int fetchVars)
{
    /* ROUTINE_DBG_MSP00 ("i28fetchcmd"); */
    i28_fetchcmd (session, fetchCmd, fetchVars);
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28mfetchcmd (
    tin01_sql_session * session,
    tin01_cstr fetchCmd,
    int fetchVars,
    int rowsToFetch)
{
    /* ROUTINE_DBG_MSP00 ("i28mfetchcmd"); */
    tsp00_Number      num;
    tsp00_NumError   res;
    int             rc = cin01_db_ok;

    i28_fetchcmd (session, fetchCmd, fetchVars);
    i28newpart (session, sp1pk_resultcount);
    s41plint (&num, 1, 18, 0, rowsToFetch, &res);
    rc = i28parg (session, (char *) num, sizeof (num), sizeof (num) + 1,
        1, csp_defined_byte);
    if (rc != cin01_db_ok)
        return rc;
    SENDINFO (session->segment, sp1c_mass_cmd) = true;
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28functioncode (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28functioncode"); */
    return RECINFO (session->segment, sp1r_function_code);
}

/*----------------------------------------*/

tin01_bool
i28gresulttablename (
    tin01_sql_session * session,
    int              * len,
    char             * resulttablename)
{
    /* ROUTINE_DBG_MSP00 ("i28gresulttablename"); */
    int                r_len = 0;

    if (i28findpart (session, sp1pk_resulttablename)) {
        r_len = PARTINFO (session->part, sp1p_buf_len);
        if (r_len > 0) {
            memcpy (resulttablename, PARTDATA (session->part), r_len);
        }
    }
    *len = r_len;
    return (r_len > 0);
} /* i28gresulttablename */

/*----------------------------------------*/

void
i28sresulttablename (
    tin01_sql_session * session,
    int                len,
    char             * resulttablename)
{
    /* ROUTINE_DBG_MSP00 ("i28sresulttablename"); */

    i28newpart (session, sp1pk_resulttablename);
    memcpy (PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len),
        resulttablename, len );
    PARTINFO (session->part, sp1p_buf_len) += len;
} /* i28sresulttablename */

/*----------------------------------------*/

tin01_bool
i28forreuse (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28forreuse"); */
    tin01_parseid       pid;

    if (!i28findpart (session, sp1pk_parsid))
        return false;
    MEMCPY_MIN01 (pid, PARTDATA (session->part));
    return ((pid [10] == csp1_p_reuse_mass_select_found)
         || (pid [10] == csp1_p_reuse_update_sel_found)
         || (pid [10] == csp1_p_reuse_mselect_found)
         || (pid [10] == csp1_p_reuse_upd_mselect_found)
           );
} /* i28forreuse */

/*----------------------------------------*/

tin01_bool
i28forupdate (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28forupdate"); */
    tin01_parseid pid;
    if (!i28findpart (session, sp1pk_parsid))
        return false;
    MEMCPY_MIN01 (pid, PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len));
    return ((pid [10] == csp1_p_select_for_update_found)
         || (pid [10] == csp1_p_for_upd_mselect_found)
         || (pid [10] == csp1_p_reuse_update_sel_found)
         || (pid [10] == csp1_p_reuse_upd_mselect_found)
           );
} /* i28forupdate */

/*----------------------------------------*/

int
i28rowsfetched (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28rowsfetched"); */
    i28findpart (session, sp1pk_data);
    return PARTINFO (session->part, sp1p_arg_count);
}

/*----------------------------------------*/

int
i28rowlen (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28rowlen"); */
    int             result;
    int             recordCount;

    i28findpart (session, sp1pk_data);
    recordCount = PARTINFO (session->part, sp1p_arg_count);
    result = PARTINFO (session->part, sp1p_buf_len) / recordCount;
    return result;
}

/*----------------------------------------*/

tin01_bool
i28endoffetch (
    tin01_sql_session * session,
    int rowsExpected)
{
    /* ROUTINE_DBG_MSP00 ("i28endoffetch"); */
    int             endOfFetch;
    int             recordCount;
    int             recordLen;
    int             bytesRemaining;

    switch (RECINFO (session->segment, sp1r_returncode)) {
        case cin01_db_row_not_found:
            endOfFetch = true;
            break;
        case cin01_db_ok:
            i28findpart (session, sp1pk_data);
            recordCount = PARTINFO (session->part, sp1p_arg_count);
            if (recordCount == rowsExpected)
                endOfFetch = false;
            else {
                recordLen = PARTINFO (session->part, sp1p_buf_len) / recordCount;
                bytesRemaining = PARTINFO (session->part, sp1p_buf_size)
                    - PARTINFO (session->part, sp1p_buf_len);
                if (bytesRemaining >= recordLen)
                    endOfFetch = true;
                else
                    endOfFetch = false;
            }
            break;
        default:
            return true;
            break;
    }
    return endOfFetch;
}

/*----------------------------------------*/
/**\
--- ----------------------------------MF__ MOD__ chapter utility
\**/
void
i28initutility (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28initutility"); */
    i28_reset (session, true);
    i28newsegment (session, sp1m_utility);
    i28newpart (session, sp1pk_command);
}

/*----------------------------------------*/

void
i28initdiagoutcopy (
    tin01_sql_session * session)
{
    ROUTINE_DBG_MEO00 ("i28initdiagoutcopy");
    i28_reset (session, true);
    i28newsegment (session, sp1m_diag_outcopy);
    i28newpart (session, sp1pk_command);
} /* end i28initdiagoutcopy */

/*----------------------------------------*/

int
i28utility (
    tin01_sql_session * session,
    tin01_cstr cmd)
{
    /* ROUTINE_DBG_MSP00 ("i28utility"); */
    i28initutility (session);
    i28pcmd (session, cmd, UNDEF_SP00);
    return i28sql (session, NULL);
}

/*----------------------------------------*/

int
i28utilcmd (
    tin01_sql_session * session,
    tin01_c_sqlca * sqlca,
    tin01_cstr cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28utilcmd"); */
    va_list         args;
    int             i;
    int             rc;
    int             paramCount;

    /* execute command */
    rc = i28utility (session, cmd);
    if (rc == cin01_db_ok) {
        /* get c variables addresses */
        va_start (args, cmd);
        for (i = 0; i < sqlca->varCount; ++i) {
            sqlca->hostVar[i].addr = va_arg (args, void *);
        }
        va_end (args);
        /* get sql parameter info */
        paramCount = i28paramcount (session);
        if (paramCount > sqlca->varCount)
            paramCount = sqlca->varCount;
/*            rc = -1200; */         /* too few values */
/*        else { */
            sqlca->paramCount = paramCount;
            if (paramCount > 0) {
                tsp1_param_info *pinfo = i28gparaminfo (session, 0);
                int              i;

                for (i = 0; i < paramCount; ++i, ++pinfo) {
                    memcpy (&sqlca->hostVar [i].pinfo, pinfo,
                            sizeof (tsp1_param_info));
                }
            }
            sqlca->inUse = true;
/*        } */
        /* get sql parameters into c variables */
        if (rc == 0) {
            rc = i28_outargs (session, sqlca);
        }
    }
    return rc;
}

/*----------------------------------------*/
int
i28utilbackuprequest (
    tin01_sql_session  * session,
    boolean              bBackupState,
    tin01_cstr           cmd)
{
    /* ROUTINE_DBG_MSP00 ("i28utilbackuprequest"); */

    if (!bBackupState) {
        i28initutility (session);
    } else {
        i28initadbs (session);
    } /* end if */
    i28pcmd (session, cmd, UNDEF_SP00);
    return i28sqlrequest(session);
} /* end i28utilbackuprequest */

/*----------------------------------------*/
int
i28utilbackupreceive (
    tin01_sql_session  * session,
    tin01_c_sqlca      * sqlca,
    boolean            * bBackupRC,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28utilbackupreceive"); */
    va_list         args;
    int             i;
    int             rc;
    int             paramCount;
    int             nBackupRC;

    rc = i28sqlreceive(session);

    switch (rc) {
      case -7075:                       /* current save skipped           */
      case -7076:                       /* no more data to read from tape */
      case -8020:                       /* next volumn required           */
        *bBackupRC = true;
        break;
      default:
        *bBackupRC = false;
        break;
    }

    if (*bBackupRC) {
      nBackupRC = rc;
    } else {
      nBackupRC = 0;
    }

    if ( (rc == cin01_db_ok)   ||
         (*bBackupRC)    ) {
        /* get c variables addresses */
        va_start (args, bBackupRC);
        for (i = 0; i < sqlca->varCount; ++i) {
            sqlca->hostVar[i].addr = va_arg (args, void *);
        }
        va_end (args);
        /* get sql parameter info */
        paramCount = i28paramcount (session);
        if (paramCount > sqlca->varCount)
            paramCount =  sqlca->varCount;
/*            rc = -1200; */        /* too few values */
/*        else { */
             sqlca->paramCount = paramCount;
            if (paramCount > 0) {
                tsp1_param_info *pinfo = i28gparaminfo (session, 0);
                int              i;

                for (i = 0; i < paramCount; ++i, ++pinfo) {
                    memcpy (&sqlca->hostVar [i].pinfo, pinfo,
                            sizeof (tsp1_param_info));
                }
            }
            sqlca->inUse = true;
        }
        /* get sql parameters into c variables */
        if ( (rc == 0)            ||
             (*bBackupRC)    ){
            rc = i28_outargs (session, sqlca);
        }
/*    } */

    if ( (rc == 0) && (*bBackupRC)) {
      rc = nBackupRC;
    }

  return rc;
} /* end i28utilbackupreceive */

/*----------------------------------------*/

int
i28utilbackupcmd (
    tin01_sql_session  * session,
    tin01_c_sqlca      * sqlca,
    boolean           * bBackupRC,
    boolean           bBackupState,
    tin01_cstr         cmd,
    ...)
{
    /* ROUTINE_DBG_MSP00 ("i28utilbackupcmd"); */
    va_list         args;
    int             i;
    int             rc;
    int             paramCount;
    int             nBackupRC;

    /* execute command */
    if (!bBackupState) {
      rc = i28utility (session, cmd);
    } else {
      rc = i28adbs (session, cmd);
    }

    switch (rc) {
      case -7075:                       /* current save skipped           */
      case -7076:                       /* no more data to read from tape */
      case -8020:                       /* next volumn required           */
        *bBackupRC = true;
        break;
      default:
        *bBackupRC = false;
        break;
    }

    if (*bBackupRC) {
      nBackupRC = rc;
    } else {
      nBackupRC = 0;
    }

    if ( (rc == cin01_db_ok)   ||
         (*bBackupRC)    ) {
        /* get c variables addresses */
        va_start (args, cmd);
        for (i = 0; i < sqlca->varCount; ++i) {
            sqlca->hostVar[i].addr = va_arg (args, void *);
        }
        va_end (args);
        /* get sql parameter info */
        paramCount = i28paramcount (session);
        if (paramCount > sqlca->varCount)
            paramCount = sqlca->varCount;
/*            rc = -1200; */        /* too few values */
/*        else { */
            sqlca->paramCount = paramCount;
            if (paramCount > 0) {
                tsp1_param_info *pinfo = i28gparaminfo (session, 0);
                int              i;

                for (i = 0; i < paramCount; ++i, ++pinfo) {
                    memcpy (&sqlca->hostVar [i].pinfo, pinfo,
                            sizeof (tsp1_param_info));
                }
            }
            sqlca->inUse = true;
/*        } */
        /* get sql parameters into c variables */
        if ( (rc == 0)            ||
             (*bBackupRC)    ){
            rc = i28_outargs (session, sqlca);
        }
    }

    if ( (rc == 0)            &&
         (*bBackupRC)    ) {
      return nBackupRC;
    } else {
      return rc;
    }
} /* end i28utilbackupcmd*/

/*----------------------------------------*/

int i28utildiagtocmd
    ( tin01_sql_session  * session,
    tin01_cstr           cmd,
    long               * nPageSize,
    void              ** pPageBuf)
{
    /* ROUTINE_DBG_MEO00 ("i28utildiagtocmd"); */

    int             rc;

    /* init out params */
    *nPageSize = 0;
    *pPageBuf  = NULL;

    /* execute command */
    rc = i28utility (session, cmd);

    if (rc == cin01_db_ok) {
        /* if there no page part get the page(s) with a diag_outcopy message */
        if (i28findpart (session, sp1pk_data) && !i28findpart (session, sp1pk_page)) {
            i28initdiagoutcopy (session);
            rc = i28sql (session, NULL);
        } /* end if */
        if (rc == cin01_db_ok) {
            /* page part */
            if (i28findpart (session, sp1pk_page)) {
                /* get page */
                *nPageSize = PARTINFO (session->part, sp1p_buf_len);
                *pPageBuf  = (void *) PARTDATA (session->part);
            } /* end if */
        } /* end if */

    } /* end if */

    return rc;

} /* end i28utildiagtocmd  */

/*----------------------------------------*/

int i28utildiagrestcmd
      ( tin01_sql_session  * session,
        tin01_cstr           cmd,
        long                 nPageSize,
        const void         * pPageBuf)
{
    ROUTINE_DBG_MEO00 ("i28utildiagrestcmd");

  /* init segment and commad part*/
  i28initutility (session);
  i28pcmd (session, cmd, UNDEF_SP00);

  /* init pagepart and commad part*/
  i28newpart (session, sp1pk_page);
  i28findpart (session, sp1pk_page);
  PARTINFO (session->part, sp1p_buf_len) = nPageSize;
  memcpy(PARTDATA (session->part), pPageBuf, nPageSize);

  return i28sql (session, NULL);

} /* end i28utildiagrestcmd  */

/*----------------------------------------*/
/**\
--- ----------------------------------MF__ MOD__ chapter communication
\**/
void
i28pascalstring (
    char       *target,
    int         targetlen,
    const char *source,
    int         sourcelen)
{
    /* ROUTINE_DBG_MSP00 ("i28pascalstring"); */
    if (source == NULL) {
        /* one blank so memcpy is ok */
        source = " ";
        sourcelen = 1;
    }
    else {
        if (sourcelen == -1)
            sourcelen = strlen (source);
    }
    if (sourcelen > targetlen)
        memcpy (target, source, (int) targetlen);
    else {
        memcpy (target, source, (int) sourcelen);
        memset (target + sourcelen, ' ', (int) (targetlen - sourcelen));
    }
}

/*----------------------------------------*/

tin01_sql_session *
i28lasterr_off (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28lasterr_off"); */
    session->lasterr.lasterr_on = false;
    return session;
} /* i28lasterr_off */

/*----------------------------------------*/

tin01_sql_session *
i28lasterr_on (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28lasterr_on"); */
    session->lasterr.lasterr_on = true;
    return session;
} /* i28lasterr_on */

/*----------------------------------------*/

void
i28setlasterr_rte (
    tin01_sql_session * session,
    tsp00_ErrText     errtext,
    tsp01_CommErr sp_rc)
{
    /* ROUTINE_DBG_MSP00 ("i28setlasterr_rte"); */
    ASSERT_DBG (session != NULL);
    if (!session->lasterr.lasterr_on)
        return;
    session->lasterr.sp_rc = sp_rc;
    if (sp_rc == commErrOk_esp01)
        return;
    MEMCPY_MIN01 (session->lasterr.errtext, errtext);
    memset (session->lasterr.errname, ' ',
            sizeof (session->lasterr.errname));
}

/*----------------------------------------*/

void
i28resetlasterr (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28resetlasterr"); */
    ASSERT_DBG (session != NULL);
    session->lasterr.sqlresult.returnCode = cin01_db_ok;
    session->lasterr.sqlresult.errorPos = 0;
    memset (session->lasterr.sqlresult.sqlmsg, ' ',
            sizeof (session->lasterr.sqlresult.sqlmsg));
    memset (session->lasterr.errname, ' ',
            sizeof (session->lasterr.errname));
}

/*----------------------------------------*/

void
i28whenever_errpos (
    tin01_sql_session    *session,
    int                 whenever_pos)
{
    /* ROUTINE_DBG_MSP00 ("i28whenever_errpos"); */
    tin01_sqlresult  *sqlresult;
    if (whenever_pos == UNDEF_SP00)
        return;
    sqlresult = &session->lasterr.sqlresult;
    if (sqlresult->errorPos >= whenever_pos)  {
        sqlresult->errorPos = -(sqlresult->errorPos - whenever_pos);
    }
}

/*----------------------------------------*/
int
i28replyavailable (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28replyavailable"); */
    tsp00_ErrText     errtext;
    tsp01_CommErr  sp_rc;

    sqlareplyavailable (session->reference, errtext, &sp_rc);

    i28setlasterr_rte (session, errtext, sp_rc) ;
    return sp_rc;
} /* end i28replyavailable */

/*----------------------------------------*/
void
i28cancel (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28cancel"); */
    sqlacancel(session->reference);

} /* end i28cancel */

/*----------------------------------------*/

tsp01_CommErr
i28request (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28request"); */
    tsp00_ErrText     errtext;
    tsp01_CommErr  sp_rc;

    ASSERT_DBG (session->is_connected);
    sqlarequest (session->reference, session->send_packet,
        i28packetlen (session), errtext, &sp_rc);
    if ((sp_rc == commErrTimeout_esp01) || (sp_rc == commErrCrash_esp01)) {
        i28cleanup_session (session);
        /*
        sqlarelease (session->reference);
        session->is_connected = false;
        */
    }
    if (sp_rc != commErrOk_esp01) {
        TRACEF_MIN01 (5, (SQLTRACE, "Request error: %40.40s\n",
                errtext));
        if (sp_rc == commErrTimeout_esp01)
            i28connect (session);
    }
    i28setlasterr_rte (session, errtext, sp_rc) ;
    return sp_rc;
}

/*----------------------------------------*/

tsp01_CommErr
i28receive (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28receive"); */
    tsp00_Int4        length;
    tsp00_ErrText     errtext;
    tsp01_CommErr  sp_rc;

    ASSERT_DBG (session->is_connected);
    sqlareceive (session->reference, (void**)&session->rec_packet,
        &length, errtext, &sp_rc);
    if ((sp_rc == commErrTimeout_esp01) || (sp_rc == commErrCrash_esp01)) {
        sqlarelease (session->reference);
        session->is_connected = false;
    }
    if (sp_rc != commErrOk_esp01) {
        TRACEF_MIN01 (5, (SQLTRACE, "Receive error: %40.40s\n",
                errtext));
        session->rec_packet = NULL;
    }
    i28setlasterr_rte (session, errtext, sp_rc) ;
    return sp_rc;
}

/*----------------------------------------*/

void
i28callsql (
    tin01_sql_session * session,
    tsp01_CommErr * comm_error)
{
    /* ROUTINE_DBG_MSP00 ("i28callsql"); */
    *comm_error = i28request (session);
    if (*comm_error == commErrOk_esp01)
        *comm_error = i28receive (session);
    i28lasterr_on (session);
}

/*----------------------------------------*/

void
i28setlasterr_name (
    tin01_sql_session    * session,
    tsp00_KnlIdentifier  * errname)
{
    /* ROUTINE_DBG_MSP00 ("i28setlasterr_name"); */
    ASSERT_DBG (session != NULL);
    MEMCPY_MIN01 (session->lasterr.errname, errname);
}

/*----------------------------------------*/

void
i28sqllasterr (
    tin01_sql_session     * session,
    tsp00_ErrTextc        * errtext,
    tsp00_KnlIdentifierc  * errname,
    tsp00_Int2            * errcode,
    tsp00_Int2            * errpos)
{
    /* ROUTINE_DBG_MSP00 ("i28sqllasterr"); */
    #define RTEERR_OFFSET   10000
    * errpos = 0;
    *errcode = 0;
    memset(errtext, 0, sizeof(tsp00_ErrTextc));
    memset(errname, 0, sizeof(tsp00_KnlIdentifierc));
    if (session->lasterr.sp_rc != commErrOk_esp01) {
        memcpy (errtext, session->lasterr.errtext, sizeof (tsp00_ErrText));
        memcpy (errname, session->lasterr.errname, sizeof (tsp00_KnlIdentifier));
        *errcode = (tsp00_Int2) (session->lasterr.sp_rc + RTEERR_OFFSET);
        session->lasterr.sp_rc = commErrOk_esp01;
    }
    else if (session->lasterr.sqlresult.returnCode != cin01_db_ok) {
        *errcode = session->lasterr.sqlresult.returnCode;
        *errpos = session->lasterr.sqlresult.errorPos;
        memcpy (errtext, session->lasterr.sqlresult.sqlmsg, sizeof (tsp00_ErrText));
        memcpy (errname, session->lasterr.errname, sizeof (tsp00_KnlIdentifier));
        session->lasterr.sqlresult.returnCode = cin01_db_ok;
    }
    else {
        *errcode = 0;
        memset (errtext, ' ', sizeof (tsp00_ErrText));
        memset (errname, ' ', sizeof (tsp00_KnlIdentifier));
    }
}

/*----------------------------------------*/

int
i28sqlconnect (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28sqlconnect"); */

    tsp00_TaskId      aid;
    tsp4_xuser_record   *xuser;
    int                 connect_rc;
    tsp00_Int4          packetSize;
    tsp00_ErrText       errtext;
    tsp01_CommErr       sp_rc;
    tsp01_Service       connectKind;
    void               *packetList[1];

    sqluid (&aid);
    xuser = &session->xuser;
    if (session->as_utility) {
        connectKind = srvUtility_esp01;
    }
    else {
        connectKind = srvUser_esp01;
    }
    sqlaconnect (aid, xuser->xu_servernode, xuser->xu_serverdb,
        connectKind, 1, &session->reference, &packetSize,
        packetList, errtext, &sp_rc);
    if (sp_rc != commErrOk_esp01) {
        TRACEF_MIN01 (5, (SQLTRACE, "Connect error: %40.40s\n",
                errtext));
       i28setlasterr_rte (session, errtext, sp_rc) ;
    }
    else {
        tsp00_TermId      termid;

        ASSERT_DBG (!session->is_connected);
        session->send_packet = (tsp1_packet_ptr ) packetList [0];
        session->send_packet->sp1_header.sp1h_varpart_size =
            packetSize - sizeof (tsp1_packet_header);
        session->is_connected = true;
        sqltermid (termid);
        i28connectcommand (session, termid);
        connect_rc = i28sql (session, NULL);
        if (connect_rc != cin01_db_ok) {
            sqlarelease (session->reference);
            session->is_connected = false;
            TRACEF_MIN01 (5, (SQLTRACE, "Connect command failed with %d\n",
                (int) connect_rc));
        }
        return connect_rc;
    }
    return commErrNotOk_esp01;
}

/*----------------------------------------*/

int
i28_connect (
    tin01_sql_session * session,
    tsp01_Service       connectKind)
{
    /* ROUTINE_DBG_MSP00 ("i28_connect"); */

    tsp00_TaskId      aid;
    tsp4_xuser_record   *xuser;
    tsp00_Int4          packetSize;
    tsp00_ErrText       errtext;
    tsp01_CommErr       sp_rc;
    void              *packetList [1];

    sqluid (&aid);
    xuser = &session->xuser;

    sqlaconnect (aid, xuser->xu_servernode, xuser->xu_serverdb,
        connectKind, 1, &session->reference, &packetSize,
        packetList, errtext, &sp_rc);

    if (sp_rc != commErrOk_esp01) {

      TRACEF_MIN01 (5, (SQLTRACE, "Connect error: %40.40s\n", errtext));
      i28setlasterr_rte (session, errtext, sp_rc) ;

    } else {

      ASSERT_DBG (!session->is_connected);
      session->send_packet = (tsp1_packet_ptr ) packetList [0];
      session->send_packet->sp1_header.sp1h_varpart_size = packetSize - sizeof (tsp1_packet_header);
      session->is_connected = true;

    }
    return sp_rc;
} /* end i28_connect */

/*----------------------------------------*/

int
i28specialconnect (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28specialconnect"); */

    tsp01_Service       connectKind;

    connectKind = srvUser_esp01;

    return i28_connect( session, connectKind);
} /* end i28specialconnect */

/*----------------------------------------*/

int
i28eventconnect (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28eventconnect"); */

    tsp01_Service       connectKind;

    connectKind = srvEvent_esp01;

    return i28_connect( session, connectKind);
} /* end i28eventconnect */

/*----------------------------------------*/

int
i28eventwait (
    tin01_sql_session       * session,
    tsp31_event_description * event)
{
  /* ROUTINE_DBG_MSP00 ("i28eventwait"); */

  int rc;

  /* packet initialisieren*/
  i28initspecial(session, sp1m_wait_for_event);

  /* request absetzen und ins receive gehen*/
  rc = i28sql (session, NULL);

  /* struktur auswerten*/
  if (rc == cin01_db_ok) {
    if (i28findpart (session, sp1pk_data)) {
      memcpy(event, PARTDATA (session->part) + 1, sizeof(tsp31_event_description));

    } /* end if*/
  } /* end if*/

  return rc;
} /* end i28eventwait */

/*----------------------------------------*/

int
i28connect (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28connect"); */
    return i28sqlconnect ( session );
}

/*----------------------------------------*/

void
i28cleanup_session (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28cleanup_session"); */
    sqlarelease (session->reference);
    session->is_connected = false;
    i28clearpacketref (session);
}

/*----------------------------------------*/

void
i28release (
    tin01_sql_session * session,
    tin01_bool with_commit)
{
    /* ROUTINE_DBG_MSP00 ("i28release"); */
    int oldMode;

    oldMode = i28adabasmode (session);
    IFDEBUG_MIN01 (i28lasterr_off (session));
    IFDEBUG_MIN01 (i28adbs_noinfo (session, "VTRACE", false));
    i28oldmode (session, oldMode);
    i28lasterr_off (session);
    if (with_commit)
        i28adbs_noinfo (session, "COMMIT WORK RELEASE", false);
    else
        i28adbs_noinfo (session, "ROLLBACK WORK RELEASE", false);
    i28cleanup_session (session);
}

/*----------------------------------------*/

void
i28specialrelease (
    tin01_sql_session * session)
{
    /* ROUTINE_DBG_MSP00 ("i28specialrelease"); */

    i28cleanup_session(session);
}

/*----------------------------------------*/

void
i28getFreePartInfo (
    tin01_sql_session * session,
    void ** dataPtr,
    int   * bufPos,
    int   * freeLen)
{
    /* ROUTINE_DBG_MSP00 ("i28getFreePartInfo"); */
    *dataPtr = PARTDATA (session->part) + PARTINFO (session->part, sp1p_buf_len);
    *bufPos = PARTINFO (session->part, sp1p_buf_len) + 1 /* is pascal index */;
    *freeLen = i28bytesfree (session);
}

/*----------------------------------------*/

static int
i28_handleCommError (
    tin01_sql_session * session,
    tin01_sqlresult * sqlresult,
    tsp01_CommErr  comm_error)
{
    /* ROUTINE_DBG_MSP00 ("i28_handleCommError"); */
    int result = cin01_db_ok;

    if ((int) comm_error != commErrOk_esp01) {
        result = cin01_db_not_accessible;
        /* session->is_connected = false; lower level routines try reconnect */
        if (sqlresult != NULL) {
            sqlresult->returnCode = result;
            M_WARNINGSET (sqlresult->warnings) = EMPTYSET_MIN01;
            sqlresult->errorPos = 0;
            sqlresult->rowCount = 0;
            MEMCPY_MIN01 (sqlresult->sqlstate, "I8888");
            sqlresult->sqlmsg[0] = '\0';
        }
    }
    return result;
}

/*----------------------------------------*/

static int
i28_handleSQLError (
    tin01_sql_session * session,
    tin01_sqlresult * sqlresult)
{
    /* ROUTINE_DBG_MSP00 ("i28_handleSQLError"); */
    int             result;
    tsp1_segment   *segment;
    int             msglen;

    i28resetpackets (session, false);
    IFTRACE_MIN01 (4, j96dumppacket (session, "RECEIVE", SQLTRACE));
    segment = i28_lastsegment (session->rec_packet);
    result = RECINFO (segment, sp1r_returncode);
    /* to lasterr, only store errors: */
    if ((sqlresult != NULL) &&
        ((result != cin01_db_ok) ||
            (sqlresult != &(session->lasterr.sqlresult)))) {
        sqlresult->returnCode = result;
        M_WARNINGSET(sqlresult->warnings) = M_WARNINGSET
            (RECINFO (segment, sp1r_extern_warning));
        sqlresult->errorPos = RECINFO (segment, sp1r_errorpos);
        if (result == cin01_db_row_not_found) {
            sqlresult->rowCount = 0;
        }
        else {
            sqlresult->rowCount = i28resultcount (session);
        }
        MEMCPY_MIN01 (sqlresult->sqlstate, RECINFO (segment, sp1r_sqlstate));
        if (result != cin01_db_ok) {
            if (i28findpart (session, sp1pk_errortext)) {
                memcpy (sqlresult->sqlmsg, PARTDATA (session->part),
                    sizeof (sqlresult->sqlmsg) - 1);
                msglen = PARTINFO (session->part, sp1p_buf_len);
                sqlresult->sqlmsg[msglen] = '\0';
            }
        }
    }
    return result;
}

/*----------------------------------------*/

int
i28requestForPython (
    tin01_sql_session * session,
    tin01_sqlresult * sqlresult)
{
    /* ROUTINE_DBG_MSP00 ("i28requestForPython"); */
    tsp01_CommErr  comm_error;
    tsp00_Int2        result;

    if (sqlresult == NULL)
        sqlresult = &(session->lasterr.sqlresult);
    if (!session->is_connected) {
        TRACE_MIN01 (4, SQLTRACE, "No connection: command skipped");
        result = cin01_db_not_accessible;
        if (sqlresult != NULL) {
            sqlresult->returnCode = result;
            M_WARNINGSET (sqlresult->warnings) = EMPTYSET_MIN01;
            sqlresult->errorPos = 0;
            sqlresult->rowCount = 0;
            MEMCPY_MIN01 (sqlresult->sqlstate, "I8888");
            sqlresult->sqlmsg[0] = '\0';
        }
        return result;
    }
    session->rec_packet = NULL;
    i28closesend (session);
    IFTRACE_MIN01 (4, j96dumppacket (session, "REQUEST", SQLTRACE));
    comm_error = i28request (session);
    result = i28_handleCommError (session, sqlresult, comm_error);
    return result;
}

/*----------------------------------------*/

int
i28receiveForPython (
    tin01_sql_session * session,
    tin01_sqlresult * sqlresult)
{
    /* ROUTINE_DBG_MSP00 ("i28receiveForPython"); */
    tsp01_CommErr  comm_error;
    tsp00_Int2        result;

    if (sqlresult == NULL)
        sqlresult = &(session->lasterr.sqlresult);
    comm_error = i28receive (session);
    i28lasterr_on (session);
    result = i28_handleCommError (session, sqlresult, comm_error);
    if (result == cin01_db_ok) {
        result = i28_handleSQLError (session, sqlresult);
    }
    return result;
}

/*----------------------------------------*/


Generated by  Doxygen 1.6.0   Back to index