.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$VPA11AC$
.tt 2 $$$
.TT 3 $BurkhardD$LEVEL 1 FUNCTIONS A - N$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-06-06
.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 64 "vpa11ac"
#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"

API_RETCODE pa08GetDSNOptions( tpa40DBC FAR * dbc_ptr,
                               UCHAR FAR *szProfileStr );

API_RETCODE apegetl ( tpa41ESQBlock FAR * api_cb_ptr,
                      tpa40DBC FAR * api_dbc_ptr,
                      tpa60Stmt FAR * api_stmt_ptr,
                      tpa20Desc *impl_desc_ptr,
                      SWORD *col);

void pa11_GetTotalLength (tpa60Stmt *stmt_block_ptr,
                          SQLUSMALLINT icol,
                          SQLLEN *len);

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

extern SDWORD pa07blockmodus;

#ifndef SAPDB_FAST
#ifndef _UNICODE_ODBC
UCHAR FAR *PA11_FN_SQLBINDPARAMETER = { (UCHAR*) "SQLBindParameter" };
UCHAR FAR *PA11_FN_SQLCOLUMNS = { (UCHAR*) "SQLColumns" };
UCHAR FAR *PA11_FN_SQLGETDATA = { (UCHAR*) "SQLGetData" };
UCHAR FAR *PA11_FN_SQLGETTYPEINFO = { (UCHAR*) "SQLGetTypeInfo" };
#else
extern UCHAR  *PA11_FN_SQLBINDPARAMETER;
extern UCHAR  *PA11_FN_SQLCOLUMNS;
extern UCHAR  *PA11_FN_SQLGETDATA;
extern UCHAR  *PA11_FN_SQLGETTYPEINFO;
#endif
#endif

#ifndef _UNICODE_ODBC
/* ------------------------------------------------------------------------ */
/* SQLColumns */
const char  *PA11SELECTCOLUMNS = 
"SELECT TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE, \
TYPE_NAME, PRECISION, LENGTH, SCALE, RADIX, NULLABLE, REMARKS, POS, CODETYPE \
FROM %sCOLUMNS WHERE TABLE_OWNER %s '%'=.*S' %s  AND \ 
TABLE_NAME %s '%'=.*S' %s AND COLUMN_NAME %s '%'=.*S' %s  \
ORDER BY 2, 3, 13";

/* ODBC 3.x has different column names and some additional columns */
const char  *PA11SELECTCOLUMNS_ODBC35 = 
"SELECT TABLE_QUALIFIER TABLE_CAT, TABLE_OWNER TABLE_SCHEM, TABLE_NAME, \
COLUMN_NAME, DATA_TYPE, \
TYPE_NAME, PRECISION COLUMN_SIZE, LENGTH BUFFER_LENGTH, \
SCALE DECIMAL_DIGITS, RADIX NUM_PREC_RADIX, NULLABLE, REMARKS, \
%s, DATA_TYPE SQL_DATA_TYPE, \
NULL SQL_DATETIME_SUB, \
PRECISION CHAR_OCTET_LENGTH, POS ORDINAL_POSITION, \
DECODE(NULLABLE,1,\'YES\',0,\'NO\',\'NO\') IS_NULLABLE, \
CODETYPE \
FROM %sCOLUMNS WHERE TABLE_OWNER %s '%'=.*S' %s AND \ 
TABLE_NAME %s '%'=.*S' %s AND COLUMN_NAME %s '%'=.*S' %s \
ORDER BY 2, 3, 17";
/* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1141626 */

/* ------------------------------------------------------------------------ */
/* SQLGetTypeInfo */
const char  *PA11SELECTCOLTYPES = 
"SELECT TYPE_NAME, DATA_TYPE, PRECISION, LITERAL_PREFIX, LITERAL_SUFFIX, \
CREATE_PARAMS, NULLABLE, CASE_SENSITIVE, SEARCHABLE, UNSIGNED_ATTRIBUTE, \
MONEY, AUTO_INCREMENT, LOCAL_TYPE_NAME, MINIMUM_SCALE, \
MAXIMUM_SCALE \
FROM %sTYPES ";

/* ODBC 3.x has different column names */
const char  *PA11SELECTCOLTYPES_ODBC35 = 
"SELECT TYPE_NAME, decode (DATA_TYPE, \
%d, %d, %d, %d, %d, %d, \
DATA_TYPE) DATA_TYPE, PRECISION COLUMN_SIZE, LITERAL_PREFIX, \
LITERAL_SUFFIX, \
decode (CREATE_PARAMS, 'max length', 'length', CREATE_PARAMS) CREATE_PARAMS, \
NULLABLE, CASE_SENSITIVE, SEARCHABLE, UNSIGNED_ATTRIBUTE, \
MONEY FIXED_PREC_SCALE, AUTO_INCREMENT AUTO_UNIQUE_VALUE, LOCAL_TYPE_NAME, \
MINIMUM_SCALE, \
MAXIMUM_SCALE, SQL_DATA_TYPE, SQL_DATETIME_SUB, NUM_PREC_RADIX, \
INTERVAL_PRECISION \
FROM %sTYPES ";
#else
extern const char  *PA11SELECTCOLUMNS;
extern const char  *PA11SELECTCOLUMNS_ODBC35;
extern const char  *PA11SELECTCOLTYPES;
extern const char  *PA11SELECTCOLTYPES_ODBC35;
#endif

#ifndef _UNICODE_ODBC
ODBC_PROC(SQLBindParameter,( SQLHSTMT      hstmt,
                             SQLUSMALLINT  ipar,
                             SQLSMALLINT   fParamType,
                             SQLSMALLINT   fCType,
                             SQLSMALLINT   fSqlType,
                             SQLULEN       cbColDef,
                             SQLSMALLINT   ibScale,
                             SQLPOINTER    rgbValue,
                             SQLLEN        cbValueMax,
                             SQLLEN       *pcbValue),
          (hstmt,
           ipar,
           fParamType,
           fCType,
           fSqlType,
           cbColDef,
           ibScale,
           rgbValue,
           cbValueMax,
           pcbValue))
{
    RETCODE      retcode;
    API_RETCODE  api_retcode;
    UWORD        state;
    tpa60Stmt   *stmt_block_ptr;
    UWORD        allocated_input_attr;
    UWORD        type;
    SWORD        real_c_type;
    SQLHSTMT     hstmt_setpos;
    tpa21DescRecord *appl_rec_ptr;
    tpa21DescRecord *impl_rec_ptr;
    
    API_TRACE(API_TR_ENTRY,PA11_FN_SQLBINDPARAMETER,0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE(API_TR_UWORD,"ipar",&ipar);
    API_TRACE(API_TR_SWORD,"fParamType",&fParamType);
    API_TRACE(API_TR_SWORD,"fCType",&fCType);
    API_TRACE(API_TR_SWORD,"fSqlType",&fSqlType);
    API_TRACE(API_TR_UDWORD,"cbColDef",&cbColDef);
    API_TRACE(API_TR_SWORD,"ibScale", &ibScale);
    API_TRACE(API_TR_PTR,"rgbValue",&rgbValue);
    API_TRACE(API_TR_SDWORD,"cbValueMax",&cbValueMax);
    API_TRACE(API_TR_PTR,"pcbValue",&pcbValue);

    retcode = SQL_SUCCESS;

    api_retcode = apmstfc( SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                           SQL_API_SQLBINDPARAMETER);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    else { 
        if (pa60VerifyStmt( hstmt ) != API_OK) { /* hstmt valid? */
            retcode = SQL_INVALID_HANDLE;
        }
        else {
            stmt_block_ptr = (tpa60Stmt*) hstmt;
            API_ASSERT_PTR(stmt_block_ptr);
            state = stmt_block_ptr->state;
            hstmt_setpos = stmt_block_ptr -> hstmt_setpos;
            /*
              number_parms = stmt_block_ptr -> number_parms;
              */
            /* verify function sequence        */
            /* only necessary for asynch. exec.*/

            /* check SQL-format type           */
            /* must be changed for ext.data typ*/
            if ((fSqlType < SQL_CHAR || fSqlType > SQL_VARCHAR) &&
                fSqlType < SQL_BIT ) {
                if ( fSqlType != SQL_BIT 
                     && fSqlType != SQL_ABAPHANDLE
                     && fSqlType != SQL_WCHAR
                     && fSqlType != SQL_WVARCHAR
                     && fSqlType != SQL_WLONGVARCHAR ) {
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt, API_ODBC_S1C00, NULL);
                    goto exit_1_lock;
                }
            }
	 
            if (fParamType != SQL_PARAM_INPUT
                && fParamType != SQL_PARAM_OUTPUT 
                && fParamType != SQL_PARAM_INPUT_OUTPUT) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1009, NULL);
                goto exit_1_lock;
            }
	 
            /* check conversion                */
            /* char C data can be converted to */
            /*   any valid SQL data type       */
            /* numeric C data can not be       */
            /*   converted to char SQL data typ*/

            switch (fCType) {        /* !! add extended C data types    */
            case (SQL_C_CHAR): {}
            case (SQL_C_WCHAR): {}
            case (SQL_C_BINARY): {}
            case (SQL_C_DEFAULT): {
                break;
            }
            case (SQL_C_SSHORT): {}
            case (SQL_C_USHORT): {}
            case (SQL_C_SHORT): {}
            case (SQL_C_SLONG): {}
            case (SQL_C_ULONG): {}
            case (SQL_C_LONG): {}
            case (SQL_C_FLOAT): {}
            case (SQL_C_DOUBLE): {}
            case (SQL_C_BIT): {}
            case (SQL_C_STINYINT): {}
            case (SQL_C_UTINYINT): {}
            case (SQL_C_TINYINT): {
            case (SQL_C_NUMERIC): {} /* new in 3.0 */
#ifdef BIGINT_SUPPORTED
            case (SQL_C_SBIGINT): {} /* new in 3.0 */
            case (SQL_C_UBIGINT): {} /* new in 3.0 */
#endif /* BIGINT_SUPPORTED */
                switch (fSqlType) {  /* !! add extended SQL data types */
                case (SQL_TYPE_DATE): {}
                case (SQL_TYPE_TIME): {}
                case (SQL_TYPE_TIMESTAMP): {}
                case (SQL_DATE): {}
                case (SQL_TIME): {}
                case (SQL_TIMESTAMP): {}
                case (SQL_LONGVARBINARY): {}
                case (SQL_VARBINARY): {}
                case (SQL_BINARY): { /* restricted data type */
                    retcode = SQL_ERROR;
                    pa60PutError( hstmt, API_ODBC_07006, NULL);
                    goto exit_1_lock;
                    break;
                }
                default: {
                    break;
                }
                }
                break;
            }
            case (SQL_C_TYPE_DATE): {}
            case (SQL_C_TYPE_TIME): {}
            case (SQL_C_TYPE_TIMESTAMP): {}
            case (SQL_C_DATE): {}
            case (SQL_C_TIME): {}
            case (SQL_C_TIMESTAMP): {
                switch (fSqlType) {  /* !! add extended SQL data types */
                case (SQL_CHAR): {}
                case (SQL_VARCHAR): {}
                case (SQL_LONGVARCHAR): {}
                case (SQL_WCHAR): {}
                case (SQL_WVARCHAR): {}
                case (SQL_WLONGVARCHAR): {}
                case (SQL_TIMESTAMP): {}
                case (SQL_TYPE_TIMESTAMP): {
                    break;
                }
                default: {
                if (( fCType == SQL_C_TYPE_TIME
                      || fCType == SQL_C_TYPE_TIMESTAMP
                      || fCType == SQL_C_TIME
                      || fCType == SQL_C_TIMESTAMP)
                    && (fSqlType == SQL_TYPE_TIME || fSqlType == SQL_TIME ))
                    break;
                if (( fCType == SQL_C_TYPE_DATE
                      || fCType == SQL_C_TYPE_TIMESTAMP
                      || fCType == SQL_C_DATE
                      || fCType == SQL_C_TIMESTAMP)
                    && (fSqlType == SQL_TYPE_DATE || fSqlType == SQL_DATE))
                    break;
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_07006, NULL);
                goto exit_1_lock;
                break;
                }
                break;
                }
                break;
            }
            default: {  
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1003, NULL );
                goto exit_1_lock;
                break;
            }
            }
            /* check argument value            */
            if (rgbValue == NULL && pcbValue == NULL ) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1009, NULL);
                /* invalid argument value */
                goto exit_1_lock;
            }	
            if ( ipar == 0 ) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1093, NULL);
                /* invalid parameter value */
                goto exit_1_lock;
            }
            /* check input scale               */
            if (ibScale < 0) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1094, NULL);
                /* invalid scale  value            */
                goto exit_1_lock;
            }
            /* check for overflow of the       */
            /* attribute block array           */
            api_retcode = pa20ReallocRecords( stmt_block_ptr->apdPtr,
                                              (UWORD)(ipar + API_BIND_INC) );
            if (api_retcode != API_OK) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1001, NULL);
                /* memory allocation failure     */
                goto exit_1_lock;
            }; /* if */
            api_retcode = pa20ReallocRecords( &stmt_block_ptr->ipd,
                                              (UWORD)(ipar + API_BIND_INC) );
            if (api_retcode != API_OK) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1001, NULL);
                /* memory allocation failure     */
                goto exit_1_lock;
            }; /* if */
            
            allocated_input_attr = stmt_block_ptr -> apdPtr -> allocRec;

            /* SQL data type FLOAT is handled  */
            /* as type DOUBLE (ODBC book, 469) */
            switch (fSqlType) {
            case SQL_FLOAT: {
                type = SQL_DOUBLE;
                break;
            }
            case SQL_NUMERIC: {
                type = SQL_DECIMAL;
                break;
            }
            case SQL_VARCHAR: {
                type = SQL_CHAR;
                break;
            }
            default: {
                type = fSqlType;
                break;
            }
            }

            if (retcode == SQL_SUCCESS) {
                SQLULEN length  = 0;
                
                if (stmt_block_ptr -> ipd.count < ipar) {
                    stmt_block_ptr -> ipd.count = ipar;
                    stmt_block_ptr -> apdPtr->count = ipar;
                }; /* if */
                appl_rec_ptr = pa20GetRecord( stmt_block_ptr->apdPtr, ipar );
                API_ASSERT_PTR( appl_rec_ptr );
                impl_rec_ptr = pa20GetRecord( &stmt_block_ptr->ipd, ipar );
                API_ASSERT_PTR( appl_rec_ptr );
                
                pa21SetCType( appl_rec_ptr, fCType );
                appl_rec_ptr -> bound          = API_TRUE;
                appl_rec_ptr -> octetLengthPtr = pcbValue;
                appl_rec_ptr -> indicatorPtr   = pcbValue;
                /* check type conciseType and datetimeIntervalCode */
                if (!pa20TypesAreConsistent( stmt_block_ptr->apdPtr, ipar )) {
                    pa60PutError( hstmt, API_ODBC_HY021, NULL );
                    /* Inconsistent descriptor information */
                    goto exit_1_lock;
                }; /* else */
                appl_rec_ptr -> dataPtr        = rgbValue;
      
                apgstyc( fCType, cbColDef, fSqlType, (UDWORD) cbColDef, ibScale,  /* ia64 cast */
                         &real_c_type,
                         &length );
                appl_rec_ptr -> precision   = (SWORD) length;
                appl_rec_ptr -> scale       = ibScale;
                appl_rec_ptr -> octetLength = cbValueMax; /* (SDWORD) length; */
                pa21SetSQLType( impl_rec_ptr, type );
                appl_rec_ptr -> length = appl_rec_ptr -> octetLength;
#if 0                    
                if (appl_rec_ptr -> octetLengthPtr != NULL)
                    appl_rec_ptr -> length =
                        *PA20_OCTETLENGTH_PTR(appl_rec_ptr);
                else
                    appl_rec_ptr -> length = 0;
#endif                
                impl_rec_ptr -> parameterType = fParamType;
            }

        exit_1_lock:
            if (hstmt_setpos && (retcode == SQL_SUCCESS
                                 || retcode == SQL_SUCCESS_WITH_INFO)) {
                CALL_ODBC(SQLBindParameter, (hstmt_setpos,
                                             ipar,
                                             fParamType,
                                             fCType,
                                             fSqlType,
                                             cbColDef,
                                             ibScale,
                                             rgbValue,
                                             cbValueMax,
                                             pcbValue));
            }
        }
    }
    API_TRACE(API_TR_EXIT,PA11_FN_SQLBINDPARAMETER,0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);
   
    return(retcode);
} /* SQLBindParameter */

#endif  /* of _UNICODE_ODBC */

/*
typedef struct {
  UCHAR owner_buffer [API_USERID_MAX_LEN*2+1];
  UCHAR table_buffer [API_TABLE_NAME_MAX*2+1];
  UCHAR column_buffer [API_COLUMN_NAME_MAX*2+1];
} pa11StackColumns;
*/

typedef struct {
  tpr05_String *owner_buffer;
  tpr05_String *table_buffer;
  tpr05_String *column_buffer;
} pa11StackColumns;

#ifdef _UNICODE_ODBC
ODBC_PROC(SQLColumnsW, (SQLHSTMT      hstmt,
                        SQLWCHAR     *szTableQualifier,
                        SQLSMALLINT   cbTableQualifier,
                        SQLWCHAR     *szTableOwner,
                        SQLSMALLINT   cbTableOwner,
                        SQLWCHAR     *szTableName,
                        SQLSMALLINT   cbTableName,
                        SQLWCHAR     *szColumnName,
                        SQLSMALLINT   cbColumnName),
	  (hstmt, szTableQualifier, cbTableQualifier, szTableOwner, cbTableOwner, szTableName, cbTableName, szColumnName, cbColumnName))
#else
ODBC_PROC(SQLColumns, (SQLHSTMT      hstmt,
                       SQLCHAR      *szTableQualifier,
                       SQLSMALLINT   cbTableQualifier,
                       SQLCHAR      *szTableOwner,
                       SQLSMALLINT   cbTableOwner,
                       SQLCHAR      *szTableName,
                       SQLSMALLINT   cbTableName,
                       SQLCHAR      *szColumnName,
                       SQLSMALLINT   cbColumnName),
	  (hstmt, szTableQualifier, cbTableQualifier, szTableOwner, cbTableOwner, szTableName, cbTableName, szColumnName, cbColumnName))
#endif
{

    RETCODE		retcode=SQL_SUCCESS;
    API_RETCODE  api_retcode;
    pa11StackColumns LV;
    SQLHENV    henv;
    SQLHDBC    hdbc;
    tpa40DBC  *dbc_block_ptr;
    tpa50Env  *env_block_ptr;
    tpa60Stmt *stmt_block_ptr;
    UWORD      comment;
    UWORD      state;
    UDWORD     odbcVersion;
#ifdef _UNICODE_ODBC
    const tsp77encoding *encodingType = sp77nativeUnicodeEncoding ();
    SQLCHAR sql_string [API_SQL_STRING_SWAG * 4 * sizeof (tsp81_UCS2Char)];
#else
    const tsp77encoding *encodingType = sp77encodingAscii;
    SQLCHAR sql_string [API_SQL_STRING_SWAG * 4];
#endif   
    const int charSize = encodingType->fixedCharacterSize;
    SQLINTEGER sqlLen;

    const char *owner_op, *tabname_op, *column_op;
    const char *owner_escape, *tabname_escape, *column_escape;

    API_TRACE(API_TR_ENTRY,PA11_FN_SQLCOLUMNS,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);
    API_TRACE_LEN(API_TR_ODBC_STRING,"szColumnName",
                  szColumnName, cbColumnName);
    API_TRACE(API_TR_SWORD,"cbColumnName",&cbColumnName);
  
    LV.owner_buffer = LV.table_buffer = LV.column_buffer = NULL;

    if (cbTableQualifier != SQL_NTS)
      cbTableQualifier *= charSize;
    if (cbTableOwner != SQL_NTS)
      cbTableOwner *= charSize;
    if (cbTableName != SQL_NTS)
      cbTableName *= charSize;
    if (cbColumnName != SQL_NTS)
      cbColumnName *= charSize;

    api_retcode = API_OK;
    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLCOLUMNS);
    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_S1000, NULL);
                    goto exit_async;
                }	
                if (state == API_STMT_POSITIONED) {
                    /* function seqeunces error */
                    retcode = SQL_ERROR;            /* SQLSTATE: 24000 */
                    pa60PutError( hstmt, API_ODBC_24000, NULL);
                    goto exit_async;
                }

                LV.owner_buffer = 
                  pr05IfCom_String_NewDynString (charSize * (API_USERID_MAX_LEN*2+1),
                                                 encodingType);
                LV.table_buffer = 
                  pr05IfCom_String_NewDynString (charSize * (API_TABLE_NAME_MAX*2+1), 
                                                 encodingType);
                LV.column_buffer = 
                  pr05IfCom_String_NewDynString (charSize * (API_COLUMN_NAME_MAX*2+1), 
                                                 encodingType);

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

                /* get owner and table name   */
                api_retcode = pa80ODBCtoTpr05 (LV.owner_buffer,
                                               encodingType,
                                               szTableOwner,
                                               cbTableOwner);
                if (api_retcode == API_OK) {
                    if (LV.owner_buffer->cbLen == 0) {
                      pr05IfCom_String_strcatP (LV.owner_buffer, "%", 
                                                (tsp00_Uint4) API_STRLEN ("%"),
                                                sp77encodingAscii);
                    }
                    api_retcode = pa80ODBCtoTpr05 (LV.table_buffer,
                                                   encodingType,
                                                   szTableName,
                                                   cbTableName);
                    if (api_retcode == API_OK) {
                        if (LV.table_buffer->cbLen == 0) {
                          pr05IfCom_String_strcatP (LV.table_buffer, "%",
                                                    (tsp00_Uint4) API_STRLEN ("%"),
                                                    sp77encodingAscii);
                        }
                        api_retcode = pa80ODBCtoTpr05 (LV.column_buffer,
                                                       encodingType,
                                                       szColumnName,
                                                       cbColumnName);
                        if (api_retcode == API_OK) {
                            if (LV.column_buffer->cbLen == 0) {
                              pr05IfCom_String_strcatP (LV.column_buffer, "%", 
                                                        (tsp00_Uint4) API_STRLEN ("%"),
                                                        sp77encodingAscii);
                            }
                        } /* column_buffer */
                    } /* table_buffer */
                } /* owner_buffer */
                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_SQLCOLUMNS;
                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_SQLCOLUMNS);     
                }
            } /* 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;
                }
            }
            comment = dbc_block_ptr->catalogcomments;
            if (!pa10GetODBCVersion( SQL_HANDLE_STMT, hstmt, &odbcVersion )) {
                retcode = SQL_ERROR;
                /* general error */
                pa60PutError( hstmt, API_ODBC_S1000, NULL);
                goto exit_1_lock;
            };

            /* determine whether TABLE_OWNER, TABLE_NAME can be selected with LIKE or =
               http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1141702 */
            if (pa80containsWildCard (LV.owner_buffer->rawString, LV.owner_buffer->cbLen,
                                      LV.owner_buffer->encodingType)) {
              owner_op = "LIKE";
              owner_escape = "ESCAPE '\\'";
            } else {
              owner_op = "=";
              owner_escape = "";
            }

            if (pa80containsWildCard (LV.table_buffer->rawString, LV.table_buffer->cbLen,
                                      LV.table_buffer->encodingType)) {
              tabname_op = "LIKE";
              tabname_escape = "ESCAPE '\\'";
            } else {
              tabname_op = "=";
              tabname_escape = "";
            }

            if (pa80containsWildCard (LV.column_buffer->rawString, LV.column_buffer->cbLen,
                                      LV.column_buffer->encodingType)) {
              column_op = "LIKE";
              column_escape = "ESCAPE '\\'";
            } else {
              column_op = "=";
              column_escape = "";
            }

            /* ODBC version 3.0 defines different column-names */
            if (odbcVersion == SQL_OV_ODBC3) {
              /* Column default values available with 7.6 (after b12)
                 http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1136245 */
              char column_def_new[] = "COLUMN_DEF";
              char column_def_old[] = "NULL COLUMN_DEF";
              char *column_def = column_def_new;
              if (dbc_block_ptr->kernelVersionString[0] < '7'  ||
                  (dbc_block_ptr->kernelVersionString[0] == '7'  &&
                   dbc_block_ptr->kernelVersionString[1] == '0'  &&
                   dbc_block_ptr->kernelVersionString[2] <= '5'))
                column_def = column_def_old;

              sqlLen = sp77sprintfUnicode (encodingType,
                                           sql_string, sizeof (sql_string),
                                           (char*) PA11SELECTCOLUMNS_ODBC35,
                                           column_def,
                                           pa12_getTablePrefix (dbc_block_ptr),
                                           owner_op,
                                           LV.owner_buffer->encodingType,
                                           LV.owner_buffer->cbLen,
                                           LV.owner_buffer->rawString,
                                           owner_escape,

                                           tabname_op,
                                           LV.table_buffer->encodingType,
                                           LV.table_buffer->cbLen,
                                           LV.table_buffer->rawString,
                                           tabname_escape,

                                           column_op,
                                           LV.column_buffer->encodingType,
                                           LV.column_buffer->cbLen,
                                           LV.column_buffer->rawString,
                                           column_escape);
              
/*                 API_SPRINTF((char*) sql_ptr,(char*) PA11SELECTCOLUMNS_ODBC35, */
/*                             LV.owner_buffer, API_ESCAPE_CHAR,  */
/*                             LV.table_buffer, API_ESCAPE_CHAR,  */
/*                             LV.column_buffer, API_ESCAPE_CHAR); */
            } else {
              sqlLen = sp77sprintfUnicode (encodingType,
                                           sql_string, sizeof (sql_string),
                                           (char*) PA11SELECTCOLUMNS,
                                           pa12_getTablePrefix (dbc_block_ptr),
                                           owner_op,
                                           LV.owner_buffer->encodingType,
                                           LV.owner_buffer->cbLen,
                                           LV.owner_buffer->rawString,
                                           owner_escape,

                                           tabname_op,
                                           LV.table_buffer->encodingType,
                                           LV.table_buffer->cbLen,
                                           LV.table_buffer->rawString,
                                           tabname_escape,

                                           column_op,
                                           LV.column_buffer->encodingType,
                                           LV.column_buffer->cbLen,
                                           LV.column_buffer->rawString,
                                           column_escape);



/*                 API_SPRINTF((char*) sql_ptr,(char*) PA11SELECTCOLUMNS, */
/*                             LV.owner_buffer, API_ESCAPE_CHAR,  */
/*                             LV.table_buffer, API_ESCAPE_CHAR,  */
/*                             LV.column_buffer, API_ESCAPE_CHAR); */
            }; /* else */
#ifdef _UNICODE_ODBC
            retcode = CALL_ODBC(SQLPrepareW, (hstmt, (SQLWCHAR*) sql_string, sqlLen / charSize));
#else
            retcode = CALL_ODBC(SQLPrepare, (hstmt, sql_string, sqlLen));
#endif
            if (retcode == SQL_SUCCESS) {
                retcode = CALL_ODBC(SQLExecute, (hstmt));
            }

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

    return(retcode);
} /* SQLColumns */

/* SQLGetData returns also for data type SQL_WCHAR */
#ifdef _UNICODE_ODBC
API_RETCODE pa60MoveLong( tpa40DBC   *dbc_block_ptr,
                          tpa60Stmt  *stmt_block_ptr,
                          tpa20Desc  *appl_desc_ptr,
                          tpa20Desc  *impl_desc_ptr,
                          UWORD       icol,
                          UWORD       number_cols );


API_RETCODE pa60MoveLongPos( tpa40DBC   *dbc_block_ptr,
                             tpa60Stmt  *stmt_block_ptr,
                             tpa20Desc  *appl_desc_ptr,
                             tpa20Desc  *impl_desc_ptr,
                             UWORD       icol,
                             UDWORD      long_pos );

ODBC_PROC(SQLGetData,
	  (SQLHSTMT       hstmt,
	   SQLUSMALLINT   icol,
	   SQLSMALLINT    fCType,
	   SQLPOINTER     rgbValue,
	   SQLLEN         cbValueMax,
	   SQLLEN        *pcbValue),
	  (hstmt, icol, fCType, rgbValue, cbValueMax, pcbValue))
{
    RETCODE retcode;
    API_RETCODE    api_retcode;
    SWORD          _fCType;
    PTR            _rgbValue;
    SQLLEN         cbValue;
    SQLLEN         _cbValue;
    SQLLEN        *_pcbValue;
    SWORD          _bound;
    SQLLEN        *_bindOffsetPtr;
    
    UWORD          state;
    UWORD          number_cols;
    tpa60Stmt     *stmt_block_ptr;
    SQLHDBC        hdbc;
    tpa40DBC      *dbc_block_ptr;
    SQLHENV        henv;
    tpa50Env      *env_block_ptr;
    sqldatype     *sqlda_ptr;
    API_HANDLE     sqlda_handle;
    API_HANDLE     tuple_handle;
    UCHAR         *tuple_ptr;
    UDWORD         col_size;
    UDWORD         alreadyRead;       /* already read bytes (for long data) */

    tpa21DescRecord *appl_rec_ptr;
    tpa21DescRecord *impl_rec_ptr;
    
    API_TRACE(API_TR_ENTRY,PA11_FN_SQLGETDATA,0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE(API_TR_UWORD,"icol",&icol);
    API_TRACE(API_TR_SWORD,"fCType",&fCType);
    API_TRACE(API_TR_PTR,"rgbValue",&rgbValue);
    API_TRACE(API_TR_SDWORD,"cbValueMax",&cbValueMax);
    API_TRACE(API_TR_PTR,"pcbValue",&pcbValue);

    retcode = SQL_SUCCESS;

    api_retcode = apmstfc( SQL_NULL_HENV, SQL_NULL_HDBC,
                           hstmt, SQL_API_SQLGETDATA );
    if (api_retcode != API_OK) {
        retcode = pa06stfcerror(api_retcode, hstmt);
    }
    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;
            if (state == API_STMT_PREPARED) {
                UDWORD odbcVersion = SQL_OV_ODBC2;

                /* different SQLSTATES for ODBC 2.x and 3.x */
                pa10GetODBCVersion( SQL_HANDLE_STMT, hstmt, &odbcVersion );

                if (odbcVersion == SQL_OV_ODBC3) {
                    /* function sequence error */
                    pa60PutError( hstmt, API_ODBC_HY010, NULL);
                } else {
                    pa60PutError( hstmt, API_ODBC_S1010, NULL);
                }
                retcode = SQL_ERROR;
                goto lock1_exit;
                }
            else if (state != API_STMT_POSITIONED) {
                /* invalid cursor state */
                pa60PutError( hstmt, API_ODBC_24000, NULL);
                retcode = SQL_ERROR;
                goto lock1_exit;
            }
            /* PTS 1105584 */
            if (stmt_block_ptr->fetchRetcode != SQL_SUCCESS
                && stmt_block_ptr->fetchRetcode != SQL_SUCCESS_WITH_INFO) {
                /* invalid cursor state */
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_24000, NULL);
                goto lock1_exit;
            }            
            number_cols = stmt_block_ptr -> number_cols;

            if (number_cols < icol) {
                /* overflow! temp solution */
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1002, NULL);
                goto lock1_exit;
            }; /* if */
            /* column 0 is only valid if bookmarks are enabled */
            if (icol == 0
                && stmt_block_ptr->stmtopt.use_bookmarks == SQL_UB_OFF) {
                /* invalid descriptor index */
                pa60PutError( hstmt, API_ODBC_07009, NULL); 
                goto lock1_exit;
            }; /* if */
            
            sqlda_handle = stmt_block_ptr ->output_sqlda_handle;
            sqlda_ptr = (sqldatype*) sqlda_handle;
            API_ASSERT_PTR(sqlda_ptr);

            tuple_handle = stmt_block_ptr -> col_handle;
            col_size = stmt_block_ptr -> col_size;
            tuple_ptr = (UCHAR*) tuple_handle;
            API_ASSERT_PTR(tuple_ptr);

            impl_rec_ptr = pa20GetRecord( &stmt_block_ptr->ird, icol );
            if ( icol > 0 && impl_rec_ptr -> optimizePtr == NULL ) {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1001, NULL);
            }       
            else {
                appl_rec_ptr = pa20GetRecord( stmt_block_ptr->ardPtr, icol );
                if ( apgislong( impl_rec_ptr -> type )) {
                    /* no LONG for bookmarks */
                    API_ASSERT( icol > 0 );
                    /* for SQLGetData bindOffsetPtr is ignored. Set it to NULL
                     * temporary. */
                    _bindOffsetPtr =
                        stmt_block_ptr->ardPtr->header.bindOffsetPtr;
                    stmt_block_ptr->ardPtr->header.bindOffsetPtr = NULL;
                    _fCType = appl_rec_ptr -> conciseType;
                    _rgbValue = appl_rec_ptr -> dataPtr;
                    _cbValue = appl_rec_ptr -> length;
                    _pcbValue = appl_rec_ptr -> octetLengthPtr;
                    _bound = appl_rec_ptr -> bound;
                    appl_rec_ptr -> conciseType = fCType;
                    appl_rec_ptr -> dataPtr = rgbValue;
                    appl_rec_ptr -> length = cbValueMax;
                    if (pcbValue)
                        cbValue = *pcbValue;
                    appl_rec_ptr -> octetLengthPtr = &cbValue;
                    appl_rec_ptr -> bound = API_TRUE;

                    /* bytes already read: shift for positioned read */
                    /* read_long_pos is given in character count -> determine byte length */
                    /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1126177 */
                    if (fCType == SQL_C_WCHAR)
                      impl_rec_ptr->alreadyRead += sizeof(SQLWCHAR) * stmt_block_ptr->stmtopt.read_long_pos;
                    else
                      impl_rec_ptr->alreadyRead += stmt_block_ptr->stmtopt.read_long_pos;

                    alreadyRead = impl_rec_ptr->alreadyRead;

                    if (stmt_block_ptr->stmtopt.read_long_pos == 0) {
                        api_retcode = pa60MoveLong( dbc_block_ptr,
                                                    stmt_block_ptr,
                                                    stmt_block_ptr->ardPtr,
                                                    &stmt_block_ptr->ird,
                                                    icol,
                                                    icol );
                    } else {
                        api_retcode = pa60MoveLongPos( dbc_block_ptr,
                                                       stmt_block_ptr,
                                                       stmt_block_ptr->ardPtr,
                                                       &stmt_block_ptr->ird,
                                                       icol,
                                                       stmt_block_ptr
                                                       ->stmtopt.read_long_pos);
                        stmt_block_ptr->stmtopt.read_long_pos = 0;
                    }; /* else */

                    appl_rec_ptr -> conciseType = _fCType;
                    appl_rec_ptr -> dataPtr = _rgbValue;
                    appl_rec_ptr -> length = _cbValue;	   
                   if (api_retcode != API_NO_DATA_FOUND)
                     if (pcbValue) {
                        *pcbValue = *appl_rec_ptr -> octetLengthPtr;
                        if (*pcbValue == SQL_NO_TOTAL) { /* PTS 1119132 */
                            SWORD  realSqlType;
                            UDWORD sql_len;
                            UWORD  sql_scale;

                            pa11_GetTotalLength (stmt_block_ptr, icol, pcbValue);
                            
                            apgstys (impl_rec_ptr->realEsqType, impl_rec_ptr->esqLength,
                                     impl_rec_ptr->esqScale,
                                     &realSqlType, &sql_len, &sql_scale);

                            /* size after conversion */
                            switch (realSqlType) {
                            case SQL_CHAR: {}
                            case SQL_VARCHAR: {}
                            case SQL_LONGVARCHAR: {
                              if (fCType == SQL_C_WCHAR)
                                *pcbValue *= sizeof (SQLWCHAR);
                              break;
                            }
                            case SQL_WCHAR: {}
                            case SQL_WVARCHAR: {}
                            case SQL_WLONGVARCHAR: {
                              if (fCType == SQL_C_CHAR)
                                *pcbValue /= sizeof (SQLWCHAR);
                              break;
                            }
                            default: {}
                            }
                            /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1126177 */
                            /* return number of bytes available to return
                               before current call of SQLGetData */
                            *pcbValue -= alreadyRead;
                        }
                    } else {
                      /* Indicator variable required but not supplied */
                      /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1122725 */
                        if (appl_rec_ptr -> indicatorPtr != NULL  &&
                            appl_rec_ptr -> indicatorPtr != appl_rec_ptr -> octetLengthPtr) {
                          if (*appl_rec_ptr -> indicatorPtr == SQL_NULL_DATA)
                              api_retcode = API_NO_INDICATOR;
                          else if (*appl_rec_ptr -> octetLengthPtr == SQL_NULL_DATA)
                              api_retcode = API_NO_INDICATOR;
                        }
                        /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1129010 */
                        if (appl_rec_ptr -> indicatorPtr == NULL  &&
                            appl_rec_ptr -> octetLengthPtr != NULL) {
                          if (*appl_rec_ptr -> octetLengthPtr == SQL_NULL_DATA)
                            api_retcode = API_NO_INDICATOR;
                        }
                    }; /* else */
                    appl_rec_ptr -> octetLengthPtr = _pcbValue;
                    appl_rec_ptr -> bound = _bound;
                    stmt_block_ptr->ardPtr->header.bindOffsetPtr =
                        _bindOffsetPtr;
                }
                else {
                    SQLLEN lenOrIndi = 0;
                    /* PTS 1110478, set conciseType if SQL_ARD_TYPE */
                    if (fCType == SQL_ARD_TYPE)
                      fCType = appl_rec_ptr->conciseType;

                    if (icol == 0) {
                        /* bookmark field */
                        /* expect that bookmark will not be moved in
                         * pieces .... Else we have to use moved_len ... */
                        size_t copyLen = min( sizeof(stmt_block_ptr->fetch_pos),
                                              (size_t) cbValueMax );
                        lenOrIndi = sizeof(stmt_block_ptr->fetch_pos);
                        API_MEMCPY( rgbValue,
                                    &stmt_block_ptr->fetch_pos,
                                    copyLen );
                        if (copyLen < sizeof(stmt_block_ptr->fetch_pos)) {
                            api_retcode = API_TRUNCATE;
                        } else {
                            api_retcode = API_OK;
                        }; /* else */
                    } else {
                        /* "regular" column */
                        tpa62DBCSpecial FAR * dbc_special_ptr;
                        dbc_special_ptr = &stmt_block_ptr -> dbc_special;
                        api_retcode = pa20SMap( &stmt_block_ptr->ird,
                                                icol,
                                                dbc_special_ptr,
                                                fCType,
                                                appl_rec_ptr->scale,
                                                rgbValue,
                                                cbValueMax,
                                                &lenOrIndi );
                    }; /* else */
                    if (api_retcode != API_NO_DATA_FOUND) {
                      if (pcbValue) {
                        *pcbValue = lenOrIndi;
                      } else if (lenOrIndi == SQL_NULL_DATA) {
                        /* Indicator variable required but not supplied */
                        api_retcode = API_NO_INDICATOR;
                      }; /* else */
                    }
                }; /* else */
                /* ODBC style error handling  */
                retcode = pa60PutESQError( hstmt, api_retcode );
                if ( retcode == SQL_SUCCESS
                     || retcode == SQL_SUCCESS_WITH_INFO) {
                    stmt_block_ptr -> state = API_STMT_POSITIONED;
                }; /* if */
            }
        } /* of if */
    }

lock1_exit:

    API_TRACE(API_TR_EXIT,PA11_FN_SQLGETDATA,0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);
    API_TRACE(API_TR_SDWORD,"*pcbVALUE",pcbValue);
   
    return(retcode);
} /* SQLGetData */
#endif  /* of _UNICODE_ODBC */


#ifdef _UNICODE_ODBC
ODBC_PROC(SQLGetTypeInfoW, (SQLHSTMT     hstmt,
                            SQLSMALLINT  fSqlType),
	  (hstmt, fSqlType))
#else
ODBC_PROC(SQLGetTypeInfo, (SQLHSTMT     hstmt,
                           SQLSMALLINT  fSqlType),
	  (hstmt, fSqlType))
#endif
{
    RETCODE retcode=SQL_SUCCESS;
    API_RETCODE api_retcode;
    tpa60Stmt FAR * stmt_block_ptr;
    SQLHDBC hdbc;
    tpa40DBC FAR * dbc_block_ptr;
    SQLHENV henv;
    tpa50Env FAR * env_block_ptr;

    UCHAR sql_string [(API_SQL_STRING_SWAG * 2)];
    UCHAR where_buffer [(API_SQL_STRING_SWAG / 2)];
    UCHAR FAR * sql_ptr;
    SDWORD sql_len;
#ifdef _UNICODE_ODBC
    tsp00_Uint4 destBytesWritten;
    SQLWCHAR sqlStringW[(API_SQL_STRING_SWAG * 2)];
    const tsp77encoding *nativeEncoding = sp77nativeUnicodeEncoding ();
#endif

    API_TRACE(API_TR_ENTRY,PA11_FN_SQLGETTYPEINFO,0);
    API_TRACE(API_TR_HANDLE,"hstmt",&hstmt);
    API_TRACE(API_TR_SWORD,"fSqlType",&fSqlType);

    api_retcode = apmstfc(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, 
                          SQL_API_SQLGETTYPEINFO);
    if (api_retcode != API_OK) {
        retcode = SQL_INVALID_HANDLE;
    }
    else {
        UDWORD     odbcVersion;
        
        apmlocp(&hstmt, &stmt_block_ptr, &hdbc, &dbc_block_ptr, 
                &henv, &env_block_ptr);
        PA09ENTERASYNCFUNCTION(dbc_block_ptr, stmt_block_ptr);
        retcode = SQL_SUCCESS;
        sql_ptr = (UCHAR FAR *) sql_string;
        /* 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);
        } else {
            /* ODBC version 3.0 defines different column-names */
            if (odbcVersion == SQL_OV_ODBC3) {
                API_SPRINTF ((CHAR*) sql_ptr, (CHAR*) PA11SELECTCOLTYPES_ODBC35,
                             SQL_DATE, SQL_TYPE_DATE,
                             SQL_TIME, SQL_TYPE_TIME,
                             SQL_TIMESTAMP, SQL_TYPE_TIMESTAMP,
                             pa12_getTablePrefix (dbc_block_ptr));
            } else {
                API_SPRINTF ((char*) sql_ptr, PA11SELECTCOLTYPES, pa12_getTablePrefix (dbc_block_ptr));
            }; /* else */

            /* map ODBC 3 types to ODBC 2 types */
            switch (fSqlType) {
            case (SQL_TYPE_DATE):
                fSqlType = SQL_DATE;       break;
            case (SQL_TYPE_TIME):
                fSqlType = SQL_TIME;       break;
            case (SQL_TYPE_TIMESTAMP):
                fSqlType = SQL_TIMESTAMP;  break;
            default: {}
            }

            switch (fSqlType) {
            case (SQL_ALL_TYPES): {      /* don't add where clause */
                break;
            }
            case (SQL_CHAR): {}
            case (SQL_UNICODE): {}
            case (SQL_NUMERIC): {}
            case (SQL_DECIMAL): {}
            case (SQL_INTEGER): {}
            case (SQL_SMALLINT): {}
            case (SQL_FLOAT): {}
            case (SQL_REAL): {}
            case (SQL_DOUBLE): {}
            case (SQL_VARCHAR): {}     
            case (SQL_UNICODE_VARCHAR): {}     
            case (SQL_TYPE_DATE): {}
            case (SQL_TYPE_TIME): {}          
            case (SQL_TYPE_TIMESTAMP): {}
            case (SQL_DATE): {}
            case (SQL_TIME): {}          
            case (SQL_TIMESTAMP): {}
            case (SQL_LONGVARCHAR): {}     
            case (SQL_UNICODE_LONGVARCHAR): {}     
            case (SQL_BINARY): {}   
            case (SQL_VARBINARY): {}        
            case (SQL_LONGVARBINARY): {}
            case (SQL_BIGINT): {} 
            case (SQL_TINYINT): {}        
            case (SQL_BIT): {
                API_SPRINTF((char*) where_buffer, 
                            (char*) " WHERE DATA_TYPE = %d ", fSqlType);
                API_STRCAT(sql_ptr, (UCHAR FAR *) where_buffer);
                break;
            }
            default: {
                retcode = SQL_ERROR;
                pa60PutError( hstmt, API_ODBC_S1004, NULL); /* data type invalid */
                break;
            }
            }
            if (retcode == SQL_SUCCESS) {
                tpa60Stmt *stmt_block_ptr;
                API_STRCAT(sql_ptr, (UCHAR FAR *) " ORDER BY 2, 1");
                sql_len = (SDWORD) API_STRLEN(sql_ptr);
                stmt_block_ptr = (tpa60Stmt*) hstmt;
                API_ASSERT_PTR(stmt_block_ptr);
                stmt_block_ptr -> dbc_special.special = API_SPEC_SQLGETTYPEINFO;
#ifdef _UNICODE_ODBC
                pa80convertString (nativeEncoding,
                                   sqlStringW, sizeof (sqlStringW), &destBytesWritten,
                                   sp77encodingAscii,
                                   sql_string,
                                   sql_len);
                retcode = CALL_ODBC(SQLPrepareW, (hstmt, sqlStringW, sql_len));
#else
                retcode = CALL_ODBC(SQLPrepare, (hstmt, sql_ptr, sql_len));
#endif
            }
            if (retcode == SQL_SUCCESS) {
                retcode = CALL_ODBC(SQLExecute, (hstmt));
            }
        }; /* else */
        PA09LEAVEASYNCFUNCTION();
    }
    API_TRACE(API_TR_EXIT,PA11_FN_SQLGETTYPEINFO,0);
    API_TRACE(API_TR_RETCODE,"retcode",&retcode);
   
    return(retcode);
} /* SQLGetTypeInfo */


#ifndef _UNICODE_ODBC
void pa11_GetTotalLength (tpa60Stmt *stmt_block_ptr,
                          SQLUSMALLINT icol,
                          SQLLEN *len)
{
  int i;
  struct SQLPCLD *pc = stmt_block_ptr->rasqlldp->ldpc;
  struct SQLSPLD *sp = stmt_block_ptr->rasqlldp->ldsp;

  for (i=0; i<icol; i++) {
    if (pc[i].ldcolno == icol) {
      *len = sp[i].ld.o.ld_maxlen;
      break;
    }
  }
}

#endif

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