/*
** RESULTS.C - This is the module containing the code for ODBC for
** returning results and information about results.
**
** (c) 1996 by Dirk Ohme - all rights reserved
*/

#include "cli.h"

/*---------------------------------------------------------------------------*/
/*      This returns the number of columns associated with the database      */
/*      attached to "lpstmt".                                                */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLNumResultCols(
        LPSTMT  lpstmt,
        SDWORD FAR *pccol)
{                                                /*--------------------------*/
#ifdef ORACLE
        sb4      cbSize;                         /* database entry size      */
#endif
                                                 /*--------------------------*/
        /*
        ** check parameter
        */
        LogEntry( LOG_STATUS, "[SQLNumResultCols]  lpstmt = $%08lX", lpstmt );
        LogEntry( LOG_STATUS, "                   *pccol  = $%08lX", pccol  );
        if( NULL == lpstmt )
        {
                LogEntry( LOG_ERROR,      "[SQLNumResultCols] NULL == lpstmt" );
                LogEntry( LOG_RETURNCODE, "[SQLNumResultCols] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }
        if( NULL == pccol )
        {
                strcpy( lpstmt->szSqlState, "S1009" );
                lpstmt->pszSqlMsg = "[SQLNumResultCols] pccol must not be NULL";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLNumResultCols] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
        *pccol = 0;

        /*
        ** get number of result columns
        */
        if( NULL == lpstmt->pszQuery )
        {
                strcpy( lpstmt->szSqlState, "S1010" );
                lpstmt->pszSqlMsg = "[SQLNumResultCols] no prepared statement";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLNumResultCols] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
#ifdef mSQL
        if( NULL != lpstmt->pMsqlResult )
                *pccol = msqlNumFields( lpstmt->pMsqlResult );
        else
                *pccol = 0;
#endif
#ifdef ORACLE
        *pccol         = lpstmt->ciCol;
#endif
        LogEntry( LOG_OUTPUT, "[SQLNumResultCols] columns = %d", *pccol );

        /*
        ** return success
        */
        LogEntry( LOG_RETURNCODE, "[SQLNumResultCols] SQL_SUCCESS" );
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      Return information about the database column the user wants          */
/*      information about.                                                   */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLDescribeCol(
        LPSTMT  lpstmt,
        UWORD   icol,
        UCHAR FAR *szColName,
        SWORD   cbColNameMax,
        SWORD FAR *pcbColName,
        SWORD FAR *pfSqlType,
        UDWORD FAR *pcbColDef,
        SWORD FAR *pibScale,
        SWORD FAR *pfNullable)
{                                                /*--------------------------*/
#ifdef mSQL
        m_field         *pField;                 /* curr. proccessed field   */
#endif
#ifdef ORACLE
        sb4              o_cbColSize;            /* column size              */
        sb2              o_fColType;             /* column type              */
        sb1              o_szColName[40];        /* column name              */
        sb4              o_cbColName;            /* column name len          */
        sb4              o_cbColDisp;            /* column display len       */
        sb2              o_cbColPrec;            /* column precision         */
        sb2              o_cbColScale;           /* column scale             */
        sb2              o_fColNullOk;           /* column nullable          */
#endif
                                                 /*--------------------------*/
        /*
        ** check parameter
        */
        LogEntry( LOG_STATUS, "[SQLDescribeCol]  lpstmt       = $%08lX", lpstmt       );
        LogEntry( LOG_STATUS, "                  icol         =  %3d",   icol         );
        LogEntry( LOG_STATUS, "                  *szColName   = $%08lX", szColName    );
        LogEntry( LOG_STATUS, "                  cbColNameMax = $%08lX", cbColNameMax );
        LogEntry( LOG_STATUS, "                  *pcbColName  = $%08X",  pcbColName   );
        LogEntry( LOG_STATUS, "                  *pfSqlType   = $%08X",  pfSqlType    );
        LogEntry( LOG_STATUS, "                  *pcbColDef   = $%08X",  pcbColDef    );
        LogEntry( LOG_STATUS, "                  *pibScale    = $%08X",  pibScale     );
        LogEntry( LOG_STATUS, "                  *pfNullable  = $%08X",  pfNullable   );
        if( NULL == lpstmt )
        {
                LogEntry( LOG_ERROR,      "[SQLDescribeCol] NULL == lpstmt" );
                LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }

        /*
        ** set defaults
        */
        if( NULL != szColName )
                *szColName  = '\0';
        if( NULL != pcbColName )
                *pcbColName = 0;
        if( NULL != pfSqlType )
                *pfSqlType  = 0;
        if( NULL != pcbColDef )
                *pcbColDef  = 0;
        if( NULL != pibScale )
                *pibScale   = 0;
        if( NULL != pfNullable )
                *pfNullable = SQL_FALSE;

        /*
        ** check query status
        */
#ifdef mSQL
        if( NULL == lpstmt->pszQuery ||
            NULL == lpstmt->pMsqlResult )
#endif
#ifdef ORACLE
        if( NULL == lpstmt->pszQuery )
#endif
        {
                strcpy( lpstmt->szSqlState, "S1010" );
                lpstmt->pszSqlMsg = "[SQLDescribeCol] no prepared statement";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

#ifdef mSQL
        /*
        ** get infos about the desired column (mSQL)
        */
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        if( 0 >= icol || icol > msqlNumFields(lpstmt->pMsqlResult) )
        {
                strcpy( lpstmt->szSqlState, "S1002" );
                lpstmt->pszSqlMsg = "[SQLDescribeCol] invalid column number";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        while( 0 < icol && NULL != (pField=msqlFetchField(lpstmt->pMsqlResult)) )
        {
                icol--;
        }
        if( NULL == pField )
        {
                strcpy( lpstmt->szSqlState, "07005" );
                lpstmt->pszSqlMsg = "[SQLDescribeCol] column not available";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

        /*
        ** check for column name (mSQL)
        */
        if( NULL != szColName )
        {
                memset(  szColName, 0, cbColNameMax );
                strncpy( szColName, pField->name, cbColNameMax - 1 );
                LogEntry( LOG_OUTPUT,
                          "[SQLDescribeCol] name of col.  = %s", szColName );
                if( NULL != pcbColName )
                {
                        *pcbColName = strlen( szColName );
                }
        }

        /*
        ** check for column type (mSQL)
        */
        if( NULL != pfSqlType )
        {
                switch( pField->type )
                {
                        case INT_TYPE:
                                LogEntry( LOG_OUTPUT,
                                          "[SQLDescribeCol] SQL_INTEGER" );
                                *pfSqlType = SQL_INTEGER;
                                break;
                        case REAL_TYPE:
                                LogEntry( LOG_OUTPUT,
                                          "[SQLDescribeCol] SQL_REAL" );
                                *pfSqlType = SQL_REAL;
                                break;
                        case CHAR_TYPE:
                                LogEntry( LOG_OUTPUT,
                                          "[SQLDescribeCol] SQL_CHAR" );
                                *pfSqlType = SQL_CHAR;
                                break;
                        default:
                                strcpy( lpstmt->szSqlState, "S1097" );
                                lpstmt->pszSqlMsg = "[SQLDescribeCol] invalid column type detected";
                                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                                LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_ERROR (%s)",
                                          lpstmt->szSqlState );
                                return SQL_ERROR;
                }
        }

        /*
        ** check for precision
        */
        if( NULL != pcbColDef )
        {
                switch( pField->type )
                {
                        case CHAR_TYPE:
                                *pcbColDef = pField->length;
                                break;
                        case INT_TYPE:
                                *pcbColDef = 5;
                                break;
                        case REAL_TYPE:
                                *pcbColDef = 16;
                                break;
                        default:
                                *pcbColDef = 0;
                }
                LogEntry( LOG_OUTPUT,
                          "[SQLDescribeCol] max col. len. = %d", *pcbColDef );
        }

        /*
        ** check for scale
        */
        if( NULL != pibScale )
        {
                *pibScale = 0;
                LogEntry( LOG_OUTPUT,
                          "[SQLDescribeCol] column scale  = %d", *pibScale );
        }

        /*
        ** check for nullable
        */
        if( NULL != pfNullable )
        {
                *pfNullable = (IS_NOT_NULL(pField->flags)) ? SQL_NO_NULLS
                                                           : SQL_NULLABLE;
                LogEntry( LOG_OUTPUT,
                          "[SQLDescribeCol] NULLs allowed = %s",
                          (IS_NOT_NULL(pField->flags)) ? "no" : "yes" );
        }
#endif

#ifdef ORACLE
        /*
        ** get infos about column (Oracle)
        */
        if( NULL != pcbColDef )
                *pcbColDef = 0;
        o_cbColName = sizeof( o_szColName );
        if( odescr( &lpstmt->cda, icol, &o_cbColSize, &o_fColType,
                    &o_szColName[0], &o_cbColName, &o_cbColDisp,
                    &o_cbColPrec, &o_cbColScale, &o_fColNullOk ) )
        {
                strcpy( lpstmt->szSqlState, "07005" );
                lpstmt->pszSqlMsg = "[SQLDescribeCol] column not available";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

        /*
        ** set column name (Oracle)
        */
        o_szColName[o_cbColName] = '\0';
        if( NULL != szColName )
                strncpy( szColName, o_szColName, cbColNameMax );
        if( NULL != pcbColName )
                *pcbColName = strlen( szColName );

        /*
        ** set data type (Oracle)
        */
        if( NULL != pfSqlType )
        {
                switch( o_fColType )
                {
                        case VARCHAR2_TYPE:     *pfSqlType = SQL_CHAR;
                                                break;
                        case INT_TYPE:          *pfSqlType = SQL_INTEGER;
                                                break;
                        case NUMBER_TYPE:       *pfSqlType = SQL_REAL;
                                                break;
                        default:
                                strcpy( lpstmt->szSqlState, "S1097" );
                                lpstmt->pszSqlMsg = "[SQLDescribeCol] invalid column type detected";
                                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                                LogEntry( LOG_RETURNCODE,
                                          "[SQLDescribeCol] SQL_ERROR (%s)",
                                          lpstmt->szSqlState );
                                return SQL_ERROR;
                }
        }

        /*
        ** set precision (Oracle)
        */
        if( NULL != pcbColDef )
        {
                if( VARCHAR2_TYPE == o_fColType )
                {
                        *pcbColDef = o_cbColSize;
                }
        }

        /*
        ** set scale (Oracle)
        */
        if( NULL != pibScale )
        {
                *pibScale = o_cbColScale;
        }

        /*
        ** set nullable (Oracle)
        */
        if( NULL != pfNullable )
        {
                *pfNullable = (0 != o_fColNullOk) ? SQL_NULLABLE
                                                  : SQL_NO_NULLS;
        }
#endif

        /*
        ** return success
        */
#ifdef mSQL
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
#endif
        LogEntry( LOG_RETURNCODE, "[SQLDescribeCol] SQL_SUCCESS" );
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      Returns result column descriptor information for a result set.       */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLColAttributes(
        LPSTMT  lpstmt,
        UWORD   icol,
        UWORD   fDescType,
        UCHAR FAR *rgbDesc,
        SWORD   cbDescMax,
        SWORD FAR *pcbDesc,
        SDWORD FAR *pfDesc)
{                                                /*--------------------------*/
#ifdef mSQL
        m_field         *pField;                 /* curr. proccessed field   */
#endif
#ifdef ORACLE
        sb4              cbLen;                  /* length of a column       */
        sb4              o_cbColSize;            /* column size              */
        sb2              o_fColType;             /* column type              */
        sb1              o_szColName[40];        /* column name              */
        sb4              o_cbColName;            /* column name len          */
        sb4              o_cbColDisp;            /* column display len       */
        sb2              o_cbColPrec;            /* column precision         */
        sb2              o_cbColScale;           /* column scale             */
        sb2              o_fColNullOk;           /* column nullable          */
#endif
                                                 /*--------------------------*/
        /*
        ** check parameters
        */
        LogEntry( LOG_STATUS, "[SQLColAttributes]  lpstmt     = $%08lX", lpstmt    );
        LogEntry( LOG_STATUS, "                    icol       =  %5d",   icol      );
        LogEntry( LOG_STATUS, "                    fDescType  = $%08lX", fDescType );
        LogEntry( LOG_STATUS, "                    rgbDesc    = $%08lX", rgbDesc   );
        LogEntry( LOG_STATUS, "                    cbDescMax  =  %5d",   cbDescMax );
        LogEntry( LOG_STATUS, "                    pcbDesc    = $%08lX", pcbDesc   );
        LogEntry( LOG_STATUS, "                    pfDesc     = $%08lX", pfDesc    );
        if( NULL == lpstmt )
        {
                LogEntry( LOG_ERROR,      "[SQLColAttributes] NULL == lpstmt" );
                LogEntry( LOG_RETURNCODE, "[SQLColAttributes] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }

        /*
        ** check query status
        */
#ifdef mSQL
        if( NULL == lpstmt->pszQuery ||
            NULL == lpstmt->pMsqlResult )
#endif
#ifdef ORACLE
        if( NULL == lpstmt->pszQuery )
#endif
        {
                strcpy( lpstmt->szSqlState, "S1010" );
                lpstmt->pszSqlMsg = "[SQLColAttributes] no prepared statement";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLColAttributes] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

        /*
        ** get infos about the desired column
        */
#ifdef mSQL
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        if( 0 >= icol || icol > msqlNumFields(lpstmt->pMsqlResult) )
        {
                strcpy( lpstmt->szSqlState, "S1002" );
                lpstmt->pszSqlMsg = "[SQLColAttributes] invalid column number";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLColAttributes] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        while( 0 < icol && NULL != (pField=msqlFetchField(lpstmt->pMsqlResult)) )
        {
                icol--;
        }
        if( NULL == pField )
        {
                strcpy( lpstmt->szSqlState, "07005" );
                lpstmt->pszSqlMsg = "[SQLColAttributes] column not available";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLColAttributes] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
#endif
#ifdef ORACLE
        if( odescr( &lpstmt->cda, icol, &o_cbColSize, &o_fColType,
                    &o_szColName[0], &o_cbColName, &o_cbColDisp,
                    &o_cbColPrec, &o_cbColScale, &o_fColNullOk ) )
        {
                strcpy( lpstmt->szSqlState, "07005" );
                lpstmt->pszSqlMsg = "[SQLColAttributes] column not available";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLColAttributes] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
#endif

        /*
        ** check pointers
        */
        switch( fDescType )
        {
                case SQL_COLUMN_AUTO_INCREMENT:
                case SQL_COLUMN_CASE_SENSITIVE:
                case SQL_COLUMN_COUNT:
                case SQL_COLUMN_DISPLAY_SIZE:
                case SQL_COLUMN_LENGTH:
                case SQL_COLUMN_MONEY:
                case SQL_COLUMN_NULLABLE:
                case SQL_COLUMN_PRECISION:
                case SQL_COLUMN_SCALE:
                case SQL_COLUMN_SEARCHABLE:
                case SQL_COLUMN_TYPE:
                case SQL_COLUMN_UNSIGNED:
                case SQL_COLUMN_UPDATABLE:
                        if( NULL == pfDesc )
                        {
                                strcpy( lpstmt->szSqlState, "S1090" );
                                lpstmt->pszSqlMsg =
                                    "[SQLColAttributes] NULL == pfDesc";
                                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                                LogEntry( LOG_RETURNCODE,
                                          "[SQLColAttributes] SQL_ERROR (%s)",
                                          lpstmt->szSqlState );
                                return SQL_ERROR;
                        }
                        break;
                case SQL_COLUMN_CATALOG_NAME:
                case SQL_COLUMN_QUALIFIER_NAME:
                case SQL_COLUMN_DISTINCT_TYPE:
                case SQL_COLUMN_LABEL:
                case SQL_COLUMN_NAME:
                case SQL_COLUMN_SCHEMA_NAME:
                case SQL_COLUMN_OWNER_NAME:
                case SQL_COLUMN_TABLE_NAME:
                case SQL_COLUMN_TYPE_NAME:
                        if( NULL == rgbDesc || 0 == cbDescMax )
                        {
                                strcpy( lpstmt->szSqlState, "S1090" );
                                lpstmt->pszSqlMsg =
                                    "[SQLColAttributes] NULL == rgbDesc";
                                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                                LogEntry( LOG_RETURNCODE,
                                          "[SQLColAttributes] SQL_ERROR (%s)",
                                          lpstmt->szSqlState );
                                return SQL_ERROR;
                        }
                        break;
                default:
                        strcpy( lpstmt->szSqlState, "S1091" );
                        lpstmt->pszSqlMsg =
                            "[SQLColAttributes] invalid fDescType value";
                        LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                        LogEntry( LOG_RETURNCODE,
                                  "[SQLColAttributes] SQL_ERROR (%s)",
                                  lpstmt->szSqlState );
                        return SQL_ERROR;
        } /* switch */

        /*
        ** check mode
        */
        switch( fDescType )
        {
                case SQL_COLUMN_AUTO_INCREMENT:
                case SQL_COLUMN_MONEY:
                        *pfDesc = FALSE;
                        break;
                case SQL_COLUMN_CASE_SENSITIVE:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                        *pfDesc = TRUE;
                                        break;
                                default:
                                        *pfDesc = FALSE;
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                        *pfDesc = TRUE;
                                        break;
                                default:
                                        *pfDesc = FALSE;
                        }
#endif
                        break;
                case SQL_COLUMN_CATALOG_NAME:
                case SQL_COLUMN_DISTINCT_TYPE:
                case SQL_COLUMN_OWNER_NAME:
                case SQL_COLUMN_QUALIFIER_NAME:
                case SQL_COLUMN_SCHEMA_NAME:
                case SQL_COLUMN_TABLE_NAME:
                        *rgbDesc = '\0';
                        break;
                case SQL_COLUMN_COUNT:
#ifdef mSQL
                        *pfDesc = msqlNumFields( lpstmt->pMsqlResult );
#endif
#ifdef ORACLE
                        *pfDesc = lpstmt->ciCol;
#endif
                        break;
                case SQL_COLUMN_DISPLAY_SIZE:
                case SQL_COLUMN_PRECISION:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                        *pfDesc = pField->length;
                                        break;
                                case INT_TYPE:
                                        *pfDesc = 5;
                                        break;
                                case REAL_TYPE:
                                        *pfDesc = 16;
                                        break;
                                default:
                                        *pfDesc = 0;
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                case INT_TYPE:
                                case NUMBER_TYPE:
                                        *pfDesc = o_cbColSize;
                                        break;
                                default:
                                        *pfDesc = 0;
                        }
#endif
                        break;
                case SQL_COLUMN_LABEL:
                case SQL_COLUMN_NAME:
#ifdef mSQL
                        strncpy( rgbDesc, pField->name, cbDescMax - 1 );
#endif
#ifdef ORACLE
                        strncpy( rgbDesc, o_szColName, cbDescMax - 1 );
#endif
                        if( NULL != pcbDesc )
                        {
                                *pcbDesc = strlen( rgbDesc );
                        }
                        break;
                case SQL_COLUMN_LENGTH:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                case INT_TYPE:
                                case REAL_TYPE:
                                default:
                                        *pfDesc = pField->length;
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                case INT_TYPE:
                                case NUMBER_TYPE:
                                        *pfDesc = o_cbColSize;
                                        break;
                                default:
                                        *pfDesc = 0;
                        }
#endif
                        break;
                case SQL_COLUMN_NULLABLE:
#ifdef mSQL
                        *pfDesc = (IS_NOT_NULL(pField->flags)) ? SQL_NO_NULLS
                                                               : SQL_NULLABLE;
#endif
#ifdef ORACLE
                        *pfDesc = (0 != o_fColNullOk) ? SQL_NULLABLE
                                                      : SQL_NO_NULLS;
#endif
                        break;
                case SQL_COLUMN_SCALE:
#ifdef mSQL
                        *pfDesc = 0;
#endif
#ifdef ORACLE
                        *pfDesc = o_cbColScale;
#endif
                        break;
                case SQL_COLUMN_SEARCHABLE:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                        *pfDesc = SQL_SEARCHABLE;
                                        break;
                                case INT_TYPE:
                                case REAL_TYPE:
                                        *pfDesc = SQL_ALL_EXCEPT_LIKE;
                                        break;
                                default:
                                        *pfDesc = SQL_UNSEARCHABLE;
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                        *pfDesc = SQL_SEARCHABLE;
                                        break;
                                case INT_TYPE:
                                case NUMBER_TYPE:
                                        *pfDesc = SQL_ALL_EXCEPT_LIKE;
                                        break;
                                default:
                                        *pfDesc = SQL_UNSEARCHABLE;
                        }
#endif
                        break;
                case SQL_COLUMN_TYPE:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                        *pfDesc = SQL_CHAR;
                                        break;
                                case INT_TYPE:
                                        *pfDesc = SQL_INTEGER;
                                        break;
                                case REAL_TYPE:
                                        *pfDesc = SQL_REAL;
                                        break;
                                default:
                                        *pfDesc = 0;
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                        *pfDesc = SQL_CHAR;
                                        break;
                                case INT_TYPE:
                                        *pfDesc = SQL_INTEGER;
                                        break;
                                case NUMBER_TYPE:
                                        *pfDesc = SQL_REAL;
                                        break;
                                default:
                                        *pfDesc = 0;
                        }
#endif
                        break;
                case SQL_COLUMN_TYPE_NAME:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                        strncpy( rgbDesc, "CHARacter",
                                                 cbDescMax - 1 );
                                        break;
                                case INT_TYPE:
                                        strncpy( rgbDesc, "INTeger",
                                                 cbDescMax - 1 );
                                        break;
                                case REAL_TYPE:
                                        strncpy( rgbDesc, "REAL",
                                                 cbDescMax - 1 );
                                        break;
                                default:
                                        *rgbDesc = '\0';
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                        strncpy( rgbDesc, "CHARacter",
                                                 cbDescMax - 1 );
                                        break;
                                case INT_TYPE:
                                        strncpy( rgbDesc, "INTeger",
                                                 cbDescMax - 1 );
                                        break;
                                case NUMBER_TYPE:
                                        strncpy( rgbDesc, "REAL",
                                                 cbDescMax - 1 );
                                        break;
                                default:
                                        *rgbDesc = '\0';
                        }
#endif
                        if( NULL != pcbDesc )
                        {
                                *pcbDesc = strlen( rgbDesc );
                        }
                        break;
                case SQL_COLUMN_UNSIGNED:
#ifdef mSQL
                        switch( pField->type )
                        {
                                case CHAR_TYPE:
                                        *pfDesc = TRUE;
                                        break;
                                default:
                                        *pfDesc = FALSE;
                        }
#endif
#ifdef ORACLE
                        switch( o_fColType )
                        {
                                case VARCHAR2_TYPE:
                                        *pfDesc = TRUE;
                                        break;
                                default:
                                        *pfDesc = FALSE;
                        }
#endif
                        break;
                case SQL_COLUMN_UPDATABLE:
                        *pfDesc = SQL_ATTR_READWRITE_UNKNOWN;
                        break;
                default:
                        break;
        } /* switch */

        /*
        ** display results
        */
        LogEntry( LOG_OUTPUT, "[SQLColAttributes] rgbDesc = '%s'\n",
                  (NULL == rgbDesc) ? (char *) "<NULL>" : (char *) rgbDesc );
        LogEntry( LOG_OUTPUT, "[SQLColAttributes] pcbDesc = %5d\n",
                  (NULL == pcbDesc) ? 0 : pcbDesc );
        LogEntry( LOG_OUTPUT, "[SQLColAttributes] pfDesc  = %5d\n",
                  (NULL == pfDesc) ? 0 : pfDesc );

        /*
        ** return success
        */
#ifdef mSQL
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
#endif
        LogEntry( LOG_RETURNCODE, "[SQLColAttributes] SQL_SUCCESS" );
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      Associate a user-supplied buffer with a database column.             */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLBindCol(
        LPSTMT  lpstmt,
        UWORD   icol,
        SWORD   fCType,
        PTR     rgbValue,
        SDWORD  cbValueMax,
        SDWORD FAR *pcbValue)
{                                                /*--------------------------*/
#ifdef mSQL
        int              ci;                     /* index counter            */
        m_field         *pField;                 /* curr. proccessed field   */
#endif
                                                 /*--------------------------*/
        /*
        ** check parameters
        */
        LogEntry( LOG_STATUS, "[SQLBindCol]  lpstmt     = $%08lX", lpstmt     );
        LogEntry( LOG_STATUS, "              icol       =  %5d",   icol       );
        LogEntry( LOG_STATUS, "              fCType     = $%08lX", fCType     );
        LogEntry( LOG_STATUS, "              rgbValue   = $%08lX", rgbValue   );
        LogEntry( LOG_STATUS, "              cbValueMax =  %5d",   cbValueMax );
        LogEntry( LOG_STATUS, "              pcbValue   = $%08lX", pcbValue   );
        if( NULL == lpstmt )
        {
                LogEntry( LOG_ERROR,      "[SQLBindCol] NULL == lpstmt" );
                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }

        /*
        ** set defaults
        */
        if( NULL != pcbValue )
                *pcbValue = 0;

        /*
        ** check query status
        */
#ifdef mSQL
        if( NULL == lpstmt->pszQuery ||
            NULL == lpstmt->pMsqlResult )
#endif
#ifdef ORACLE
        if( NULL == lpstmt->pszQuery )
#endif
        {
                strcpy( lpstmt->szSqlState, "S1010" );
                lpstmt->pszSqlMsg = "[SQLBindCol] no prepared statement";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

#ifdef mSQL
        /*
        ** get infos about the desired column, adapt icol for C arrays (mSQL)
        */
        icol--;
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        if( SQL_MAX_COLUMN <= icol                               ||
            icol           >  msqlNumFields(lpstmt->pMsqlResult) )
        {
                strcpy( lpstmt->szSqlState, "S1002" );
                lpstmt->pszSqlMsg = "[SQLBindCol] invalid column number";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
        ci = icol;
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        while( 0 <= ci && NULL != (pField=msqlFetchField(lpstmt->pMsqlResult)) )
        {
                ci--;
        }
        if( NULL == pField )
        {
                strcpy( lpstmt->szSqlState, "07005" );
                lpstmt->pszSqlMsg = "[SQLBindCol] column not available";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

        /*
        ** check SQL data type (mSQL)
        */
        switch( pField->type )
        {
                case INT_TYPE:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] SQL data type = SQL_INTEGER" );
                        lpstmt->fSqlType[icol] = SQL_INTEGER;
                        break;
                case REAL_TYPE:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] SQL data type = SQL_REAL" );
                        lpstmt->fSqlType[icol] = SQL_REAL;
                        break;
                case CHAR_TYPE:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] SQL data type = SQL_CHAR" );
                        lpstmt->fSqlType[icol] = SQL_CHAR;
                        break;
                default:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] SQL data type = SQL_UNKNOWN" );
                        lpstmt->fSqlType[icol] = SQL_UNKNOWN;
        }

        /*
        ** check C data type (mSQL)
        */
        switch( lpstmt->fCType[icol]=fCType )
        {
                case SQL_C_DEFAULT:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] C data type   = SQL_C_DEFAULT" );
                        lpstmt->fCType[icol]   = lpstmt->fSqlType[icol];
                        lpstmt->cbMaxLen[icol] = pField->length;
                        if( NULL != rgbValue && cbValueMax < lpstmt->cbMaxLen[icol] )
                        {
                                lpstmt->cbMaxLen[icol] = 0;
                                strcpy( lpstmt->szSqlState, "S1090" );
                                lpstmt->pszSqlMsg = "[SQLBindCol] result greater than allowed";
                                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                                          lpstmt->szSqlState );
                                return SQL_ERROR;
                        }
                        break;
                case SQL_C_INTEGER:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] C data type   = SQL_C_INTEGER" );
                        lpstmt->cbMaxLen[icol] = sizeof( int );
                        break;
                case SQL_C_REAL:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] C data type   = SQL_C_REAL" );
                        lpstmt->cbMaxLen[icol] = sizeof( float );
                        break;
                case SQL_C_CHAR:
                case SQL_C_DBCHAR:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] C data type   = SQL_C_CHAR" );
                        switch( lpstmt->fSqlType[icol] )
                        {
                                case SQL_INTEGER:
                                        lpstmt->cbMaxLen[icol] = sizeof(int) / 3 + 1;
                                         break;
                                case SQL_REAL:
                                        lpstmt->cbMaxLen[icol] = 32;
                                        break;
                                case SQL_CHAR:
                                        lpstmt->cbMaxLen[icol] = pField->length;
                                        break;
                                default:
                                        lpstmt->cbMaxLen[icol] = 0;
                        }
                        if( NULL != rgbValue && cbValueMax < lpstmt->cbMaxLen[icol] )
                        {
                                lpstmt->cbMaxLen[icol] = 0;
                                strcpy( lpstmt->szSqlState, "S1090" );
                                lpstmt->pszSqlMsg = "[SQLBindCol] result greater than allowed";
                                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                                          lpstmt->szSqlState );
                                return SQL_ERROR;
                        }
                        break;
                default:
                        LogEntry( LOG_SUMMARY,
                                  "[SQLBindCol] C data type   = SQL_C_UNKNOWN" );
                        lpstmt->fCType[icol] = SQL_C_UNKNOWN;
        }

        /*
        ** valid data types? (mSQL)
        */
        if( SQL_UNKNOWN   == lpstmt->fSqlType[icol] ||
            SQL_C_UNKNOWN == lpstmt->fCType[icol]   )
        {
                lpstmt->pResultVar[icol] = NULL;
                strcpy( lpstmt->szSqlState, "S1003" );
                lpstmt->pszSqlMsg = "[SQLBindCol] unsupported C data type";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

        /*
        ** bind column to variable (mSQL)
        */
        if( NULL != rgbValue )
        {
                lpstmt->pResultVar[icol] = rgbValue;
        }

        /*
        ** set resulting length pointer and initial value (mSQL)
        */
        LogEntry( LOG_SUMMARY,
                  "[SQLBindCol] max. length   = %d", lpstmt->cbMaxLen[icol] );
        if( NULL != pcbValue )
        {
                lpstmt->pResultLen[icol] = pcbValue;
               *pcbValue                 = lpstmt->cbMaxLen[icol];
        }
#endif

#ifdef ORACLE
        /*
        ** bind column to variable (Oracle)
        */

        /*---| check C data type |---*/
        switch( fCType )
        {
                case SQL_C_DEFAULT:
                        fCType = VARCHAR2_TYPE;
                        break;
                case SQL_C_INTEGER:
                        fCType = INT_TYPE;
                        /* cbValueMax = sizeof( int ); */
                        break;
                case SQL_C_REAL:
                        fCType = FLOAT_TYPE;
                        /* cbValueMax = sizeof( float ); */
                        break;
                case SQL_C_CHAR:
                case SQL_C_DBCHAR:
                        fCType = STRING_TYPE;
                        break;
                default:
                        strcpy( lpstmt->szSqlState, "S1003" );
                        lpstmt->pszSqlMsg = "[SQLBindCol] unsupported C data type";
                        LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                        LogEntry( LOG_RETURNCODE,
                                  "[SQLBindCol] SQL_ERROR (%s)",
                                  lpstmt->szSqlState );
                        return SQL_ERROR;
        }

        /*---| initialize result variable |---*/
        if( NULL != pcbValue )
                *pcbValue = 0;

        /*---| bind column to variable |---*/
        if( odefin( &lpstmt->cda, icol, rgbValue, (sword) cbValueMax,
                    fCType, -1, 0, 0, -1, -1, (sb2 *) pcbValue, 0 ) )
        {
                strcpy( lpstmt->szSqlState, "07005" );
                lpstmt->pszSqlMsg = "[SQLBindCol] column not available";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
#endif

        /*
        ** return success
        */
#ifdef mSQL
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
#endif
        LogEntry( LOG_RETURNCODE, "[SQLBindCol] SQL_SUCCESS" );
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      Returns data for bound columns in the current row                    */
/*      ("lpstmt->iCursor"), advances the cursor.                            */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLFetch(
        LPSTMT  lpstmt)
{                                                /*--------------------------*/
#ifdef mSQL
        int              ci;                     /* index counter            */
        m_row            sRow;                   /* curr. processed row      */
#endif
                                                 /*--------------------------*/
        /*
        ** check parameters
        */
        LogEntry( LOG_STATUS, "[SQLFetchl]  lpstmt = $%08lX", lpstmt );
        if( NULL == lpstmt )
        {
                LogEntry( LOG_ERROR,      "[SQLFetch] NULL == lpstmt" );
                LogEntry( LOG_RETURNCODE, "[SQLFetch] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }

        /*
        ** check query status
        */
#ifdef mSQL
        if( NULL == lpstmt->pszQuery ||
            NULL == lpstmt->pMsqlResult )
#endif
#ifdef ORACLE
        if( NULL == lpstmt->pszQuery )
#endif
        {
                strcpy( lpstmt->szSqlState, "S1010" );
                lpstmt->pszSqlMsg = "[SQLFetch] no prepared statement";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLFetch] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }

        /*
        ** get next row
        */
#ifdef mSQL
        if( NULL == (sRow=msqlFetchRow(lpstmt->pMsqlResult)) )
#endif
#ifdef ORACLE
        lpstmt->cda.rc = 0;
        if( ofetch(&lpstmt->cda) && 1403 != lpstmt->cda.rc
                                 && 1405 != lpstmt->cda.rc
                                 && 1406 != lpstmt->cda.rc )
        {
                strcpy( lpstmt->szSqlState, "58004" );
                lpstmt->pszSqlMsg = "[SQLFetch] can't get data";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLFetch] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
        if( 1403 == lpstmt->cda.rc )
#endif
        {
                LogEntry( LOG_RETURNCODE, "[SQLFetch] SQL_NO_DATA_FOUND" );
                return SQL_NO_DATA_FOUND;
        }

#ifdef mSQL
        /*
        ** process columns (mSQL)
        */
        ci = 0;
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
        for( ci = 0;
             ci < SQL_MAX_COLUMN && ci < msqlNumFields(lpstmt->pMsqlResult);
             ci++
           )
        {
                /*---| pointers okay? |---*/
                if( NULL == lpstmt->pResultVar[ci] )
                {
                        LogEntry( LOG_WARNING,
                                  "[SQLFetch] invalid pointer for column %d",
                                  ci+1
                                );
                        continue;                /* NO! */
                }

                /*---| is data available? |---*/
                if( NULL == sRow[ci] )
                {
                        LogEntry( LOG_SUMMARY,
                                  "[SQLFetch] NULL statement in column %d",
                                  ci+1
                                );
                        if( NULL != lpstmt->pResultLen[ci] )
                        {
                                *(lpstmt->pResultLen[ci]) = SQL_NULL_DATA;
                        }
                        switch( lpstmt->fCType[ci] )
                        {
                                case SQL_C_INTEGER:
                                        LogEntry( LOG_SUMMARY,
                                                  "           (SQL_C_INTEGER)"
                                                );
                                        memset( lpstmt->pResultVar[ci],
                                                0, sizeof(int) );
                                        break;
                                case SQL_C_REAL:
                                        LogEntry( LOG_SUMMARY,
                                                  "           (SQL_C_REAL)"
                                                );
                                        memset( lpstmt->pResultVar[ci],
                                                0, sizeof(float) );
                                        break;
                                case SQL_C_CHAR:
                                case SQL_C_DBCHAR:
                                        LogEntry( LOG_SUMMARY,
                                                  "           (SQL_C_(DB)CHAR)"
                                                );
                                default:
                                        *((char *)lpstmt->pResultVar[ci]) = '\0';
                                        /*------------------------------------
                                         * enable this in order to fill the
                                         * complete destination buffer with 0s
                                         *------------------------------------
                                         * memset( lpstmt->pResultVar[ci],
                                         *         0, lpstmt->cbMaxLen[ci] );
                                         *------------------------------------
                                         */
                        }
                }
                /*---| copy data |---*/
                else switch( lpstmt->fSqlType[ci] )
                {
                        /*
                         * all data can be treated equally since
                         * the mSQL server sends all data as ascii
                         * strings :-)
                         */
                        case SQL_INTEGER:
                        case SQL_REAL:
                        case SQL_CHAR:
                                LogEntry( LOG_OUTPUT,
                                          "[SQLFetch] col %d -> %s",
                                          ci + 1, sRow[ci]
                                        );
                                switch( lpstmt->fCType[ci] )
                                {
                                        case SQL_C_INTEGER:
                                                *((int *)lpstmt->pResultVar[ci]) =
                                                    atoi(sRow[ci]);
                                                if( NULL !=
                                                    lpstmt->pResultLen[ci] )
                                                {
                                                        *(lpstmt->pResultLen[ci]) =
                                                            sizeof( int );
                                                }
                                                break;
                                        case SQL_C_REAL:
                                                sscanf( sRow[ci], "%g",
                                                        lpstmt->pResultVar[ci]
                                                      );
                                                if( NULL !=
                                                    lpstmt->pResultLen[ci] )
                                                {
                                                        *(lpstmt->pResultLen[ci]) =
                                                            sizeof( float );
                                                }
                                                break;
                                        case SQL_C_CHAR:
                                        case SQL_C_DBCHAR:
                                                strncpy( lpstmt->pResultVar[ci],
                                                         sRow[ci],
                                                         lpstmt->cbMaxLen[ci] );
                                                if( NULL !=
                                                    lpstmt->pResultLen[ci] )
                                                {
                                                        *(lpstmt->pResultLen[ci]) =
                                                            strlen(lpstmt->pResultVar[ci]);
                                                }
                                        default:
                                                if( NULL !=
                                                    lpstmt->pResultLen[ci] )
                                                {
                                                        *(lpstmt->pResultLen[ci]) =
                                                            SQL_NULL_DATA;
                                                }
                                }
                                break;
                        default:
                                LogEntry( LOG_WARNING,
                                          "[SQLFetch] invalid type %d in col %d",
                                          lpstmt->fSqlType[ci], ci + 1
                                        );
                                if( NULL != lpstmt->pResultLen[ci] )
                                {
                                        *(lpstmt->pResultLen[ci]) = SQL_NULL_DATA;
                                }
                }
        }

        /*
        ** set other binding variables (mSQL)
        */
        LogEntry( LOG_SUMMARY,
                  "[SQLFetch] columns with result parameters = %d", ci );
        for( ; ci < SQL_MAX_COLUMN; ci++ )
        {
                /*---| pointers okay? |---*/
                if( NULL == lpstmt->pResultVar[ci] )
                {
                        continue;                /* NO! */
                }

                /*---| set pointers |---*/
                if( NULL != lpstmt->pResultLen[ci] )
                {
                        *(lpstmt->pResultLen[ci]) = SQL_NULL_DATA;
                }
                switch( lpstmt->fCType[ci] )
                {
                        case SQL_C_INTEGER:
                                memset( lpstmt->pResultVar[ci], 0, sizeof(int) );
                                break;
                        case SQL_C_REAL:
                                memset( lpstmt->pResultVar[ci], 0, sizeof(float) );
                                break;
                        case SQL_C_CHAR:
                        default:
                                *((char *)lpstmt->pResultVar[ci]) = '\0';
                                /*--------------------------------------------
                                 * enable this in order to fill the complete
                                 * destination buffer with zeros (0s)
                                 *--------------------------------------------
                                 * memset( lpstmt->pResultVar[ci],
                                 *         0, lpstmt->cbMaxLen[ci] );
                                 *--------------------------------------------
                                 */
                }
        }
        LogEntry( LOG_SUMMARY,
                  "[SQLFetch] columns total                  = %d", ci );
#endif

        /*
        ** return success
        */
#ifdef mSQL
        msqlFieldSeek( lpstmt->pMsqlResult, 0 );
#endif
        LogEntry( LOG_RETURNCODE, "[SQLFetch] SQL_SUCCESS" );
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      Returns result data for a single column in the current row.          */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLGetData(
        LPSTMT  lpstmt,
        UWORD   icol,
        SWORD   fCType,
        PTR     rgbValue,
        SDWORD  cbValueMax,
        SDWORD FAR *pcbValue)
{
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      This determines whether there are more results sets available for    */
/*      the "lpstmt".                                                        */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLMoreResults(
        LPSTMT  lpstmt)
{
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      This returns the number of rows associated with the database         */
/*      attached to "lpstmt".                                                */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLRowCount(
        LPSTMT  lpstmt,
        SDWORD FAR *pcrow)
{
        /*
        ** check parameter
        */
        LogEntry( LOG_STATUS, "[SQLRowCount]  lpstmt = $%08lX", lpstmt );
        LogEntry( LOG_STATUS, "              *pcrow  = $%08lX", pcrow  );
        if( NULL == lpstmt )
        {
                LogEntry( LOG_ERROR,      "[SQLRowCount] NULL == lpstmt" );
                LogEntry( LOG_RETURNCODE, "[SQLRowCount] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }
        if( NULL == pcrow )
        {
                strcpy( lpstmt->szSqlState, "S1009" );
                lpstmt->pszSqlMsg = "[SQLRowCount] pcrow must not be NULL";
                LogEntry( LOG_ERROR, lpstmt->pszSqlMsg );
                LogEntry( LOG_RETURNCODE, "[SQLRowCount] SQL_ERROR (%s)",
                          lpstmt->szSqlState );
                return SQL_ERROR;
        }
        *pcrow = 0;

        /*
        ** get number of result columns
        */
#ifdef mSQL
        if( NULL != lpstmt->pMsqlResult )
        {
                *pcrow = msqlNumRows( lpstmt->pMsqlResult );
                LogEntry( LOG_OUTPUT, "[SQLRowCount] rows    = %d", *pcrow );
        }
#endif
#ifdef ORACLE
        *pcrow = lpstmt->cda.rpc;
#endif

        /*
        ** return success
        */
        LogEntry( LOG_RETURNCODE, "[SQLRowCount] SQL_SUCCESS" );
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      This positions the cursor within a block of data.                    */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLSetPos(
        LPSTMT  lpstmt,
        UWORD   irow,
        BOOL    fRefresh,
        BOOL    fLock)
{
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      This fetchs a block of data (rowset).                                */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLExtendedFetch(
        LPSTMT  lpstmt,
        UWORD   fFetchType,
        SDWORD  irow,
        UDWORD FAR *pcrow,
        UWORD FAR *rgfRowStatus)
{
        return SQL_SUCCESS;
}


/*---------------------------------------------------------------------------*/
/*      Returns the next SQL error information.                              */
/*---------------------------------------------------------------------------*/
RETCODE SQL_API SQLError(
        LPENV   lpenv,
        LPDBC   lpdbc,
        LPSTMT  lpstmt,
        UCHAR FAR *szSqlState,
        SDWORD FAR *pfNativeError,
        UCHAR FAR *szErrorMsg,
        SWORD   cbErrorMsgMax,
        SWORD FAR *pcbErrorMsg)
{                                                /*--------------------------*/
        char    *pszState       = NULL;          /* pointer to status code   */
        char    *pszErrMsg      = NULL;          /* pointer to error message */
#ifdef mSQL
        char    *pszMsqlMsg     = NULL;          /* pointer to mSQL message  */
#endif
#ifdef ORACLE
        char     szOraErr[512];                  /* Oracle error message     */
#endif
                                                 /*--------------------------*/
        /*
        ** check parameter
        */
        LogEntry( LOG_STATUS, "[SQLError] lpenv         = $%08lX", lpenv  );
        LogEntry( LOG_STATUS, "           lpdbc         = $%08lX", lpdbc  );
        LogEntry( LOG_STATUS, "           lpstmt        = $%08lX", lpstmt );
        LogEntry( LOG_STATUS, "           szSqlState    = $%08lX", szSqlState );
        LogEntry( LOG_STATUS, "           pfNativeError = $%08lX",
                  pfNativeError
                );
        LogEntry( LOG_STATUS, "           szErrorMsg    = $%08lX", szErrorMsg );
        LogEntry( LOG_STATUS, "           cbErrorMsgMax =  %d", cbErrorMsgMax );
        LogEntry( LOG_STATUS, "           pcbErrorMsg   = $%08lX", pcbErrorMsg);

        pszState        =
        pszErrMsg       = NULL;

#ifdef ORACLE
        szOraErr[0]     = '\0';
#endif

        /*---| environment |---*/
        if( NULL != lpenv )
        {
                pszState          = &lpenv->szSqlState[0];
                pszErrMsg         =  lpenv->pszSqlMsg;
                lpenv->pszSqlMsg  = NULL;
#ifdef mSQL
                pszMsqlMsg        = NULL;
#endif
        }

        /*---| database context |---*/
        if( NULL != lpdbc )
        {
                pszState          = &lpdbc->szSqlState[0];
                pszErrMsg         =  lpdbc->pszSqlMsg;
                lpdbc->pszSqlMsg  = NULL;
#ifdef mSQL
                pszMsqlMsg        = &lpdbc->szMsqlErrorMsg[0];
#endif
        }

        /*---| statement |---*/
        if( NULL != lpstmt )
        {
                pszState          = &lpstmt->szSqlState[0];
                pszErrMsg         =  lpstmt->pszSqlMsg;
                lpstmt->pszSqlMsg = NULL;
#ifdef mSQL
                pszMsqlMsg        =  lpstmt->szMsqlErrorMsg;
#endif
#ifdef ORACLE
                if( NULL != lpstmt->pSqlDbc )
                {
                        oerhms( &lpstmt->pSqlDbc->lda, lpstmt->cda.rc,
                                &szOraErr[0], sizeof(szOraErr) );
                }
#endif
        }

        /*---| check pointers |---*/
        if( NULL == pszState )
        {
                LogEntry( LOG_ERROR, "[SQLError] no valid handle(s)" );
                LogEntry( LOG_RETURNCODE, "[SQLError] SQL_INVALID_HANDLE" );
                return SQL_INVALID_HANDLE;
        }

        /*
        ** check status
        */
        if( NULL == pszErrMsg )
        {
#ifdef mSQL
                /*---| reset mSQL message buffer |---*/
                if( NULL != pszMsqlMsg )
                {
                        *pszMsqlMsg = '\0';
                }
#endif

                /*---| reset status code |---*/
                strcpy( pszState, "00000" );

                /*---| return status code |---*/
                if( NULL != szSqlState )
                {
                        strcpy( szSqlState, pszState );
                }

                /*---| return internal code |---*/
                if( NULL != pfNativeError )
                {
                        *pfNativeError = 0;
                }

                /*---| return message |---*/
                if( NULL != szErrorMsg && 0 < cbErrorMsgMax )
                {
                        *szErrorMsg = '\0';
                        if( NULL != pcbErrorMsg )
                        {
                                *pcbErrorMsg = 0;
                        }
                }

                /*---| return data |---*/
                LogEntry( LOG_RETURNCODE, "[SQLError] SQL_NO_DATA_FOUND" );
                return SQL_NO_DATA_FOUND;
        }

        /*
        ** return data on errors
        */
        /*---| return status code |---*/
        if( NULL != szSqlState )
        {
                strcpy( szSqlState, pszState );
        }

        /*---| return internal code |---*/
        if( NULL != pfNativeError )
        {
                *pfNativeError = 0;
        }

        /*---| return message |---*/
        if( NULL != szErrorMsg && 0 < cbErrorMsgMax )
        {                                        /*--------------------------*/
                register int    ci;              /* counter variable         */
                                                 /*--------------------------*/
                /*---| initialize buffer |---*/
                ci  = 0;
#ifdef mSQL
                strncpy( szErrorMsg, "[mSQL]", cbErrorMsgMax );
                ci += 6;
#endif
#ifdef ORACLE
                strncpy( szErrorMsg, "[Oracle]", cbErrorMsgMax );
                ci += 8;
#endif

                /*---| add message |---*/
                if( cbErrorMsgMax > ci )
                {
                        strncat( szErrorMsg, pszErrMsg, cbErrorMsgMax - ci );
                        ci += strlen( pszErrMsg );
                }

                /*---| additional info |---*/
#ifdef mSQL
                if( NULL          !=  pszMsqlMsg &&
                    '\0'          != *pszMsqlMsg &&
                    cbErrorMsgMax  >  (ci + 4 + strlen(pszMsqlMsg))
                  )
                {
                        sprintf( &szErrorMsg[ci], " (%s)", pszMsqlMsg );
                        ci  = strlen( szErrorMsg );
                }
#endif
#ifdef ORACLE
                if( '\0' != szOraErr[0] )
                {
                        szErrorMsg[ci++] = ' ';
                        szErrorMsg[ci++] = '(';
                        strncat( szErrorMsg, szOraErr, cbErrorMsgMax - ci );
                        ci += strlen( szOraErr );
                        if( '\n' == szErrorMsg[ci-1] )
                                ci--;
                        szErrorMsg[ci++] = ')';
                        szErrorMsg[ci]   = '\0';
                }
#endif

                /*---| set string length |---*/
                if( NULL != pcbErrorMsg )
                {
                        *pcbErrorMsg = ci;
                }

        } /* if */

        /*---| reset mSQL message buffer |---*/
#ifdef mSQL
        if( NULL != pszMsqlMsg )
        {
                *pszMsqlMsg = '\0';
        }
#endif

        /*---| return data |---*/
        LogEntry( LOG_RETURNCODE, "[SQLError] SQL_SUCCESS" );
        return SQL_SUCCESS;
}

/*===| end of file |=========================================================*/
