.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VPA12PC$
.tt 2 $$$
.TT 3 $BurkhardD$LEVEL 2 FUNCTIONS P - Z$2001-07-10$
***********************************************************
.nf

.nf

.nf

    ========== licence begin  GPL
    Copyright (c) 2000-2005 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
.fo


.fo


.fo
Module  :
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
Define  :
.CM *-END-* define --------------------------------------
Use     :
.CM *-END-* use -----------------------------------------
Synonym :
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : BurkhardD
.sp
.cp 3
Created : 08-31-1993
.sp
.cp 3
Version : 1994-04-25
.sp
.cp 3
Release :  7.3    Date : 2001-07-10
.sp
Specification:
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.CM -lll-
Code    :
#ifndef DEBUG
#line 63 "vpa12pc"
#endif

#include "vpa00global.h"
#include "vpa10Handle.h"
#include "vpa50Env.h"
#include "vpa40DBC.h"
#include "vpa60Stmt.h"
#include "vpa80String.h"
#include "vpa30.h"
#include "vpa06.h"
#include "vpa09.h"
#include "SAPDB/SAPDBCommon/MemoryManagement/SAPDBMem_Alloca.h"

#ifndef SAPDB_FAST
#ifndef _UNICODE_ODBC
UCHAR *PA12_FN_SQLPARAMOPTIONS = { (UCHAR*) "SQLParamOptions" };
UCHAR *PA12_FN_SQLPRIMARYKEYS = { (UCHAR*) "SQLPrimaryKeys" };
UCHAR *PA12_FN_SQLPROCEDURECOLUMNS = { (UCHAR*) "SQLProcedureColumns" };
UCHAR *PA12_FN_SQLPROCEDURES = { (UCHAR*) "SQLProcedures" };
UCHAR *PA12_FN_SQLSETPOS = { (UCHAR*) "SQLSetPos" };
UCHAR *PA12_FN_SQLSETSCROLLOPTIONS = { (UCHAR*) "SQLSetScrollOptions" };
UCHAR *PA12_FN_SQLTABLEPRIVILEGES = { (UCHAR*) "SQLTablePrivileges" };
#else
extern UCHAR *PA12_FN_SQLPARAMOPTIONS;
extern UCHAR *PA12_FN_SQLPRIMARYKEYS;
extern UCHAR *PA12_FN_SQLPROCEDURECOLUMNS;
extern UCHAR *PA12_FN_SQLPROCEDURES;
extern UCHAR *PA12_FN_SQLSETPOS;
extern UCHAR *PA12_FN_SQLSETSCROLLOPTIONS;
extern UCHAR *PA12_FN_SQLTABLEPRIVILEGES;
#endif
#endif

/* PROTOTYPES from VPA12AC */
RETCODE pa12FetchOneRow( tpa50Env       *env_block_ptr, 
                         tpa40DBC       *dbc_block_ptr,
                         tpa60Stmt      *stmt_block_ptr,
                         tpa20Desc      *appl_desc_ptr,
                         tpa20Desc      *impl_desc_ptr,                        
                         SQLUSMALLINT    fetchtype, 
                         SQLROWOFFSET    pos,
                         SQLUSMALLINT   *rowstatus,
                         SQLHSTMT        hstmt);

RETCODE pa12SelectOneRow( SQLHSTMT   hstmt,
                          tpa20Desc *appl_desc_ptr,
                          tpa20Desc *impl_desc_ptr );

/* local prototypes */

/* check if arguments for SQLSetPos are valid */
SQLRETURN pa12_CheckSetPosArguments( tpa60Stmt    *stmtPtr,
                                     SQLROWOFFSET  irow,
                                     SQLUSMALLINT  fOption,
                                     SQLUSMALLINT  fLock);

/* builds a parameter list of the form "col1=?, col2=?, ..." with all columns
 * in the ard that have a length != SQL_IGNORE. In numParams the actual number
 * of parameters is returned. */
API_RETCODE pa12_BuildParamList( tpa20Desc   *ard,
                                 sqldatype   *sqldaPtr,
                                 SQLUINTEGER  rowsetPos,
                                 UCHAR       *stringBuf,
                                 tsp00_Int4   bufLen,
                                 tsp00_Int4  *numParams );


/* build insert, update or delete stmt for SQLSetPos */
API_RETCODE pa12_BuildSqlStmt( SQLUSMALLINT          fOption,
                               tpr05_String  *sqlBuf,
                               tsp00_Int4     bufLen,
                               tpr05_String  *tableName,
                               UCHAR         *paramList,
                               tpr05_String  *cursorName);


SQLRETURN pa12_AllocHstmtSetPos( SQLHDBC     hdbc,
                                 tpa60Stmt  *stmtPtr,
                                 tpa60Stmt **stmtSetPos );

VOID pa12_SetRowstatus( SQLUSMALLINT *statPtr, 
                        SQLUSMALLINT status );

/* http://pts:1080/webpts?wptsdetail=yes&ErrorType=1&ErrorID=1130120 */
const char* pa12_getTablePrefix (tpa40DBC *dbc_block_ptr);

/* ------------------------------------------------------------------------ */
#ifndef _UNICODE_ODBC
/* SQLPrimaryKeys */
const char *PA12PKSELECT = \
"SELECT TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, COLUMN_NAME, KEY_SEQ, \
NULL PK_NAME FROM %sCOLUMNS \
WHERE KEY_SEQ IS NOT NULL AND TABLE_OWNER = '%%'=.*S' AND TABLE_NAME = '%%'=.*S' \
ORDER BY 2, 3, 5";

/* ODBC version 3.x expects different column names */
const char *PA12PKSELECT_OV3 = \
"SELECT TABLE_QUALIFIER TABLE_CAT, TABLE_OWNER TABLE_SCHEM, \
TABLE_NAME, COLUMN_NAME, KEY_SEQ, NULL PK_NAME \
FROM %sCOLUMNS \
WHERE KEY_SEQ IS NOT NULL AND TABLE_OWNER = '%%'=.*S' AND TABLE_NAME = '%%'=.*S' \
ORDER BY 2, 3, 5";

/* ------------------------------------------------------------------------ */
/* SQLProcedures SQL-Statements */
const char *PA12SELECTPROCEDURES = \
"SELECT PROCEDURE_QUALIFIER,  PROCEDURE_OWNER, PROCEDURE_NAME, \
NUM_INPUT_PARAMS, NUM_OUTPUT_PARAMS, NUM_RESULT_SETS, REMARKS, \
PROCEDURE_TYPE FROM %sPROCEDURES \ 
WHERE PROCEDURE_OWNER LIKE '%%'=.*S' ESCAPE '%%c' AND \ 
PROCEDURE_NAME LIKE '%%'=.*S' ESCAPE '%%c' ORDER BY 2, 3 ";

/* ODBC version 3.x expects different column names */
const char *PA12SELECTPROCEDURES_OV3 = \
"SELECT PROCEDURE_QUALIFIER PROCEDURE_CAT, \
PROCEDURE_OWNER PROCEDURE_SCHEM, PROCEDURE_NAME, \
NUM_INPUT_PARAMS, NUM_OUTPUT_PARAMS, NUM_RESULT_SETS, REMARKS, \
PROCEDURE_TYPE FROM %sPROCEDURES \ 
WHERE PROCEDURE_OWNER LIKE '%%'=.*S' ESCAPE '%%c' AND \ 
PROCEDURE_NAME LIKE '%%'=.*S' ESCAPE '%%c' ORDER BY 2, 3 ";

/* ------------------------------------------------------------------------ */
/* SQLProcedureColumns SQL-Statements */
const char *PA12SELECTPROCEDURECOLUMNS = \
"SELECT PROCEDURE_QUALIFIER, PROCEDURE_OWNER, PROCEDURE_NAME, COLUMN_NAME, \
COLUMN_TYPE, DATA_TYPE, TYPE_NAME, PRECISION, \"LENGTH\", SCALE, RADIX, \
NULLABLE, REMARKS, CODETYPE FROM %sPROCCOLUMNS WHERE \
PROCEDURE_OWNER LIKE '%'=.*S' ESCAPE '%c' AND PROCEDURE_NAME LIKE '%'=.*S' \
ESCAPE '%c' AND COLUMN_NAME LIKE '%'=.*S' ESCAPE '%c' ORDER BY 2, 3, PARAM_NO ";

/* ------------------------------------------------------------------------ */
/* SQLTablePrivileges SQL-Statements */
const char *PA12SELECTTABLEPRIVILEGES = \
"SELECT TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, GRANTOR, GRANTEE, \
PRIVILEGE, IS_GRANTABLE FROM %sTABLEPRIVILEGES WHERE \
TABLE_OWNER LIKE '%%'=.*S'  ESCAPE '%%c' AND TABLE_NAME LIKE '%%'=.*S' ESCAPE '%%c' \
ORDER BY 2, 3, 6 ";

/* ODBC version 3.x expects different column names */
const char *PA12SELECTTABLEPRIVILEGES_OV3 = \
"SELECT TABLE_QUALIFIER TABLE_CAT, TABLE_OWNER TABLE_SCHEM, \
TABLE_NAME, GRANTOR, GRANTEE, PRIVILEGE, IS_GRANTABLE \
FROM %sTABLEPRIVILEGES \
WHERE TABLE_OWNER LIKE '%%'=.*S'  ESCAPE '%%c' AND TABLE_NAME LIKE '%%'=.*S' ESCAPE '%%c' \
ORDER BY 2, 3, 6 ";

/* ------------------------------------------------------------------------ */
/* SQLSetpos SQL-Statements */
const char *PA12ADDSETPOS  = "INSERT %'=.*S SET %s ";
const char *PA12UPDSETPOS  = "UPDATE %'=.*S SET %s WHERE CURRENT OF \"%'=.*S\" ";
const char *PA12DELSETPOS  = "DELETE %'=.*S WHERE CURRENT OF \"%'=.*S\" ";
/* ------------------------------------------------------------------------ */

#else

extern const char *PA12PKSELECT;
extern const char *PA12PKSELECT_OV3;
extern const char *PA12SELECTPROCEDURES;
extern const char *PA12SELECTPROCEDURES_OV3;
extern const char *PA12SELECTPROCEDURECOLUMNS;
extern const char *PA12SELECTTABLEPRIVILEGES;
extern const char *PA12SELECTTABLEPRIVILEGES_OV3;

extern const char *PA12ADDSETPOS;
extern const char *PA12UPDSETPOS;
extern const char *PA12DELSETPOS;
#endif  /* of _UNICODE_ODBC */


#if 0
ODBC_PROC( SQLParamOptions, (HSTMT        hstmt,
                             SQLUINTEGER  crow,
                             SQLUINTEGER *pirow),
           (hstmt, crow, pirow))
{
    RETCODE retcode;
    API_RETCODE api_retcode;
  
    tpa60Stmt * stmt_block_ptr;
    SQLUSMALLINT state;
  
    API_TRACE(API_TR_ENTRY, PA12_FN_SQLPARAMOPTIONS, 0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE(API_TR_UDWORD,"crow",&crow);
    API_TRACE(API_TR_PTR,"pirow",&pirow);

    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLPARAMOPTIONS);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    else {
        /* ----------------------------------------------------------- */
        /* ----- Check hstmt ----- */
        if (pa60VerifyStmt( hstmt ) != API_OK) { /* hstmt valid ? */
            retcode = SQL_INVALID_HANDLE;
            goto error_exit;
        }
        else {
            state = ((tpa60Stmt*) hstmt)->state;
            if ((state != API_STMT_PREPARED) && 
                (state != API_STMT_EXECUTED)) {
                /* function sequence error */
                pa60PutError( hstmt, 
                              API_ODBC_S1010, NULL);
                retcode = SQL_ERROR; 
                goto error_exit;
            }
        }
        /* ----------------------------------------------------------- */
        /* ----- Check crow ----- */ 
        if (crow < 1) {
            /* row value out of range */
            pa60PutError( hstmt, 
                          API_ODBC_S1107, NULL);
            retcode = SQL_ERROR; 
            goto error_exit;
        }
        /* ----------------------------------------------------------- */
        retcode = SQL_SUCCESS;
	
        stmt_block_ptr = (tpa60Stmt *) apdlock(hstmt);
        API_ASSERT_PTR(stmt_block_ptr);
	
        *pirow = 1;
        stmt_block_ptr -> parm_crow = crow;
        stmt_block_ptr -> parm_pirow_ptr = pirow;
	
    }
error_exit:  
    API_TRACE(API_TR_EXIT, PA12_FN_SQLPARAMOPTIONS, 0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);
} /* SQLParamOptions */
#endif /* if 0 */


/*
typedef struct {
  UCHAR owner_buffer [(API_USERID_MAX_LEN)+1];
  UCHAR table_buffer [(API_TABLE_NAME_MAX)+1];
} pa11SQLPrimaryKeys;
*/

typedef struct {
  tpr05_String *owner_buffer;
  tpr05_String *table_buffer;
} pa11SQLPrimaryKeys;


#ifdef _UNICODE_ODBC
ODBC_PROC(SQLPrimaryKeysW,(SQLHSTMT      hstmt,
                           SQLWCHAR     *szTableQualifier,
                           SQLSMALLINT   cbTableQualifier,
                           SQLWCHAR     *szTableOwner,
                           SQLSMALLINT   cbTableOwner,
                           SQLWCHAR     *szTableName,
                           SQLSMALLINT   cbTableName),
          ( hstmt, szTableQualifier, cbTableQualifier, szTableOwner,
            cbTableOwner, szTableName, cbTableName))
#else
ODBC_PROC(SQLPrimaryKeys, (SQLHSTMT      hstmt,
                           SQLCHAR      *szTableQualifier,
                           SQLSMALLINT   cbTableQualifier,
                           SQLCHAR      *szTableOwner,
                           SQLSMALLINT   cbTableOwner,
                           SQLCHAR      *szTableName,
                           SQLSMALLINT   cbTableName),
          ( hstmt, szTableQualifier, cbTableQualifier, szTableOwner,
            cbTableOwner, szTableName, cbTableName))
#endif
{
    RETCODE      retcode=SQL_SUCCESS;
    API_RETCODE  api_retcode;
    int          sql_len;
    API_HANDLE   hand=API_NULL_HANDLE;
    SQLUSMALLINT state;

    pa11SQLPrimaryKeys LV;
    tpa60Stmt   *stmt_block_ptr;
    SQLHENV      henv;
    tpa50Env    *env_block_ptr;
    SQLHDBC      hdbc;
    tpa40DBC    *dbc_block_ptr;
    SQLUINTEGER  odbcVersion;
    char        *pkSelect;
    const char  *tableprefix;
#ifdef _UNICODE_ODBC
    const tsp77encoding *encodingType = sp77nativeUnicodeEncoding ();
    SQLCHAR      sql_string [API_SQL_STRING_SWAG * 3 * sizeof (tsp81_UCS2Char)];
#else
    const tsp77encoding *encodingType = sp77encodingAscii;
    SQLCHAR      sql_string [API_SQL_STRING_SWAG * 3];
#endif   
    const int charSize = encodingType->fixedCharacterSize;
    
    API_TRACE( API_TR_ENTRY, PA12_FN_SQLPRIMARYKEYS, 0);
    API_TRACE( API_TR_HANDLE, "hstmt", &hstmt );
    API_TRACE_LEN( API_TR_ODBC_STRING, "szTableQualifier",
                   szTableQualifier, cbTableQualifier );
    API_TRACE( API_TR_SWORD, "cbTableQualifier", &cbTableQualifier);
    API_TRACE_LEN( API_TR_ODBC_STRING, "szTableOwner",
                   szTableOwner, cbTableOwner);
    API_TRACE(API_TR_SWORD,"cbTableOwner",&cbTableOwner);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szTableName", szTableName, cbTableName);

    LV.owner_buffer = LV.table_buffer = NULL;

    if (cbTableQualifier != SQL_NTS)
      cbTableQualifier *= charSize;
    if (cbTableOwner != SQL_NTS)
      cbTableOwner *= charSize;
    if (cbTableName != SQL_NTS)
      cbTableName *= charSize;
    
    api_retcode = API_OK;
    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLPRIMARYKEYS);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    else {
        if (pa60VerifyStmt( hstmt ) != API_OK) { /* hstmt valid? */
            retcode = SQL_INVALID_HANDLE;
        }
        else {
            /* determine which ODBC version the application wants */
            if (!pa10GetODBCVersion( SQL_HANDLE_STMT, hstmt,
                                     &odbcVersion )) {
                retcode = SQL_ERROR;
                /* general error */
                pa60PutError( hstmt, API_ODBC_S1000, NULL);
                goto exit_1_lock;                    
            }; /* if */
            apmlocp(&hstmt, &stmt_block_ptr, &hdbc, &dbc_block_ptr, 
                    &henv, &env_block_ptr);
            state = stmt_block_ptr->state;
            tableprefix = pa12_getTablePrefix (dbc_block_ptr);
            /* ODBC version 3.0 defines different column-names */
            if (odbcVersion == SQL_OV_ODBC3) {
                pkSelect = (char *) alloca (strlen(PA12PKSELECT_OV3) + 30);
                sprintf (pkSelect, PA12PKSELECT_OV3, tableprefix);
            } else { /* version < 3.x */
                pkSelect = (char *) alloca (strlen(PA12PKSELECT) + 30);
                sprintf (pkSelect, PA12PKSELECT, tableprefix);
            }; /* else */
            PA09ENTERASYNCFUNCTION(dbc_block_ptr, stmt_block_ptr);
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, NULL)) { 
                if (pa09IsConnectionBusy(stmt_block_ptr, dbc_block_ptr)) {
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt, API_ODBC_S1010, NULL);
                    goto exit_1_lock;
                }	
                if (state == API_STMT_POSITIONED) {
                    /* function seqeunces error */
                    retcode = SQL_ERROR;            /* SQLSTATE: 24000 */
                    pa60PutError( hstmt, API_ODBC_24000, NULL);
                    goto exit_1_lock;
                }

                /* create strings */
                LV.owner_buffer = 
                  pr05IfCom_String_NewDynString (charSize * (API_USERID_MAX_LEN+1),
                                                 encodingType);
                LV.table_buffer = 
                  pr05IfCom_String_NewDynString (charSize * (API_TABLE_NAME_MAX+1), 
                                                 encodingType);

                if (LV.owner_buffer == NULL || LV.table_buffer == NULL) {
                  retcode = SQL_ERROR;            
                  pa60PutError( hstmt, API_ODBC_S1001, NULL);
                  goto exit_1_lock;
                }

                /* get owner and table name   */
                if (szTableOwner == NULL) {
                  if (pr05IfCom_String_strcpy (LV.owner_buffer, dbc_block_ptr->userid) != ok_epr05)
                    api_retcode = API_NOT_OK;
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.owner_buffer,
                                                   encodingType,
                                                   szTableOwner,
                                                   cbTableOwner);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                if (szTableName == NULL) {
/*                     API_STRCPY((UCHAR *)LV.table_buffer->rawString, (UCHAR *)""); */
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.table_buffer,
                                                   encodingType,
                                                   szTableName,
                                                   cbTableName);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
      
                stmt_block_ptr -> dbc_special.special =
                    API_SPEC_SQLPRIMARYKEYS;
                if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                    /* store the local stack to restore get the values
                     * in async call */
                    pa09SaveStack( &stmt_block_ptr->async.hLocalValues,
                                   &LV,
                                   sizeof(LV));
                    pa09PrepareAsyncCall(hstmt, SQL_API_SQLPRIMARYKEYS);     
                }
            } /* async exec */
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                pa09ExecuteAsyncCall(hstmt);
                goto exit_asnyc;
            }
            else {
                /* restore the stack values from async caller */
                if (stmt_block_ptr->async.hLocalValues) {
                    pa09RestoreStack(stmt_block_ptr->async.hLocalValues, &LV);
                    apdfree(stmt_block_ptr->async.hLocalValues);
                    stmt_block_ptr->async.hLocalValues = API_NULL_HANDLE;
                }
            }
            sql_len = sp77sprintfUnicode (encodingType,
                                          sql_string, sizeof (sql_string), 
                                          (char*) pkSelect,
                                          LV.owner_buffer->encodingType,
                                          LV.owner_buffer->cbLen,
                                          LV.owner_buffer->rawString,
                                          LV.table_buffer->encodingType,
                                          LV.table_buffer->cbLen,
                                          LV.table_buffer->rawString);
            if (retcode == SQL_SUCCESS) {
#ifdef _UNICODE_ODBC
              retcode = CALL_ODBC(SQLPrepareW, (hstmt, (SQLWCHAR*) sql_string, 
                                                sql_len / charSize));
#else
              retcode = CALL_ODBC(SQLPrepare, (hstmt, sql_string, sql_len));
#endif
            }
            if (retcode == SQL_SUCCESS) {
              retcode = CALL_ODBC(SQLExecute, (hstmt));
            }
            apdfree(hand);

        exit_1_lock:
            pr05IfCom_String_DeleteString (LV.owner_buffer);
            pr05IfCom_String_DeleteString (LV.table_buffer);
        exit_asnyc:
            PA09LEAVEASYNCFUNCTION();
        }  /* start processing */
    } /* set odbc_funtion */ 
    API_TRACE(API_TR_EXIT, PA12_FN_SQLPRIMARYKEYS, 0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);
} /* SQLPrimaryKeys */


typedef struct {
  tpr05_String  *proc_qualifier;
  tpr05_String  *proc_owner;
  tpr05_String  *proc_name;
  tpr05_String  *column_name;
} pa11SQLProcedureColumns;


#ifdef _UNICODE_ODBC
ODBC_PROC(SQLProcedureColumnsW,(SQLHSTMT     hstmt,
                                SQLWCHAR    *szProcQualifier,
                                SQLSMALLINT  cbProcQualifier,
                                SQLWCHAR    *szProcOwner,
                                SQLSMALLINT  cbProcOwner,
                                SQLWCHAR    *szProcName,
                                SQLSMALLINT  cbProcName,
                                SQLWCHAR    *szColumnName,
                                SQLSMALLINT  cbColumnName),
          ( hstmt, szProcQualifier, cbProcQualifier, szProcOwner,
            cbProcOwner, szProcName, cbProcName, szColumnName, cbColumnName))
#else
ODBC_PROC(SQLProcedureColumns,(SQLHSTMT     hstmt,
                               SQLCHAR     *szProcQualifier,
                               SQLSMALLINT  cbProcQualifier,
                               SQLCHAR     *szProcOwner,
                               SQLSMALLINT  cbProcOwner,
                               SQLCHAR     *szProcName,
                               SQLSMALLINT  cbProcName,
                               SQLCHAR     *szColumnName,
                               SQLSMALLINT  cbColumnName),
          ( hstmt, szProcQualifier, cbProcQualifier, szProcOwner,
            cbProcOwner, szProcName, cbProcName, szColumnName, cbColumnName))
#endif
{
    RETCODE retcode=SQL_SUCCESS;
    API_RETCODE api_retcode;
    /* ----------------------------------------------------------------- */

    SQLUSMALLINT         state;

    pa11SQLProcedureColumns LV;
    SQLHDBC     hdbc;
    SQLHENV     henv;
    tpa40DBC   *dbc_block_ptr;
    tpa50Env   *env_block_ptr;
    tpa60Stmt  *stmt_block_ptr;
#ifdef _UNICODE_ODBC
    const tsp77encoding *encodingType = sp77nativeUnicodeEncoding ();
    SQLCHAR      sqlString [API_SQL_STRING_SWAG * 3 * sizeof (tsp81_UCS2Char)];
#else
    const tsp77encoding *encodingType = sp77encodingAscii;
    SQLCHAR      sqlString [API_SQL_STRING_SWAG * 3];
#endif   
    const int charSize = encodingType->fixedCharacterSize;
    SQLINTEGER   sqlLen;
/* -------------------------------------------------------------------- */

    API_TRACE(API_TR_ENTRY, PA12_FN_SQLPROCEDURECOLUMNS, 0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szProcQualifier",
                  szProcQualifier, cbProcQualifier);
    API_TRACE(API_TR_SWORD,"cbProcQualifier",&cbProcQualifier);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szProcOwner",
                  szProcOwner, cbProcOwner);
    API_TRACE(API_TR_SWORD,"cbProcOwner",&cbProcOwner);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szProcName",
                  szProcName, cbProcName);
    API_TRACE(API_TR_SWORD,"cbProcName",&cbProcName);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szColumnName",
                  szColumnName, cbColumnName);
    API_TRACE(API_TR_SWORD,"cbColumname",&cbColumnName);

    LV.proc_qualifier = LV.proc_owner  = NULL;
    LV.proc_name      = LV.column_name = NULL;

    if (cbProcQualifier != SQL_NTS)
      cbProcQualifier *= charSize;
    if (cbProcOwner != SQL_NTS)
      cbProcOwner *= charSize;
    if (cbProcName != SQL_NTS)
      cbProcName *= charSize;
    if (cbColumnName != SQL_NTS)
      cbColumnName *= charSize;
    
    /* ---------------------------------------------------------------- */
    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLPROCEDURECOLUMNS);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    /* ---------------------------------------------------------------- */
    else {
        if (pa60VerifyStmt( hstmt ) != API_OK) {        /* hstmt valid ? */
            retcode = SQL_INVALID_HANDLE;
        }
        else {
            apmlocp(&hstmt, &stmt_block_ptr, &hdbc, &dbc_block_ptr, 
                    &henv, &env_block_ptr);
            state = stmt_block_ptr->state;
            PA09ENTERASYNCFUNCTION(dbc_block_ptr, stmt_block_ptr);
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, NULL)) { 
                if (pa09IsConnectionBusy(stmt_block_ptr, dbc_block_ptr)) {
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt,
                                  API_ODBC_S1010, NULL);
                    goto exit_1_lock;
                }   
                if (state == API_STMT_POSITIONED) {
                    /* function seqeunces error */
                    retcode = SQL_ERROR;            /* SQLSTATE: 24000 */
                    pa60PutError( hstmt, API_ODBC_24000, NULL);
                    goto exit_1_lock;
                }

                /* ---------------------------------------------------- */
                /* ***** szProcQualifier */
                /* create strings */
                LV.proc_qualifier = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1),
                                                 encodingType);
                LV.proc_owner  = 
                  pr05IfCom_String_NewDynString (charSize * ((API_USERID_MAX_LEN*2)+1),
                                                 encodingType);
                LV.proc_name   = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1),
                                                 encodingType);
                LV.column_name = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1),
                                                 encodingType);
                if (LV.proc_qualifier == NULL || LV.proc_owner  == NULL || 
                    LV.proc_name      == NULL || LV.column_name == NULL) {
                  retcode = SQL_ERROR;            
                  pa60PutError( hstmt, API_ODBC_S1001, NULL);
                  goto exit_1_lock;
                }

                if (szProcQualifier == NULL) {
/*                     API_STRCPY( (UCHAR*) LV.proc_qualifier->rawString, (UCHAR*) ""); */
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.proc_qualifier,
                                                   encodingType,
                                                   szProcQualifier,
                                                   cbProcQualifier);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                /* ***** szProcOwner */
                if (szProcOwner == NULL) {
                    pr05IfCom_String_strcatP (LV.proc_owner, "%", 
                                              (tsp00_Uint4) API_STRLEN ("%"),
                                              sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.proc_owner,
                                                   encodingType,
                                                   szProcOwner,
                                                   cbProcOwner);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                /* ***** szProcName */
                if (szProcName == NULL) {
                    pr05IfCom_String_strcatP (LV.proc_name, "%",
                                              (tsp00_Uint4) API_STRLEN ("%"),
                                              sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.proc_name,
                                                   encodingType,
                                                   szProcName,
                                                   cbProcName);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL );
                        goto exit_1_lock;
                    }
                }
                /* ***** szColumnName */
                if (szColumnName == NULL) {
                    pr05IfCom_String_strcatP (LV.column_name, "%",
                                              (tsp00_Uint4) API_STRLEN ("%"),
                                              sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.column_name,
                                                   encodingType,
                                                   szColumnName,
                                                   cbColumnName);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                stmt_block_ptr -> dbc_special.special =
                    API_SPEC_SQLPROCEDURESCOLUMNS;
                if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                    /* store the local stack to restore get the values
                     * in async call */
                    pa09SaveStack( &stmt_block_ptr->async.hLocalValues,
                                   &LV,
                                   sizeof(LV) );
                    pa09PrepareAsyncCall(hstmt, SQL_API_SQLPROCEDURECOLUMNS);
                }
            } /* async exec */
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                pa09ExecuteAsyncCall(hstmt);
                goto exit_async;
            }
            else {
                /* restore the stack values from async caller */
                if (stmt_block_ptr->async.hLocalValues) {
                    pa09RestoreStack(stmt_block_ptr->async.hLocalValues, &LV);
                    apdfree(stmt_block_ptr->async.hLocalValues);
                    stmt_block_ptr->async.hLocalValues = API_NULL_HANDLE;
                }
            }
            /* ---------------------------------------------------- */
            sqlLen = sp77sprintfUnicode (encodingType,
                                         sqlString, sizeof (sqlString),
                                         PA12SELECTPROCEDURECOLUMNS,
                                         pa12_getTablePrefix (dbc_block_ptr),
                                         LV.proc_owner->encodingType,
                                         LV.proc_owner->cbLen,
                                         LV.proc_owner->rawString,
                                         API_ESCAPE_CHAR, 
                                         LV.proc_name->encodingType,
                                         LV.proc_name->cbLen,
                                         LV.proc_name->rawString,
                                         API_ESCAPE_CHAR, 
                                         LV.column_name->encodingType,
                                         LV.column_name->cbLen,
                                         LV.column_name->rawString,
                                         API_ESCAPE_CHAR);
            /* ---------------------------------------------------- */
            if (retcode == SQL_SUCCESS) {
#ifdef _UNICODE_ODBC
              retcode = CALL_ODBC(SQLPrepareW, (hstmt, (SQLWCHAR*) sqlString, 
                                                sqlLen / charSize));
#else
              retcode = CALL_ODBC(SQLPrepare, (hstmt, sqlString, sqlLen));
#endif
              if (retcode == SQL_SUCCESS) {
                retcode = CALL_ODBC(SQLExecute, (hstmt));
              }
            }
        exit_1_lock:
            pr05IfCom_String_DeleteString (LV.proc_qualifier);
            pr05IfCom_String_DeleteString (LV.proc_owner);
            pr05IfCom_String_DeleteString (LV.proc_name);
            pr05IfCom_String_DeleteString (LV.column_name);
        exit_async:
            PA09LEAVEASYNCFUNCTION();
        }  /* start processing */
    } /* set odbc_funtion */ 
    API_TRACE(API_TR_EXIT, PA12_FN_SQLPROCEDURECOLUMNS, 0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);
} /* SQLProcedureColumns */


typedef struct {
  tpr05_String    *proc_qualifier;
  tpr05_String    *proc_owner;
  tpr05_String    *proc_name;
} pa11SQLProcedures;

#ifdef _UNICODE_ODBC
ODBC_PROC(SQLProceduresW, (SQLHSTMT     hstmt,
                           SQLWCHAR    *szProcQualifier,
                           SQLSMALLINT  cbProcQualifier,
                           SQLWCHAR    *szProcOwner,
                           SQLSMALLINT  cbProcOwner,
                           SQLWCHAR    *szProcName,
                           SQLSMALLINT  cbProcName),
      ( hstmt, szProcQualifier, cbProcQualifier, szProcOwner, cbProcOwner, szProcName, cbProcName))
#else
ODBC_PROC(SQLProcedures, (SQLHSTMT     hstmt,
                          SQLCHAR     *szProcQualifier,
                          SQLSMALLINT  cbProcQualifier,
                          SQLCHAR     *szProcOwner,
                          SQLSMALLINT  cbProcOwner,
                          SQLCHAR     *szProcName,
                          SQLSMALLINT  cbProcName),
      ( hstmt, szProcQualifier, cbProcQualifier, szProcOwner, cbProcOwner, szProcName, cbProcName))
#endif
{
    RETCODE retcode=SQL_SUCCESS;
    API_RETCODE api_retcode;
    /* --------------------------------------------------------------- */

    SQLUSMALLINT  state;

    pa11SQLProcedures LV;
    SQLHENV    henv;
    SQLHDBC    hdbc;
    tpa50Env  *env_block_ptr;
    tpa40DBC  *dbc_block_ptr;
    tpa60Stmt *stmt_block_ptr;
    SQLUINTEGER odbcVersion;
    char       *selectProcedures;
    const char *tableprefix;
#ifdef _UNICODE_ODBC
    const tsp77encoding *encodingType = sp77nativeUnicodeEncoding ();
    SQLCHAR sqlString[API_SQL_STRING_SWAG * 3 * sizeof (tsp81_UCS2Char)];
#else
    const tsp77encoding *encodingType = sp77encodingAscii;
    SQLCHAR sqlString[API_SQL_STRING_SWAG * 3];
#endif   
    const int charSize = encodingType->fixedCharacterSize;
    SQLINTEGER sqlLen;
    
    /* -------------------------------------------------------------- */

    API_TRACE(API_TR_ENTRY, PA12_FN_SQLPROCEDURES, 0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szProcQualifier",
                  szProcQualifier, cbProcQualifier);
    API_TRACE(API_TR_SWORD,"cbProcQualifier",&cbProcQualifier);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szProcOwner",
                  szProcOwner, cbProcOwner);
    API_TRACE(API_TR_SWORD,"cbProcOwner",&cbProcOwner);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szProcName",
                  szProcName, cbProcName);
    API_TRACE(API_TR_SWORD,"cbProcName",&cbProcName);

    LV.proc_qualifier = LV.proc_owner = LV.proc_name = NULL;

    if (cbProcQualifier != SQL_NTS)
      cbProcQualifier *= charSize;
    if (cbProcOwner != SQL_NTS)
      cbProcOwner *= charSize;
    if (cbProcName != SQL_NTS)
      cbProcName *= charSize;
    /* -------------------------------------------------------------- */
    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLPROCEDURES);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    /* --------------------------------------------------------------- */
    else {
        if (pa60VerifyStmt(hstmt) != API_OK) {        /* hstmt valid ? */
            retcode = SQL_INVALID_HANDLE;
        }
        else {
            /* determine which ODBC version the application wants */
            if (!pa10GetODBCVersion( SQL_HANDLE_STMT, hstmt,
                                     &odbcVersion )) {
                retcode = SQL_ERROR;
                /* general error */
                pa60PutError( hstmt, API_ODBC_S1000, NULL);
                goto exit_1_lock;                    
            }; /* if */
            apmlocp(&hstmt, &stmt_block_ptr, &hdbc, &dbc_block_ptr, 
                    &henv, &env_block_ptr);
            state = stmt_block_ptr->state;
            tableprefix = pa12_getTablePrefix (dbc_block_ptr);
            /* ODBC version 3.0 defines different column-names */
            if (odbcVersion == SQL_OV_ODBC3) {
                selectProcedures = (char *) alloca (strlen(PA12SELECTPROCEDURES_OV3) + 30);
                sprintf (selectProcedures, PA12SELECTPROCEDURES_OV3, tableprefix);
            } else { /* version < 3.x */
                selectProcedures = (char *) alloca (strlen(PA12SELECTPROCEDURES) + 30);
                sprintf (selectProcedures, PA12SELECTPROCEDURES, tableprefix);
            }; /* else */
            PA09ENTERASYNCFUNCTION(dbc_block_ptr, stmt_block_ptr);
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, NULL)) { 
                if (pa09IsConnectionBusy(stmt_block_ptr, dbc_block_ptr)) {
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt, API_ODBC_S1010, NULL);
                    goto exit_1_lock;
                }   
                if (state == API_STMT_POSITIONED) {
                    /* function seqeunces error */
                    retcode = SQL_ERROR;            /* SQLSTATE: 24000 */
                    pa60PutError( hstmt, API_ODBC_24000, NULL);
                    goto exit_1_lock;
                }

                /* -------------------------------------------------- */
                /* create strings */
                LV.proc_qualifier = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1), 
                                                 encodingType);
                LV.proc_owner     = 
                  pr05IfCom_String_NewDynString (charSize * ((API_USERID_MAX_LEN*2)+1),
                                                 encodingType);
                LV.proc_name      = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1),
                                                 encodingType);

                if (LV.proc_qualifier == NULL || LV.proc_owner == NULL ||
                    LV.proc_name      == NULL) {
                  retcode = SQL_ERROR;            
                  pa60PutError( hstmt, API_ODBC_S1001, NULL);
                  goto exit_1_lock;
                }

                /* ***** szProcQualifier */
                if (szProcQualifier == NULL) {
/*                     API_STRCPY( (UCHAR*) LV.proc_qualifier->rawString, (UCHAR*) ""); */
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.proc_qualifier,
                                                   encodingType,
                                                   szProcQualifier,
                                                   cbProcQualifier);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                /* ***** szProcOwner */
                if (szProcOwner == NULL) {
                  pr05IfCom_String_strcatP (LV.proc_owner, "%",
                                            (tsp00_Uint4) API_STRLEN ("%"),
                                            sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.proc_owner,
                                                   encodingType,
                                                   szProcOwner,
                                                   cbProcOwner);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL );
                        goto exit_1_lock;
                    }
                }
                /* ***** szProcName */
                if (szProcName == NULL) {
                  pr05IfCom_String_strcatP (LV.proc_name, "%",
                                            (tsp00_Uint4) API_STRLEN ("%"),
                                            sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.proc_name,
                                                   encodingType,
                                                   szProcName,
                                                   cbProcName);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
      
                stmt_block_ptr -> dbc_special.special = API_SPEC_SQLPROCEDURES;
                if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                    /* store the local stack to restore get the values
                     * in async call */
                    pa09SaveStack( &stmt_block_ptr->async.hLocalValues, &LV, sizeof(LV) );
                    pa09PrepareAsyncCall(hstmt, SQL_API_SQLPROCEDURES);     
                }
            } /* async exec */
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                pa09ExecuteAsyncCall(hstmt);
                goto exit_async;
            }
            else {
                /* restore the stack values from async caller */
                if (stmt_block_ptr->async.hLocalValues) {
                    pa09RestoreStack(stmt_block_ptr->async.hLocalValues, &LV);
                    apdfree(stmt_block_ptr->async.hLocalValues);
                    stmt_block_ptr->async.hLocalValues = API_NULL_HANDLE;
                }
            }
            /* ------------------------------------------------------- */
            {
                API_ASSERT_PTR(sql_ptr);

                sqlLen = sp77sprintfUnicode (encodingType,
                                             sqlString, sizeof (sqlString),
                                             (char*) selectProcedures,
                                             LV.proc_owner->encodingType,
                                             LV.proc_owner->cbLen,
                                             LV.proc_owner->rawString,
                                             API_ESCAPE_CHAR,
                                             LV.proc_name->encodingType,
                                             LV.proc_name->cbLen,
                                             LV.proc_name->rawString,
                                             API_ESCAPE_CHAR);
                /* --------------------------------------------------- */
                if (retcode == SQL_SUCCESS) {
#ifdef _UNICODE_ODBC
                    retcode = CALL_ODBC(SQLPrepareW, (hstmt, (SQLWCHAR*) sqlString, 
                                                      sqlLen / charSize));
#else
                    retcode = CALL_ODBC(SQLPrepare, (hstmt, sqlString, sqlLen));
#endif
                    if (retcode == SQL_SUCCESS) {
                        retcode = CALL_ODBC(SQLExecute, (hstmt));
                    }
                }
            }
        exit_1_lock:
            pr05IfCom_String_DeleteString (LV.proc_qualifier);
            pr05IfCom_String_DeleteString (LV.proc_owner);
            pr05IfCom_String_DeleteString (LV.proc_name);
        exit_async:
            PA09LEAVEASYNCFUNCTION();
        }  /* start processing */
    } /* set odbc_funtion */ 
    API_TRACE(API_TR_EXIT, PA12_FN_SQLPROCEDURES, 0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);
} /* SQLProcedures */


#ifndef _UNICODE_ODBC

ODBC_PROC(SQLSetPos, (SQLHSTMT      hstmt,
                      SQLSETPOSIROW irow,
                      SQLUSMALLINT  fOption,
                      SQLUSMALLINT  fLock),
          (hstmt, irow, fOption, fLock))
{
    RETCODE         retcode;
    API_RETCODE     api_retcode;
   
    sqldatype      *sqlda_ptr;
    SQLHENV         henv;
    tpa50Env       *env_block_ptr;
    SQLHDBC         hdbc;
    tpa40DBC       *dbc_block_ptr;
    SQLHSTMT        hstmt_setpos = API_NULL_HANDLE;
    tpa60Stmt      *stmtsp_block_ptr;
    tpa60Stmt      *stmt_block_ptr;
    API_HANDLE      hrowstat     = API_NULL_HANDLE;
    api_row_status *rowstat_ptr  = NULL;
    SQLUINTEGER     fConcurrency;
    SQLINTEGER      fCursorType;
    SQLUSMALLINT    hrowstat_set = API_FALSE;
    SQLUSMALLINT    number_cols;
    SQLUINTEGER     rowset_size;
    SQLUINTEGER     number_row;
    SQLUINTEGER     bind_type;
    SQLROWOFFSET    absolute_pos;
    SQLULEN         crow;
    SQLUSMALLINT   *rowstatus;
    SQLUSMALLINT   *rowst = NULL;
    /*    UCHAR          *sql_ptr;*/
    tpr05_String   *SqlStmt = NULL;
    UCHAR          *paramList = NULL;
    SQLINTEGER      paramListBufLen = 0;
    SQLINTEGER      sql_len, i, j;
    SQLINTEGER      max_set;
    SQLINTEGER      relative_pos;
    SQLUSMALLINT    act_fc_code;
    SQLUSMALLINT    ipar;
    UCHAR          *tuple_ptr;
    SQLUINTEGER     tuple_size;

    tpa20Desc       *local_ard = NULL;
    tpa20Desc       *local_ird = NULL;
    tpa21DescRecord *ard_rec_ptr;
    tpa21DescRecord *ird_rec_ptr;

    tsp00_Bool       newStatement = false; /* set to true if update or insert
                                            * statement changed since last call.
                                            */
    
    API_TRACE(API_TR_ENTRY, PA12_FN_SQLSETPOS, 0);
    API_TRACE(API_TR_HANDLE, "hstmt", &hstmt);
    API_TRACE(API_TR_UWORD, "irow", &irow);
    API_TRACE(API_TR_OPTYPE, "fOption", &fOption);
    API_TRACE(API_TR_UWORD, "fLock", &fLock);

    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLSETPOS);
    if (api_retcode != API_OK) {
        retcode = pa06stfcerror(api_retcode, hstmt);
        goto error_exit;
    };
    /* ---------------------------------------------------------------- */
    /* ----- get pointer hstmt, hdbc, henv, attr_block, sqlda, tuple */
    if (pa60VerifyStmt( hstmt ) != API_OK) { /* hstmt valid ? */
        retcode = SQL_INVALID_HANDLE;
        goto error_exit;
    };
    apmlocp( &hstmt, &stmt_block_ptr, &hdbc, &dbc_block_ptr, 
             &henv, &env_block_ptr);
    PA09ENTERASYNCFUNCTION( dbc_block_ptr, stmt_block_ptr );
    number_cols = stmt_block_ptr -> number_cols;

    paramListBufLen = (SQLINTEGER) API_STRLEN(PA12UPDSETPOS) + API_TABLE_NAME_MAX +
        (API_COLUMN_NAME_MAX*number_cols) + API_ODBC_CURSOR_LEN + 50;
       
    /*    sql_ptr = apdallo( (DWORD) API_SQL_STRING_SWAG );*/
    if (stmt_block_ptr->cursor_name->encodingType == sp77encodingAscii)
      SqlStmt = pr05IfCom_String_NewDynString (paramListBufLen, NULL);
    else {
      SqlStmt = pr05IfCom_String_NewDynString
        (paramListBufLen * stmt_block_ptr->cursor_name->encodingType->fixedCharacterSize,
         stmt_block_ptr->cursor_name->encodingType);
    }
    paramList = apdallo( (DWORD) paramListBufLen );
    if ((SqlStmt == NULL) || (paramList == 0)) {
        retcode = SQL_ERROR;            
        pa60PutError( hstmt, API_ODBC_S1001, NULL );
        goto error_exit;
    }
    API_ASSERT_PTR(SqlStmt);
    API_ASSERT_PTR(paramList);
    /*    API_STRCPY( sql_ptr, (UCHAR*) "");   */
    API_STRCPY( paramList, (UCHAR*) "");   
    
    bind_type   = pa60GetARD( stmt_block_ptr )->header.bindType;
    rowset_size = stmt_block_ptr -> ardPtr->header.arraySize;
    rowstatus   = stmt_block_ptr -> ardPtr->header.arrayStatusPtr;
    hstmt_setpos = stmt_block_ptr -> hstmt_setpos;
    hrowstat = stmt_block_ptr -> hrowstat;
    number_row  = (SQLUINTEGER) irow;
    max_set = 1;

    API_TRACE(API_TR_HANDLE,"hstmt_setpos",&hstmt_setpos);
    API_TRACE(API_TR_HANDLE, "hrowstat", &hrowstat);
    /* ------------------------------------------------------------ */
    stmt_block_ptr -> setPosNeedData = FALSE;
    retcode = pa12_CheckSetPosArguments( stmt_block_ptr,
                                         irow,
                                         fOption,
                                         fLock );
    if (retcode != SQL_SUCCESS) {
        /* SQL_SUCCES_WITH_INFO means error in row. */
        goto error_exit;
    };            
    CALL_ODBC(SQLGetStmtAttr, ( hstmt,
                                SQL_CONCURRENCY,
                                &fConcurrency,
                                0, NULL));
    CALL_ODBC(SQLGetStmtAttr, ( hstmt,
                                SQL_CURSOR_TYPE,
                                &fCursorType,
                                0, NULL));
    /* lock sqlda */ 
    sqlda_ptr = (sqldatype*) stmt_block_ptr -> output_sqlda_handle;
    API_ASSERT_PTR(sqlda_ptr);

    tuple_size = stmt_block_ptr -> col_size;
    tuple_ptr  = (UCHAR*) stmt_block_ptr -> col_handle;
    API_ASSERT_PTR(tuple_ptr);
    /* ----------------------------------------------------------- */
    /* set hRowStatus for number of rows, if not
     * SQL_CURSOR_FORWARD_ONLY, SQL_CURSOR_DYNAMIC */
    if ((fCursorType != SQL_CURSOR_FORWARD_ONLY) && 
        (fCursorType != SQL_CURSOR_DYNAMIC)) {
        if ( fCursorType != SQL_CURSOR_KEYSET_DRIVEN
             || stmt_block_ptr->stmtopt.optimize_cursor == SQL_FALSE) {
            /* not OptimizedCursor */
            hrowstat_set = API_TRUE;
            pa06AllocRowStatus( &hrowstat,
                                stmt_block_ptr -> number_rows,
                                rowset_size );
            stmt_block_ptr->hrowstat = hrowstat;
            if (hrowstat != API_NULL_HANDLE) {
                rowstat_ptr = (api_row_status*) hrowstat;
            }
        }; /* if */
    }
    /* ----------------------------------------------------------- */
    /* ----- set api_attr_block position ----- */
    if ((fOption == SQL_REFRESH) && (irow != 0)) {
        /* we have to modify pointers in the ard so get a copy to preserve
         * the original ard. */
        local_ard = pa20CloneDesc( stmt_block_ptr->ardPtr );
        local_ird = pa20CloneDesc( &stmt_block_ptr->ird );
        if (local_ard == NULL || local_ird == NULL) {
            retcode = SQL_ERROR;
            pa60PutError( hstmt, API_ODBC_S1001, NULL );
            goto lock1_exit;
        }; /* if */
        /* set position of the cursor on the row specified by irow */
        pa20SetAttrAddr( stmt_block_ptr->ardPtr,
                         local_ard,
                         local_ird,
                         number_cols,
                         bind_type, 
                         number_row-1,
                         0 );
    }; /* if */
    /* ----------------------------------------------------------- */
    /* ----- Create insert and update parameters ----- */
    if ((fOption == SQL_ADD) || (fOption == SQL_UPDATE)) {
        /* insert and update statements are build below inside the for
         * loop because they may change for every row of the rowset */
        if (!pa60AllocSetPosSpecial( &stmt_block_ptr->setPosSpecial,
                                     stmt_block_ptr->ardPtr->count )) {
            /* memory allocation failure */
            retcode = SQL_ERROR;
            pa60PutError( hstmt, API_ODBC_S1001, NULL);
            goto lock1_exit;
        };
    } else { /* SQL_DELETE, SQL_REFRESH */
        /* ----- Create SQL-statement ------ */
        pa12_BuildSqlStmt( fOption, SqlStmt, API_SQL_STRING_SWAG,
                           stmt_block_ptr->table_name,
                           paramList,
                           stmt_block_ptr->cursor_name );
    }; /* else */
    switch (fOption) {
    case SQL_REFRESH : 
        if (irow == 0) { /* refresh all data in rowset */
            if ( fCursorType != SQL_CURSOR_DYNAMIC
                 && ( fCursorType != SQL_CURSOR_KEYSET_DRIVEN
                      || stmt_block_ptr->stmtopt.optimize_cursor
                      == SQL_FALSE)) {
                retcode = CALL_ODBC( SQLExtendedFetch,
                                     (hstmt,
                                      SQL_FETCH_ABSOLUTE,
                                      stmt_block_ptr -> fetch_pos,
                                      &crow,
                                      rowstatus));
            } else { /* DynamicCursor or optimized keyset driven cursor */
                retcode = CALL_ODBC( SQLExtendedFetch,
                                     (hstmt,
                                      SQL_FETCH_RELATIVE,
                                      0,
                                      &crow,
                                      rowstatus));
            }; /* else */
            if (retcode != SQL_SUCCESS) {
                goto lock1_exit;
            }; /* if */
        }
        break;
    case SQL_ADD        :
        act_fc_code = csp1_insert_fc;
        if (irow == 0) max_set = rowset_size;
        break;
    case SQL_UPDATE  :  
        act_fc_code = csp1_update_fc;
        /* set for call in loop, if irow (=0) for all rows */
        if (irow == 0) max_set = rowset_size;
        break;
    case SQL_DELETE  : 
        act_fc_code = csp1_delete_fc;
        /* set for call in loop, if irow (=0) for all rows */
        if (irow == 0) max_set = rowset_size;
        break;
    }
    /* ------------------------------------------------------------ */
    /* ----- Call in loop, if irow (=0) set for all rows ----- */
    for (i=1; i <= max_set; i++) {
        /* -------------------------------------------------------- */
        /* ***** set position rgfRowStatus for the row specified by irow */
        if (irow == 0) { 
            number_row = (SQLUINTEGER) i;
        };
        /* rowstatus (== SQL_ATTR_ROWSTATUS_PTR) may be NULL (PTS 1104915)
             */
        if (rowstatus) {
            if (irow == 0) { 
                if (number_row > 1)
                    rowstatus++;
            } else {
                for (j=1; j < (SQLINTEGER) number_row; j++)
                    rowstatus++;
            }
      
            /* if refresh only one row, set rgfRowStatus */
            if ((fOption == SQL_REFRESH) && (irow != 0)) {
                rowst = rowstatus;
            }
            /* Check rgfRowStatus for the row specified by irow */
            API_ASSERT_PTR( rowstatus );
            if (((*rowstatus==SQL_ROW_ERROR)
                 || (*rowstatus==SQL_ROW_DELETED))
                && (fOption != SQL_ADD)) {
                /* Invalid cursor position */
                pa60PutError( hstmt, API_ODBC_S1109, NULL );
                retcode = SQL_ERROR; 
                if (irow != 0)
                    goto lock1_exit;
            }
        }; /* if */
        /* -------------------------------------------------------- */ 
        /* ***** Set cursor to the absolute position */
        stmt_block_ptr->output_sqlda_ptr = sqlda_ptr;
        api_retcode = pa20SetAttr( sqlda_ptr,
                                   (local_ird != NULL) ?
                                   local_ird : &stmt_block_ptr->ird,
                                   number_cols,
                                   tuple_ptr,
                                   tuple_size,
                                   CPR_INFO_OUTPUT );
            
        if (api_retcode != API_OK) {
            retcode = SQL_ERROR;
            pa41apmmker( API_SQLRUNTIME_9803, &dbc_block_ptr->esqblk );
            pa60PutError( hstmt, API_ODBC_S1000, &dbc_block_ptr->esqblk);
            pa12_SetRowstatus( rowstatus, SQL_ROW_ERROR );
            if (irow != 0)
                goto lock1_exit;
            else
                continue;
        }
      
        /* set absolute_pos or relative_pos, check Cursortype */
        /* set cursor position */  
        if (fOption != SQL_ADD) {
            if ( fCursorType != SQL_CURSOR_DYNAMIC
                 && ( fCursorType != SQL_CURSOR_KEYSET_DRIVEN
                      || stmt_block_ptr->stmtopt.optimize_cursor
                      == SQL_FALSE)) {
                /* fetch absolute */
                absolute_pos = stmt_block_ptr -> fetch_pos + (number_row-1);
                retcode = pa12FetchOneRow( env_block_ptr,
                                           dbc_block_ptr, 
                                           stmt_block_ptr,
                                           local_ard,
                                           local_ird,
                                           SQL_FETCH_ABSOLUTE,
                                           absolute_pos,
                                           rowst,
                                           hstmt );
            } else { /* DynamicCursor or optimized keyset driven cursor */
                /* fetch relative */
                relative_pos =
                    (SQLINTEGER) number_row - stmt_block_ptr->rowset_pos;
                retcode = pa12FetchOneRow( env_block_ptr,
                                           dbc_block_ptr, 
                                           stmt_block_ptr,
                                           local_ard,
                                           local_ird,
                                           SQL_FETCH_RELATIVE,
                                           relative_pos,
                                           rowst,
                                           hstmt );
            }; /* else */
            if ( (retcode == SQL_SUCCESS)
                 || (retcode == SQL_SUCCESS_WITH_INFO)){
                if ( (fOption == SQL_REFRESH) && (irow != 0)
                     && (fConcurrency != SQL_CONCUR_READ_ONLY))
                    retcode = pa12SelectOneRow( hstmt,
                                                local_ard,
                                                local_ird );
                /* if (fOption != SQL_DELETE) */
                stmt_block_ptr -> rowset_pos = (SQLUINTEGER) number_row;
                /* else
                   stmt_block_ptr -> rowset_pos = 1;
                */
            } else { 
                retcode = SQL_ERROR;
                pa12_SetRowstatus( rowstatus, SQL_ROW_ERROR );
                if (irow != 0) goto lock1_exit; else continue;
            }
        }
        /* --------------------------------------------------------- */
        /* ----- Execute SQL-statement for ADD, UPDATE, DELETE ----- */
        if ( (fOption==SQL_ADD)
             || (fOption==SQL_UPDATE)
             || (fOption==SQL_DELETE)) {
            sql_len = SqlStmt->cbLen;
             
                /* ***** first call SQLSetpos allocate new hstmt */
            retcode = pa12_AllocHstmtSetPos( hdbc,
                                             stmt_block_ptr,
                                             &stmtsp_block_ptr );
            if (retcode != SQL_SUCCESS) {
                /* alloc failed */
                goto lock1_exit;
            };
            hstmt_setpos = (SQLHSTMT) stmtsp_block_ptr;
        
                /* ***** set special flags */
            stmtsp_block_ptr -> dbc_special.special = API_SPEC_SQLSETPOS;
            if ((fOption == SQL_UPDATE) || (fOption == SQL_ADD)) {
                stmtsp_block_ptr -> rowset_pos = number_row; 
            } else {
                stmtsp_block_ptr -> rowset_pos = 0;
            };

            newStatement = false;
            /* See if we have to build a new statement. */
            /* delete statement is build above outside the for loop
                 * because it does not change */
            if ( (fOption == SQL_ADD
                  || fOption == SQL_UPDATE)
                 && (stmtsp_block_ptr -> stmt_function_code != act_fc_code
                     || pa60StmtChanged( &stmt_block_ptr->setPosSpecial,
                                         stmt_block_ptr->ardPtr,
                                         number_row ))) {
                tsp00_Int4 numParams = 0;   /* number of actual parameters ==
                                             * number of columns - ignored
                                             * columns */
                    /* build new sql-stmt because differnt columns are ignored
                     * or fOption changed or first call. */
                newStatement = true;
                if (pa12_BuildParamList( stmt_block_ptr->ardPtr,
                                         sqlda_ptr,
                                         number_row,
                                         paramList,
                                         paramListBufLen,
                                         &numParams ) != API_OK) {
                    /* possibly paramList buffer too small */
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt, API_ODBC_S1000, NULL);
                    goto lock1_exit;
                };
                if (numParams == 0 /* && fOption == SQL_UPDATE */) {
                    /* nothing to do because all columns are ignored */
                    pa12_SetRowstatus( rowstatus, SQL_ROW_ERROR );
                    retcode = SQL_ERROR;
                    /* Degree of derived table does not match column list */
                    pa60PutError( hstmt, API_ODBC_21S02, NULL);
                    if (irow != 0)
                        goto lock1_exit;
                    else
                        continue;
                };
                pa60RefreshSetPosSpecial( &stmt_block_ptr->setPosSpecial,
                                          stmt_block_ptr->ardPtr,
                                          number_row );
                pa12_BuildSqlStmt( fOption, SqlStmt, API_SQL_STRING_SWAG,
                                   stmt_block_ptr->table_name,
                                   paramList,
                                   stmt_block_ptr->cursor_name );
            }; /* if */
            if ( stmtsp_block_ptr -> stmt_function_code != act_fc_code
                 || newStatement) {
              if (SqlStmt->encodingType == sp77encodingAscii) {
                retcode = CALL_ODBC( SQLPrepare, (hstmt_setpos,
                                                  SqlStmt->rawString,
                                                  SqlStmt->cbLen));
              }
              else {
                retcode = CALL_ODBC( SQLPrepareW, (hstmt_setpos,
                                                   SqlStmt->rawString,
                                                   SqlStmt->cbLen / sp77encodingUCS2Native->fixedCharacterSize));
              }
                if ( (retcode != SQL_SUCCESS)
                     && (retcode != SQL_SUCCESS_WITH_INFO)) {
                    goto lock1_exit; 
                }
                if (fOption != SQL_DELETE) {
                    SQLUSMALLINT    paramNo = 1;

                    for (ipar=1; ipar <= number_cols; ipar++) {
                        ard_rec_ptr =
                            pa20GetRecord( stmt_block_ptr->ardPtr, ipar );
                        API_ASSERT_PTR( ard_rec_ptr );
                        /* skip columns with length SQL_IGNORE
                         * (PTS 1104910) */
                        if (!stmt_block_ptr
                            ->setPosSpecial.ignoredArray[ipar-1]) {
                            ird_rec_ptr =
                                pa20GetRecord( &stmt_block_ptr->ird,
                                               ipar );
                            API_ASSERT_PTR( ird_rec_ptr );
                            retcode =
                                CALL_ODBC(SQLBindParameter,
                                          (hstmt_setpos,
                                           paramNo,
                                           SQL_PARAM_INPUT,
                                           ard_rec_ptr->conciseType,
                                           ird_rec_ptr->type,
                                           ird_rec_ptr->esqPrecision,
                                           ird_rec_ptr->esqScale,
                                           PA20_DATA_PTR(ard_rec_ptr),
                                           ard_rec_ptr->length,
                                           PA20_OCTETLENGTH_PTR(ard_rec_ptr)));
                            if (retcode != SQL_SUCCESS) break;
                            paramNo++;
                        }; /* if */
                    }; /* for */
                    if ((retcode != SQL_SUCCESS) &&
                        (retcode != SQL_SUCCESS_WITH_INFO)) {
                        goto lock1_exit; 
                    }
                }; /* if */
            }; /* if */
            /* ***** Execute */
            /*
            if (irow == 0)
                pa60PutError( hstmt_setpos, API_ODBC_01S01, NULL);
                */
            retcode = CALL_ODBC(SQLExecute, (hstmt_setpos));
            if (retcode != SQL_SUCCESS) {
                if (irow == 0)
                    retcode = SQL_SUCCESS_WITH_INFO;
                if (retcode == SQL_NEED_DATA) { /* PTS 1104694 */
                    stmt_block_ptr->setPosNeedData = TRUE;
                } else {
                    pa12_SetRowstatus( rowstatus, SQL_ROW_ERROR );
                };
                if (irow != 0)
                    goto lock1_exit;
                else
                    continue;
            }; /* if */
        
            /* ***** check number of rows touched */
            if ( (fOption != SQL_ADD)
                 && (stmtsp_block_ptr->number_rows != 1)) {
                SQLUINTEGER odbcVersion = SQL_OV_ODBC3;    /* PTS 1111632 */

                pa10GetODBCVersion (SQL_HANDLE_STMT, hstmt, &odbcVersion);

                if (odbcVersion == SQL_OV_ODBC2) {
                    retcode = SQL_SUCCESS_WITH_INFO; 
                    if (stmtsp_block_ptr->number_rows == 0)
                        /* No rows updated or deleted */
                        pa60PutError( hstmt, API_ODBC_01S03, NULL );
                    else if (stmtsp_block_ptr->number_rows > 1)
                        /* More than one row updated or deleted */
                        pa60PutError( hstmt, API_ODBC_01S04, NULL );
                }
                else {
                    retcode = SQL_SUCCESS_WITH_INFO;
                    if (stmtsp_block_ptr->number_rows == 0 ||
                        stmtsp_block_ptr->number_rows >  1)
                        /* Cursor operation conflict */
                        pa60PutError( hstmt, API_ODBC_01001, NULL );
                }

                if (irow != 0)
                    goto lock1_exit;
                else
                    continue;
            }
        }
        /* -------------------------------------------------------- */
        /* ***** Set rgfRowStatus for rowset */
        switch (fOption) {
        case SQL_ADD        :
            pa12_SetRowstatus( rowstatus, SQL_ROW_ADDED );
            stmt_block_ptr -> number_rows += 1;
            if (hrowstat_set == API_TRUE) 
                rowstat_ptr->entry[stmt_block_ptr->number_rows-1].status
                    = SQL_ROW_ADDED;
            break;
        case SQL_UPDATE  :  
            pa12_SetRowstatus( rowstatus, SQL_ROW_UPDATED );
            if (hrowstat_set == API_TRUE) 
                rowstat_ptr->entry[absolute_pos-1].status
                    = SQL_ROW_UPDATED;
            break;
        case SQL_DELETE  : 
            pa12_SetRowstatus( rowstatus, SQL_ROW_DELETED );
            if (hrowstat_set == API_TRUE) 
                rowstat_ptr->entry[absolute_pos-1].status
                    = SQL_ROW_DELETED;
            break;
        }   
    } /* for() */
    /* ----------------------------------------------------------- */
 lock1_exit:
    if (stmt_block_ptr->ird.header.rowsProcessedPtr != NULL) {
        *stmt_block_ptr->ird.header.rowsProcessedPtr =
            (SQLUINTEGER) stmt_block_ptr->number_rows;
    }; /* if */        
    if (local_ard != NULL) { 
        pa20FreeCopiedDesc( local_ard );
    }
    if (local_ird != NULL) { 
        pa20FreeCopiedDesc( local_ird );
    }
 error_exit:  
    pr05IfCom_String_DeleteString (SqlStmt);

    PA09LEAVEASYNCFUNCTION();
    if(paramList) {
        apdfree(paramList);
    }

    /* ---------------------------------------------------------------- */
    API_TRACE(API_TR_EXIT, PA12_FN_SQLSETPOS, 0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);
} /* SQLSetPos */


ODBC_PROC(SQLSetScrollOptions, ( SQLHSTMT     hstmt,
                                 SQLUSMALLINT fConcurrency,
                                 SQLLEN       crowKeyset,
                                 SQLUSMALLINT crowRowset),
          (hstmt, fConcurrency, crowKeyset, crowRowset))
{
    RETCODE      retcode;
    API_RETCODE  api_retcode;
    SQLUINTEGER  old_fConcurrency;             /* PTS 1110704 */
    SQLUINTEGER  old_crowKeyset;               /* PTS 1110704 */
    SQLUINTEGER  local_crowKeyset;             /* PTS 1110704 */
    SQLUINTEGER  old_crowRowset;               /* PTS 1110704 */
    SQLUSMALLINT        state;
    tpa60Stmt   *stmt_block_ptr;

    API_TRACE(API_TR_ENTRY, PA12_FN_SQLSETSCROLLOPTIONS, 0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE(API_TR_UWORD,"fConcurrency",&fConcurrency);
    API_TRACE(API_TR_SDWORD,"crowKeyset",&crowKeyset);
    API_TRACE(API_TR_UWORD,"crowRowset",&crowRowset);

    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLSETSCROLLOPTIONS);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    else {   
        /* ---------------------------------------------------------- */
        /* ----- Check hstmt ----- */
        if (pa60VerifyStmt( hstmt ) != API_OK) { /* hstmt valid ? */
            retcode = SQL_INVALID_HANDLE;
            goto error_exit;
        }
        else {
        /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1124531 */
            state = ((tpa60Stmt*) hstmt)->state;
            if (state != API_STMT_ALLOCATED) {
                /* function sequence error */
                pa60PutError( hstmt, 
                              API_ODBC_S1010, NULL);
                retcode = SQL_ERROR; 
                goto error_exit;
            }
        }
        /* --------------------------------------------------------- */
        /* ----- Check fConcurrency ----- */
        if ((fConcurrency != SQL_CONCUR_READ_ONLY) && 
            (fConcurrency != SQL_CONCUR_LOCK) && 
            (fConcurrency != SQL_CONCUR_ROWVER) &&
            (fConcurrency != SQL_CONCUR_VALUES)) {
            /* Concurrency option out of range */
            pa60PutError( hstmt, API_ODBC_S1108, NULL );
            retcode = SQL_ERROR; 
            goto error_exit;
        }
        /* -------------------------------------------------------- */
        /* ----- Check crowKeyset and crowRowset----- */
        if (((crowKeyset != SQL_SCROLL_FORWARD_ONLY) &&
             (crowKeyset != SQL_SCROLL_STATIC) &&
             (crowKeyset != SQL_SCROLL_KEYSET_DRIVEN) &&
             (crowKeyset != SQL_SCROLL_DYNAMIC)) ||
            (crowRowset == 0)) {
            /* Concurrency option out of range */
            pa60PutError( hstmt, 
                          API_ODBC_S1107, NULL);
            retcode = SQL_ERROR; 
            goto error_exit;   
        }
        /* -------------------------------------------------------- */
        retcode = SQL_SUCCESS;
     
        stmt_block_ptr = (tpa60Stmt *) apdlock(hstmt);
        API_ASSERT_PTR(stmt_block_ptr);
    
        /* ----- Get old parameter StmtOption ----- */
        CALL_ODBC(SQLGetStmtAttr,(hstmt,
                                  SQL_CONCURRENCY,
                                  &old_fConcurrency, 0,NULL));
        CALL_ODBC(SQLGetStmtAttr,( hstmt,
                                   SQL_CURSOR_TYPE,
                                   &old_crowKeyset,
                                   0, NULL));
        CALL_ODBC(SQLGetStmtAttr,( hstmt,
                                   SQL_ROWSET_SIZE,
                                   &old_crowRowset,
                                   0, NULL));

        /* ----- Set new parameter in StmtOption ----- */
        /* ***** fConcurrency */
        retcode = CALL_ODBC(SQLSetStmtAttr, (hstmt,
                                             SQL_CONCURRENCY,
                                             SQLPOINTER_CAST (fConcurrency),
                                             0));
        /* ***** crowKeyset */
        if (retcode == SQL_SUCCESS) {
            switch (crowKeyset) {
            case SQL_SCROLL_FORWARD_ONLY: 
                local_crowKeyset = SQL_CURSOR_FORWARD_ONLY;            
                break;  
            case SQL_SCROLL_STATIC : 
                local_crowKeyset = SQL_CURSOR_STATIC;              
                break;
            case SQL_SCROLL_KEYSET_DRIVEN : 
                local_crowKeyset = SQL_CURSOR_KEYSET_DRIVEN;               
                break;
            case SQL_SCROLL_DYNAMIC : 
                local_crowKeyset = SQL_CURSOR_DYNAMIC;
                break;
            default : 
                local_crowKeyset = SQL_CURSOR_TYPE_DEFAULT;
            }
            retcode = CALL_ODBC(SQLSetStmtAttr, (hstmt,
                                                 SQL_CURSOR_TYPE,
                                                 SQLPOINTER_CAST (local_crowKeyset),
                                                 0));
        }
        /* ***** crowRowset */
        if (retcode == SQL_SUCCESS) 
            retcode = CALL_ODBC(SQLSetStmtAttr, (hstmt,
                                                 SQL_ROWSET_SIZE,
                                                 SQLPOINTER_CAST (crowRowset),
                                                 0));

        /* ----- Set old parameter in StmtOption ----- */
        if (retcode != SQL_SUCCESS) {
            CALL_ODBC(SQLSetStmtAttr, ( hstmt,
                                        SQL_CONCURRENCY,
                                        SQLPOINTER_CAST (old_fConcurrency),
                                        0));
            CALL_ODBC(SQLSetStmtAttr, ( hstmt,
                                        SQL_CURSOR_TYPE,
                                        SQLPOINTER_CAST (old_crowKeyset),
                                        0));
            CALL_ODBC(SQLSetStmtAttr, ( hstmt,
                                        SQL_ROWSET_SIZE,
                                        SQLPOINTER_CAST (old_crowRowset),
                                        0));
        }
    }
    /* ------------------------------------------------------------- */
error_exit:  
    API_TRACE(API_TR_EXIT, PA12_FN_SQLSETSCROLLOPTIONS, 0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);   
} /* SQLScrollOptions */

#endif  /* of _UNICODE_ODBC */


typedef struct {
   tpr05_String    *tpriv_qualifier;
   tpr05_String    *tpriv_owner;
   tpr05_String    *tpriv_name;
} pa11SQLTablePrivileges;


#ifdef _UNICODE_ODBC
ODBC_PROC(SQLTablePrivilegesW,(SQLHSTMT     hstmt,
                               SQLWCHAR    *szTableQualifier,
                               SQLSMALLINT  cbTableQualifier,
                               SQLWCHAR    *szTableOwner,
                               SQLSMALLINT  cbTableOwner,
                               SQLWCHAR    *szTableName,
                               SQLSMALLINT  cbTableName ),
          ( hstmt, szTableQualifier, cbTableQualifier, szTableOwner,
            cbTableOwner, szTableName, cbTableName))
#else
ODBC_PROC(SQLTablePrivileges, (SQLHSTMT     hstmt,
                               SQLCHAR     *szTableQualifier,
                               SQLSMALLINT  cbTableQualifier,
                               SQLCHAR     *szTableOwner,
                               SQLSMALLINT  cbTableOwner,
                               SQLCHAR     *szTableName,
                               SQLSMALLINT  cbTableName ),
          ( hstmt, szTableQualifier, cbTableQualifier, szTableOwner,
            cbTableOwner, szTableName, cbTableName))
#endif
{
    RETCODE retcode=SQL_SUCCESS;
    API_RETCODE api_retcode;
    /* --------------------------------------------------------------- */
    SQLUSMALLINT         state;

    pa11SQLTablePrivileges LV;
    tpa60Stmt * stmt_block_ptr;
    SQLHDBC hdbc;
    tpa40DBC * dbc_block_ptr;
    SQLHENV henv;
    tpa50Env * env_block_ptr;
    SQLUINTEGER odbcVersion;
    char       *selectTablePrivileges;
    const char *tableprefix;
#ifdef _UNICODE_ODBC
    const tsp77encoding *encodingType = sp77nativeUnicodeEncoding ();
    SQLCHAR      sqlString [(API_USERID_MAX_LEN*2 + API_TABLE_NAME_MAX*2 + 
                             sizeof (PA12SELECTTABLEPRIVILEGES_OV3) + 60)
                           * sizeof (tsp81_UCS2Char)];
#else
    const tsp77encoding *encodingType = sp77encodingAscii;
    SQLCHAR      sqlString [(API_USERID_MAX_LEN*2 + API_TABLE_NAME_MAX*2 + 
                             sizeof (PA12SELECTTABLEPRIVILEGES_OV3) + 60)];
#endif   
    const int charSize = encodingType->fixedCharacterSize;
    SQLINTEGER sqlLen;
    /* -------------------------------------------------------------- */

    API_TRACE(API_TR_ENTRY, PA12_FN_SQLTABLEPRIVILEGES, 0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szTableQualifier",
                  szTableQualifier, cbTableQualifier);
    API_TRACE(API_TR_SWORD,"cbTableQualifier",&cbTableQualifier);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szTableOwner",
                  szTableOwner, cbTableOwner);
    API_TRACE(API_TR_SWORD,"cbTableOwner",&cbTableOwner);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szTableName",
                  szTableName, cbTableName);
    API_TRACE(API_TR_SWORD,"cbTableName",&cbTableName);

    LV.tpriv_qualifier = LV.tpriv_owner = LV.tpriv_name = NULL;
    
    if (cbTableQualifier != SQL_NTS)
      cbTableQualifier *= charSize;
    if (cbTableOwner != SQL_NTS)
      cbTableOwner *= charSize;
    if (cbTableName != SQL_NTS)
      cbTableName *= charSize;
    /* -------------------------------------------------------------- */
    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLTABLEPRIVILEGES);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    /* -------------------------------------------------------------- */
    else {
        if (pa60VerifyStmt( hstmt ) != API_OK) {        /* hstmt valid ? */
            retcode = SQL_INVALID_HANDLE;
        }
        else {
            /* determine which ODBC version the application wants */
            if (!pa10GetODBCVersion( SQL_HANDLE_STMT, hstmt,
                                     &odbcVersion )) {
                retcode = SQL_ERROR;
                /* general error */
                pa60PutError( hstmt, API_ODBC_S1000, NULL);
                goto exit_1_lock;                    
            }; /* if */
            apmlocp(&hstmt, &stmt_block_ptr, &hdbc, &dbc_block_ptr, 
                    &henv, &env_block_ptr);
            state = ((tpa60Stmt*) hstmt)->state;
            tableprefix = pa12_getTablePrefix (dbc_block_ptr);
            /* ODBC version 3.0 defines different column-names */
            if (odbcVersion == SQL_OV_ODBC3) {
                selectTablePrivileges = (char *) alloca (strlen(PA12SELECTTABLEPRIVILEGES_OV3) + 30);
                sprintf (selectTablePrivileges, PA12SELECTTABLEPRIVILEGES_OV3, tableprefix);
            } else { /* version < 3.x */
                selectTablePrivileges = (char *) alloca (strlen(PA12SELECTTABLEPRIVILEGES) + 30);
                sprintf (selectTablePrivileges, PA12SELECTTABLEPRIVILEGES, tableprefix);
            }; /* else */
            PA09ENTERASYNCFUNCTION(dbc_block_ptr, stmt_block_ptr);
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, NULL)) { 
                if (pa09IsConnectionBusy(stmt_block_ptr, dbc_block_ptr)) {
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt, API_ODBC_S1010, NULL);
                    goto exit_1_lock;
                }   
                if (state == API_STMT_POSITIONED) {
                    /* function seqeunces error */
                    retcode = SQL_ERROR;            /* SQLSTATE: 24000 */
                    pa60PutError( hstmt, API_ODBC_24000, NULL);
                    goto exit_1_lock;
                }

                /* --------------------------------------------------- */
                /* create strings */
                LV.tpriv_qualifier = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1),
                                                             encodingType);
                LV.tpriv_owner     = 
                  pr05IfCom_String_NewDynString (charSize * ((API_USERID_MAX_LEN*2)+1),
                                                 encodingType);
                LV.tpriv_name      = 
                  pr05IfCom_String_NewDynString (charSize * ((API_TABLE_NAME_MAX*2)+1),
                                                 encodingType);

                if (LV.tpriv_qualifier == NULL || LV.tpriv_owner == NULL || 
                    LV.tpriv_name     == NULL) {
                  retcode = SQL_ERROR;            
                  pa60PutError( hstmt, API_ODBC_S1001, NULL);
                  goto exit_1_lock;
                }

                /* ***** szTableQualifier */
                if (szTableQualifier == NULL) {
/*                     API_STRCPY( (UCHAR*) LV.tpriv_qualifier->rawString, (UCHAR*) ""); */
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.tpriv_qualifier,
                                                   encodingType,
                                                   szTableQualifier,
                                                   cbTableQualifier);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                /* ***** szTableOwner */
                if (szTableOwner == NULL) {
                  pr05IfCom_String_strcatP (LV.tpriv_owner, "%",
                                            (tsp00_Uint4) API_STRLEN ("%"),
                                            sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.tpriv_owner,
                                                   encodingType,
                                                   szTableOwner,
                                                   cbTableOwner);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                /* ***** szTableName */
                if (szTableName == NULL) {
                  pr05IfCom_String_strcatP (LV.tpriv_name, "%",
                                            (tsp00_Uint4) API_STRLEN ("%"),
                                            sp77encodingAscii);
                }
                else {
                    api_retcode = pa80ODBCtoTpr05 (LV.tpriv_name,
                                                   encodingType,
                                                   szTableName,
                                                   cbTableName);
                    if (api_retcode != API_OK) {
                        retcode = SQL_ERROR;
                        pa60PutError( hstmt, API_ODBC_S1090, NULL);
                        goto exit_1_lock;
                    }
                }
                stmt_block_ptr -> dbc_special.special =
                    API_SPEC_SQLTABLEPRIVILEGES;
                if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                    /* store the local stack to restore get the values
                     * in async call */
                    pa09SaveStack( &stmt_block_ptr->async.hLocalValues, &LV, sizeof(LV));
                    pa09PrepareAsyncCall( hstmt, SQL_API_SQLTABLEPRIVILEGES);
                }
            } /* async exec */
            if (pa09IsAsync(stmt_block_ptr, dbc_block_ptr, &retcode)) {
                pa09ExecuteAsyncCall(hstmt);
                goto exit_async;
            }
            else {
                /* restore the stack values from async caller */
                if (stmt_block_ptr->async.hLocalValues) {
                    pa09RestoreStack(stmt_block_ptr->async.hLocalValues, &LV);
                    apdfree(stmt_block_ptr->async.hLocalValues);
                    stmt_block_ptr->async.hLocalValues = API_NULL_HANDLE;
                }
            }
            /* -------------------------------------------------------- */
            /* SQL-Statement length */

            /* ---------------------------------------------------- */
            /* SQLTablePrivileges */
            sqlLen = sp77sprintfUnicode (encodingType,
                                         sqlString, sizeof (sqlString),
                                         (char*) selectTablePrivileges,
                                         LV.tpriv_owner->encodingType,
                                         LV.tpriv_owner->cbLen,
                                         LV.tpriv_owner->rawString,
                                         API_ESCAPE_CHAR,
                                         LV.tpriv_name->encodingType,
                                         LV.tpriv_name->cbLen,
                                         LV.tpriv_name->rawString,
                                         API_ESCAPE_CHAR);
            /* ----------------------------------------------------- */
#ifdef _UNICODE_ODBC
            retcode = CALL_ODBC(SQLPrepareW, (hstmt, (SQLWCHAR*) sqlString, 
                                              sqlLen / charSize));
#else
            retcode = CALL_ODBC(SQLPrepare, (hstmt, sqlString, sqlLen));
#endif
            if (retcode == SQL_SUCCESS) {
              retcode = CALL_ODBC(SQLExecute, (hstmt));
            }
        exit_1_lock:
            pr05IfCom_String_DeleteString (LV.tpriv_qualifier);
            pr05IfCom_String_DeleteString (LV.tpriv_owner);
            pr05IfCom_String_DeleteString (LV.tpriv_name);
        exit_async:
            PA09LEAVEASYNCFUNCTION();
        }  /* start processing */
    } /* set odbc_funtion */ 
    API_TRACE(API_TR_EXIT, PA12_FN_SQLTABLEPRIVILEGES,0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);

    return(retcode);
} /* SQLTablePrivileges */


#ifndef _UNICODE_ODBC

/******************************************************************/
/* local functions */
/******************************************************************/

SQLRETURN pa12_AllocHstmtSetPos( SQLHDBC     hdbc,
                                 tpa60Stmt  *stmtPtr,
                                 tpa60Stmt **stmtSetPos )
{
    SQLRETURN retcode = SQL_SUCCESS;
    
    /* ***** first call SQLSetpos allocate new hstmt */
    if (stmtPtr->hstmt_setpos == SQL_NULL_HSTMT) {
        retcode = pa60AllocStmt( hdbc, &stmtPtr->hstmt_setpos );
        if (retcode != SQL_SUCCESS) {
            /* Memory allocation failure */
            retcode = SQL_ERROR;
            pa60PutError( (SQLHSTMT) stmtPtr, API_ODBC_S1001, NULL );
        } else {
            *stmtSetPos = (tpa60Stmt*) stmtPtr->hstmt_setpos;
            (*stmtSetPos)->hstmt_parent = (SQLHSTMT) stmtPtr;
            /* diag-area is shared */
            pa30FreeDiagArea( (*stmtSetPos)->diagArea );
            pa30DeleteDiagArea( (*stmtSetPos)->diagArea );
            apdfree( (*stmtSetPos)->diagArea );
            (*stmtSetPos)->diagArea = stmtPtr->diagArea;
        }; /* else */
    } else {
        *stmtSetPos = (tpa60Stmt*) stmtPtr->hstmt_setpos;
    }; /* else */

    return retcode;
} /* pa12_AllocHstmtSetPos */


SQLRETURN pa12_CheckSetPosArguments( tpa60Stmt    *stmtPtr,
                                     SQLROWOFFSET  irow,
                                     SQLUSMALLINT  fOption,
                                     SQLUSMALLINT  fLock)
{
    SQLRETURN    retcode     = SQL_SUCCESS;
    SQLHSTMT     hstmt       = (SQLHSTMT) stmtPtr;
    SQLUSMALLINT state       = stmtPtr->state;
    SQLUINTEGER  rowset_size = stmtPtr->ardPtr->header.arraySize;
    SQLUINTEGER  fConcurrency;
    SQLINTEGER   fCursorType;
    
    /* with SQL_ADD we do not have to be positioned PTS 1104694 */
    if (state == API_STMT_EXECUTED && fOption != SQL_ADD) {
        retcode = SQL_ERROR;            /* SQLSTATE: 24000 */
        pa60PutError( hstmt, API_ODBC_24000, NULL);
        /* function sequence error */
        goto error_exit;
    }
    if (state != API_STMT_POSITIONED && fOption != SQL_ADD) {
        /* function sequence error */
        pa60PutError( hstmt, API_ODBC_S1010, NULL );
        retcode = SQL_ERROR; 
        goto error_exit;
    }
    /* ------------------------------------------------------------ */
    /* ----- Check fOption, fLock ----- */
    if ( ((fOption != SQL_POSITION) && (fOption != SQL_REFRESH)
          && (fOption != SQL_UPDATE) && (fOption != SQL_DELETE)
          && (fOption != SQL_ADD))
         || ((fLock != SQL_LOCK_NO_CHANGE) && (fLock != SQL_LOCK_EXCLUSIVE)
             && (fLock != SQL_LOCK_UNLOCK)) ) {
        /* Invalid argument values */
        pa60PutError( hstmt, API_ODBC_S1009, NULL );
        retcode = SQL_ERROR; 
        goto error_exit;
    }
    if ((fLock == SQL_LOCK_EXCLUSIVE) || (fLock == SQL_LOCK_UNLOCK)) {
        /* Driver not capable */
        pa60PutError( hstmt, API_ODBC_S1C00, NULL );
        retcode = SQL_ERROR; 
        goto error_exit;
    }    
    /* ------------------------------------------------------------ */
    /* ----- Check read only and forward only ----- */
    /* ----- Get old parameter StmtOption ----- */
    CALL_ODBC(SQLGetStmtAttr, ( hstmt,
                                SQL_CONCURRENCY,
                                &fConcurrency,
                                0, NULL));
    CALL_ODBC(SQLGetStmtAttr, ( hstmt,
                                SQL_CURSOR_TYPE,
                                &fCursorType,
                                0, NULL));
    
    /* check SQL_CONCUR_READ_ONLY with SQL_UPDATE, SQL_ADD_ SQL_DELETE */
    if ((fConcurrency == SQL_CONCUR_READ_ONLY)
        && ((fOption == SQL_UPDATE)
            || (fOption == SQL_DELETE)
            || (fOption == SQL_ADD))) {
        /* Invalid argument values */
        pa60PutError( hstmt, API_ODBC_S1009, NULL );
        retcode = SQL_ERROR; 
        goto error_exit;
    }
    /* check SQL_CURSOR_KEYSET_DRIVEN, SQL_CURSOR_FORWORD_ONLY with
     * SQL_ADD*/
    if ((fOption == SQL_ADD)
        && ((fCursorType == SQL_CURSOR_FORWARD_ONLY))) {
        /* Driver not capable */
        pa60PutError( hstmt, API_ODBC_S1C00, NULL );
        retcode = SQL_ERROR; 
            goto error_exit;       
    }    
    /* check SQL_CURCOR_STATIC with SQL_UPDATE */
#if 0        
    if ((fCursorType == SQL_CURSOR_STATIC) && (fOption == SQL_UPDATE)) {
        /* Driver not capable */
        pa60PutError( hstmt, API_ODBC_S1C00, NULL );
        retcode = SQL_ERROR; 
        goto error_exit;       
    }
#endif        
    /* ------------------------------------------------------------ */
    /* ----- Check irow ----- */
    if (irow > 0 && (SQLUINTEGER) irow > rowset_size) {
        if ((fOption == SQL_ADD) && ((SQLUINTEGER) irow <= rowset_size+1))
            retcode = SQL_SUCCESS; 
        else {
            /* Row value out of range */
            retcode = SQL_ERROR;       
            pa60PutError( hstmt, API_ODBC_S1107, NULL );
            goto error_exit;
        }
    }
    if ((irow == 0) && ((fOption == SQL_POSITION) || 
                        (fCursorType == SQL_CURSOR_FORWARD_ONLY))) {
        retcode = SQL_SUCCESS_WITH_INFO;  
        /* SQLSTATE: 01S01 , Error in irow */
        pa60PutError( hstmt, API_ODBC_01S01, NULL);
        goto error_exit;
    }
    /* ----------------------------------------------------------- */

 error_exit:
    
    return retcode;
} /* pa12_CheckSetPosArguments */


API_RETCODE pa12_BuildParamList( tpa20Desc   *ardPtr,
                                 sqldatype   *sqldaPtr,
                                 SQLUINTEGER  rowsetPos,
                                 UCHAR       *stringBuf,
                                 tsp00_Int4   bufLen,
                                 tsp00_Int4  *numParams )
{
    API_RETCODE      apiRetcode = API_OK;
    tpa21DescRecord *ardRecPtr = NULL;
    SQLLEN          *octetLengthPtr = NULL;
    tsp00_Bool       firstColumn = true;
    SQLUSMALLINT     iCol    = 0;
    tsp00_Int4       nameLen = 0;
    tsp00_Int4       restLen = bufLen;
    tsp00_Int4       i       = 0;
    
    *numParams = 0;
    stringBuf[0] = '\0';
    for (iCol = 1; iCol <= ardPtr->count; iCol++) {
        if (restLen < 4) {
            /* not enough space for another column */
            apiRetcode = API_NOT_OK;
            break;
        };
        ardRecPtr = pa20GetRecord( ardPtr, iCol );
        API_ASSERT_PTR( ardRecPtr );
        octetLengthPtr = PA20_OCTETLENGTH_PTR(ardRecPtr);
        /* skip columns with length SQL_IGNORE PTS 1104910.
         * In pa20PutDesc these are also skipped. So the parameters
         * do match. */
        if (octetLengthPtr == NULL
            || *(octetLengthPtr+rowsetPos-1) != SQL_IGNORE) {
            if (firstColumn) {
                firstColumn = false;
            } else {
                API_STRCAT( stringBuf, ",");
                restLen--;
            };
            API_STRCAT( stringBuf, "\"");
            restLen--;
            nameLen = (tsp00_Int4) API_STRLEN( sqldaPtr -> sqlvar[iCol - 1].colname );
            if (nameLen+4 > restLen) {
                /* stringBuf is too small */
                apiRetcode = API_NOT_OK;
                break;
            };
            restLen -= nameLen;
            API_STRCAT( stringBuf, sqldaPtr -> sqlvar[iCol - 1].colname);
            /* remove trailung spaces */
            for ( i = bufLen-restLen-2; i >= 0; i--) {
                if (stringBuf[i] != ' ') {
                    stringBuf[i+1] = '\0';
                    restLen = bufLen-i-1;
                    break;
                };
            }; /* for */
            restLen -= 3;
            API_STRCAT( stringBuf, "\"");
            API_STRCAT( stringBuf, "=");
            API_STRCAT( stringBuf, "?");
            (*numParams)++;
        }; /* if */
    }; /* for */

    return apiRetcode;
} /* pa12_BuildParamList */


API_RETCODE pa12_BuildSqlStmt( SQLUSMALLINT  fOption,
                               tpr05_String *SqlStmt,
                               tsp00_Int4    bufLen,
                               tpr05_String *tableName,
                               UCHAR        *paramList,
                               tpr05_String *cursorName )
{
    switch (fOption) {
    case SQL_ADD        :
      SqlStmt->cbLen = 
        sp77sprintfUnicode (SqlStmt->encodingType,
                            SqlStmt->rawString, SqlStmt->cbMaxLen,
                            PA12ADDSETPOS, 
                            tableName->encodingType,
                            tableName->cbLen,
                            tableName->rawString,
                            paramList);
      /*        API_SPRINTF( (char*) sqlBuf,
                     (char*) PA12ADDSETPOS, 
                     tableName, paramList );*/
        break;
    case SQL_UPDATE  :  
      SqlStmt->cbLen = 
        sp77sprintfUnicode (SqlStmt->encodingType,
                            SqlStmt->rawString, SqlStmt->cbMaxLen,
                            PA12UPDSETPOS, 
                            tableName->encodingType,
                            tableName->cbLen,
                            tableName->rawString,
                            paramList,
                            cursorName->encodingType,
                            cursorName->cbLen,
                            cursorName->rawString);
      /*        API_SPRINTF( (char*) sqlBuf,
                     (char*) PA12UPDSETPOS, 
                     tableName, paramList, cursorName);*/
        break;
    case SQL_DELETE  : 
      SqlStmt->cbLen = 
        sp77sprintfUnicode (SqlStmt->encodingType,
                            SqlStmt->rawString, SqlStmt->cbMaxLen,
                            PA12DELSETPOS, 
                            tableName->encodingType,
                            tableName->cbLen,
                            tableName->rawString,
                            cursorName->encodingType,
                            cursorName->cbLen,
                            cursorName->rawString);
      /*        API_SPRINTF( (char*) sqlBuf,
                     (char*) PA12DELSETPOS, 
                     tableName, cursorName);*/
    default:
        break;
    }; /* switch */

    return API_OK;
} /* pa12_BuildSqlStmt */


VOID pa12_SetRowstatus( SQLUSMALLINT *statPtr, SQLUSMALLINT status )
{
    if (statPtr != NULL) {
        *statPtr = status;
    };
} /* pa12_SetRowStatus */

#endif

.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
