You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ma...@apache.org on 2015/07/15 11:42:42 UTC

[09/14] incubator-kylin git commit: add odbc driver to maven repository

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d1dcfd15/odbc/Driver/KO_FETCH.CPP
----------------------------------------------------------------------
diff --git a/odbc/Driver/KO_FETCH.CPP b/odbc/Driver/KO_FETCH.CPP
new file mode 100644
index 0000000..5859eb5
--- /dev/null
+++ b/odbc/Driver/KO_FETCH.CPP
@@ -0,0 +1,1213 @@
+
+// ----------------------------------------------------------------------------
+//
+// File:    KO_FETCH.CPP
+//
+// Purpose:     Contains function for fetching results.
+//              As explained in the article ODBC has a
+//              defined way in which the data is made available.
+//
+//              1. The client CAN obtain general details
+//              about the result like num of rows etc using
+//              SQLRowCount, SQLNumResultCols.
+//
+//              2. It obtains metadata about the result
+//              more specifically info about columns like
+//              size type etc using SQLColAttribute or
+//              SQLDescribeCol.
+//
+//              3. Then it allocates and bind the buffer
+//              specifying the other info like buffer size
+//              etc for the cols it desires to extract using
+//              SQLBindCol
+//
+//              4. Then it instructs the driver to feed these
+//              buffers using SQLFetch or SQLExtendedFetch.
+//
+//              5. This is the general way. In case the data
+//              involved is quite large, it can be extracted
+//              piecemeal using SQLGetData. SQLPutData is the
+//              funcion corresponding to SQLGetData to specify
+//              large param values say storing images etc.
+//              Since I have not implemented params or long
+//              data read write in this sample, SQLPutData resides
+//              in this file with SQLGetData.
+//
+//              All fetch occur via the local function _SQLFetch.
+//              Internally the fetch is executed in the following
+//              way.
+//              1. The rowdesc from server (IRD) and appl (ARD )
+//                 is obtained.
+//              2. Main loop to fetch rowset number of rows. More
+//                 than one row can be fetched at a time. The movement
+//                 in resulset is done using _SQLFetchMoveNext.
+//              3. For each row, loop through each ARD item to
+//                 extract the col(s) required by the client.
+//
+//              SQLColConvert and associated funtions _SQLCopyCharData,
+//              SQLCopyNumData, _SQLCopyDateTimeData r used to perform
+//              necessary conversion between data as recived from the
+//              server and data as required by the client.
+//
+// Exported functions:
+//                       SQLColAttribute
+//                       SQLDescribeCol
+//                       SQLBindCol
+//                       SQLNumResultCols
+//                       SQLRowCount
+//                       SQLFetch
+//                       SQLExtendedFetch
+//                       SQLFetchScroll
+//                       SQLGetData
+//                       SQLPutData
+//                       SQLMoreResults
+//                       SQLNativeSql
+//
+// ----------------------------------------------------------------------------
+#include "stdafx.h"
+
+#include "Dump.h"
+
+// ------------------------- local functions -----------------------------
+RETCODE SQL_API     _SQLFetch ( pODBCStmt pStmt, Word pFetchOrientation, Long pFetchOffset, ULong* pRowCountPtr,
+                                UWord* pRowStatusArray );
+RETCODE SQL_API     _SQLColConvert ( pODBCStmt pStmt, void* pTgtDataPtr, Long* pTgtDataSizePtr, CStrPtr pSrcColData,
+                                     pARDItem pARDCol , bool isSigned );
+RETCODE SQL_API     _SQLFetchMoveNext ( pODBCStmt pStmt );
+RETCODE SQL_API     _SQLResetRowPos ( pODBCStmt pStmt );
+
+SQLRowContent* GetIfExist ( std::vector<SQLRowContent*>& container, int index );
+
+// -----------------------------------------------------------------------
+// to get specific detail//attribute about a col returned from server --- FROM IRD
+// kylin specific
+// -----------------------------------------------------------------------
+
+
+RETCODE  _SQLColAttribute_basic ( SQLHSTMT        pStmt,
+                                  SQLUSMALLINT    pColNum,
+                                  SQLUSMALLINT    pFldID,
+                                  SQLPOINTER      pDataPtr,
+                                  SQLSMALLINT     pDataSize,
+                                  SQLSMALLINT*    pDataSizePtr, // in bytes
+                                  SQLPOINTER      pNumValuePtr ,// integer
+                                  bool isANSI
+                                ) { //if returned data is numeric, feed this
+    Long            n;
+    SQLResponse*    ird;
+    pIRDItem        col;
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    
+    // precaution
+    if ( pColNum == 0 ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLColAttribute", "01000", -1, "bad params" );
+        return SQL_ERROR;
+    }
+    
+    // get the row descriptor obtained with response
+    ird = ( ( ( pODBCStmt ) pStmt )->IRD ).RowDesc.get();
+    
+    // check
+    if ( ird == NULL ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLColAttribute", "01000", -1, "No resultset or no col descriptors" );
+        return SQL_ERROR;
+    }
+    
+    // find the xth element/col
+    col = _SQLGetIRDItem ( & ( ( ( pODBCStmt ) pStmt )->IRD ), pColNum );
+    
+    // check
+    if ( col == NULL ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLColAttribute", "01000", -1, "Invalid col num" );
+        return SQL_ERROR;
+    }
+    
+    // get value from descriptor as per field type
+    switch ( pFldID ) {
+        // numeric types clubbed together
+        case SQL_DESC_AUTO_UNIQUE_VALUE:                // is col auto-incrementing
+        case SQL_DESC_CASE_SENSITIVE:                   // is col case-insensitive
+        case SQL_DESC_TYPE:                             // verbose type
+        case SQL_DESC_CONCISE_TYPE:                     // concise type
+        case SQL_DESC_COUNT:                            // no.of highest bound column
+        case SQL_DESC_LENGTH:
+        case SQL_DESC_DISPLAY_SIZE:
+        case SQL_DESC_OCTET_LENGTH:
+        case SQL_DESC_FIXED_PREC_SCALE:
+        case SQL_DESC_NULLABLE:
+        case SQL_DESC_NUM_PREC_RADIX:
+        case SQL_DESC_PRECISION:
+        case SQL_DESC_SCALE:
+        case SQL_DESC_SEARCHABLE:
+        case SQL_DESC_UNNAMED:
+        case SQL_DESC_UNSIGNED:
+        case SQL_DESC_UPDATABLE:
+            _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, pFldID, pNumValuePtr, -1, NULL , isANSI );
+            break;
+            
+        // char types clubbed together
+        
+        case SQL_DESC_BASE_TABLE_NAME:                  // table name for column
+        case SQL_DESC_CATALOG_NAME:                     // database name
+        case SQL_DESC_LITERAL_PREFIX:
+        case SQL_DESC_LITERAL_SUFFIX:
+        case SQL_DESC_LOCAL_TYPE_NAME:
+        case SQL_DESC_TYPE_NAME:
+        case SQL_DESC_SCHEMA_NAME:
+        case SQL_DESC_TABLE_NAME:
+            _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, pFldID, pDataPtr, pDataSize,
+                                  pDataSizePtr ? &n : NULL, isANSI );
+                                  
+            if ( pDataSizePtr )
+            { *pDataSizePtr = ( Word ) n; }
+            
+            break;
+            
+        case SQL_DESC_BASE_COLUMN_NAME:
+        case SQL_DESC_LABEL:
+        case SQL_DESC_NAME:
+            // ////
+            // as a special case the name length may be required without the actual name
+            //////
+            StrPtr cname;
+            Word   cnamesize;
+            
+            if ( pDataPtr ) {
+                cname       = ( StrPtr ) pDataPtr;
+                cnamesize   = pDataSize;
+            }
+            
+            else {
+                cname       = new Char[256];             // arbitary
+                cnamesize   = 255;
+            }
+            
+            _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, pFldID, cname, cnamesize,
+                                  pDataSizePtr ? &n : NULL, isANSI );
+                                  
+            if ( pDataPtr == NULL )
+            { delete[] cname; }
+            
+            if ( pDataSizePtr )
+            { *pDataSizePtr = ( Word ) n; }
+            
+            break;
+            
+        default:
+            __ODBCPOPMSG ( _ODBCPopMsg ( "SQLColAttribute unknown attr, ColNum: %d, FldID: %d\n", pColNum, pFldID ) );
+            return SQL_ERROR;
+    }
+    
+    return SQL_SUCCESS;
+}
+
+
+#ifdef _WIN64
+RETCODE SQL_API SQLColAttributeW ( SQLHSTMT        pStmt,
+                                   SQLUSMALLINT    pColNum,
+                                   SQLUSMALLINT    pFldID,
+                                   SQLPOINTER      pDataPtr,
+                                   SQLSMALLINT     pDataSize,
+                                   SQLSMALLINT*    pDataSizePtr,
+                                   SQLLEN*     pNumValuePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLColAttributeW called, ColNum: %d, FldID: %d", pColNum, pFldID ) );
+    RETCODE code =  _SQLColAttribute_basic ( pStmt, pColNum, pFldID, pDataPtr, pDataSize, pDataSizePtr, pNumValuePtr,
+                                             false );
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "the return code is %d", code ) );
+    return code;
+}
+
+RETCODE SQL_API SQLColAttribute ( SQLHSTMT        pStmt,
+                                  SQLUSMALLINT    pColNum,
+                                  SQLUSMALLINT    pFldID,
+                                  SQLPOINTER      pDataPtr,
+                                  SQLSMALLINT     pDataSize,
+                                  SQLSMALLINT*    pDataSizePtr,
+                                  SQLLEN*      pNumValuePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLColAttributeW called, ColNum: %d, FldID: %d", pColNum, pFldID ) );
+    return _SQLColAttribute_basic ( pStmt, pColNum, pFldID, pDataPtr, pDataSize, pDataSizePtr, pNumValuePtr, true );
+}
+
+#else
+RETCODE SQL_API SQLColAttributeW ( SQLHSTMT        pStmt,
+                                   SQLUSMALLINT    pColNum,
+                                   SQLUSMALLINT    pFldID,
+                                   SQLPOINTER      pDataPtr,
+                                   SQLSMALLINT     pDataSize,
+                                   SQLSMALLINT*    pDataSizePtr,
+                                   SQLPOINTER      pNumValuePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLColAttributeW called, ColNum: %d, FldID: %d", pColNum, pFldID ) );
+    RETCODE code =  _SQLColAttribute_basic ( pStmt, pColNum, pFldID, pDataPtr, pDataSize, pDataSizePtr, pNumValuePtr,
+                                             false );
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "the return code is %d", code ) );
+    return code;
+}
+
+RETCODE SQL_API SQLColAttribute ( SQLHSTMT        pStmt,
+                                  SQLUSMALLINT    pColNum,
+                                  SQLUSMALLINT    pFldID,
+                                  SQLPOINTER      pDataPtr,
+                                  SQLSMALLINT     pDataSize,
+                                  SQLSMALLINT*    pDataSizePtr,
+                                  SQLPOINTER      pNumValuePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLColAttributeW called, ColNum: %d, FldID: %d", pColNum, pFldID ) );
+    return _SQLColAttribute_basic ( pStmt, pColNum, pFldID, pDataPtr, pDataSize, pDataSizePtr, pNumValuePtr, true );
+}
+#endif
+
+// ----------------------------------------------------------------------
+// to get the basic set of ARD col attributes, ie details recd. from server --- FROM IRD
+// SQLDescribeCol returns the result descriptor �� column name,type, column size, decimal digits, and nullability (from msdn)
+// kylin specific
+// ----------------------------------------------------------------------
+
+SQLRETURN SQL_API _SQLDescribeCol_basic ( SQLHSTMT        pStmt,
+                                          SQLUSMALLINT    pColNum,
+                                          void*        pColNamePtr,
+                                          SQLSMALLINT     pColNameSize,
+                                          SQLSMALLINT*    pColNameSizePtr,
+                                          SQLSMALLINT*    pDataTypePtr,
+                                          SQLULEN*        pColSizePtr,
+                                          SQLSMALLINT*    pDecimalDigitsPtr,
+                                          SQLSMALLINT*    pNullablePtr ,
+                                          bool isANSI
+                                        ) {
+    Long            n;
+    SQLResponse*        ird;
+    pIRDItem        col;
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    
+    // precaution
+    if ( pColNum == 0 ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLDescribeCol", "01000", -1, "bad params" );
+        return SQL_ERROR;
+    }
+    
+    // get the row descriptor obtained with response
+    ird = ( ( ( pODBCStmt ) pStmt )->IRD ).RowDesc.get();
+    
+    // check
+    if ( ird == NULL ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLDescribeCol", "01000", -1, "No resultset or no col descriptors" );
+        return SQL_ERROR;
+    }
+    
+    // find the xth element/col
+    col = _SQLGetIRDItem ( & ( ( ( pODBCStmt ) pStmt )->IRD ), pColNum );
+    
+    // check
+    if ( col == NULL ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLDescribeCol", "01000", -1, "Invalid col num" );
+        return SQL_ERROR;
+    }
+    
+    // COL-NAME ie title
+    
+    if ( pColNamePtr ) {
+        _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, SQL_DESC_BASE_COLUMN_NAME, pColNamePtr,
+                              pColNameSize, pColNameSizePtr ? &n : NULL, isANSI );
+                              
+        if ( pColNameSizePtr )
+        { *pColNameSizePtr = ( Word ) n; }
+        
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "name: %s", pColNamePtr ) );
+    }
+    
+    // COL-DATA TYPE
+    
+    if ( pDataTypePtr ) {
+        _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, SQL_DESC_CONCISE_TYPE, pDataTypePtr, -1,
+                              NULL, isANSI );
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "data type: %d", *pDataTypePtr ) );
+    }
+    
+    // COL-SIZE
+    
+    if ( pColSizePtr ) {
+        _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, SQL_DESC_LENGTH, pColSizePtr, -1, NULL,
+                              isANSI );
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "column size: %d", *pColSizePtr ) );
+    }
+    
+    // COL-DECIMAL
+    
+    if ( pDecimalDigitsPtr ) {
+        _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, SQL_DESC_SCALE, pDecimalDigitsPtr, -1, NULL,
+                              isANSI );
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "decimal scale: %d", *pDecimalDigitsPtr ) );
+    }
+    
+    // COL-NULLABLE
+    
+    if ( pNullablePtr ) {
+        _SQLGetIRDItemField ( & ( ( ( pODBCStmt ) pStmt )->IRD ), col, pColNum, SQL_DESC_NULLABLE, pNullablePtr, -1, NULL,
+                              isANSI );
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "nullable: %d", *pNullablePtr ) );
+    }
+    
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLDescribeCol returned" ) );
+    return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLDescribeColW ( SQLHSTMT        pStmt,
+                                    SQLUSMALLINT    pColNum,
+                                    SQLWCHAR*        pColNamePtr,
+                                    SQLSMALLINT     pColNameSize,
+                                    SQLSMALLINT*    pColNameSizePtr,
+                                    SQLSMALLINT*    pDataTypePtr,
+                                    SQLULEN*        pColSizePtr,
+                                    SQLSMALLINT*    pDecimalDigitsPtr,
+                                    SQLSMALLINT*    pNullablePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG,
+                              "SQLDescribeColW. Col: %d, ColNamePtr: %d, ColNameSize: %d, ColNameSizePtr: %d, DataTypePtr: %d, ColSizePtr: %d, DecDigitsPtr: %d, NullPtr: %d",
+                              pColNum, pColNamePtr, pColNameSize, pColNameSizePtr, pDataTypePtr, pColSizePtr, pDecimalDigitsPtr, pNullablePtr ) );
+    return _SQLDescribeCol_basic ( pStmt, pColNum, pColNamePtr, pColNameSize, pColNameSizePtr, pDataTypePtr, pColSizePtr,
+                                   pDecimalDigitsPtr, pNullablePtr , false );
+}
+
+SQLRETURN SQL_API SQLDescribeCol ( SQLHSTMT        pStmt,
+                                   SQLUSMALLINT    pColNum,
+                                   SQLCHAR*        pColNamePtr,
+                                   SQLSMALLINT     pColNameSize,
+                                   SQLSMALLINT*    pColNameSizePtr,
+                                   SQLSMALLINT*    pDataTypePtr,
+                                   SQLULEN*        pColSizePtr,
+                                   SQLSMALLINT*    pDecimalDigitsPtr,
+                                   SQLSMALLINT*    pNullablePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG,
+                              "SQLDescribeCol. Col: %d, ColNamePtr: %d, ColNameSize: %d, ColNameSizePtr: %d, DataTypePtr: %d, ColSizePtr: %d, DecDigitsPtr: %d, NullPtr: %d",
+                              pColNum, pColNamePtr, pColNameSize, pColNameSizePtr, pDataTypePtr, pColSizePtr, pDecimalDigitsPtr, pNullablePtr ) );
+    return _SQLDescribeCol_basic ( pStmt, pColNum, pColNamePtr, pColNameSize, pColNameSizePtr, pDataTypePtr, pColSizePtr,
+                                   pDecimalDigitsPtr, pNullablePtr , true );
+}
+
+// -----------------------------------------------------------------------
+// to bind a column to with details from application --- TO ARD
+// kylin specific, no chagne required
+// -----------------------------------------------------------------------
+
+/*
+
+    From msdn:
+
+    SQLRETURN SQLBindCol(
+    SQLHSTMT       StatementHandle,
+    SQLUSMALLINT   ColumnNumber,
+    SQLSMALLINT    TargetType,
+    SQLPOINTER     TargetValuePtr,
+    SQLLEN         BufferLength,
+    SQLLEN *       StrLen_or_Ind);
+
+*/
+RETCODE SQL_API SQLBindCol ( SQLHSTMT        pStmt,
+                             SQLUSMALLINT    pColNum,
+                             SQLSMALLINT     pDataType,
+                             SQLPOINTER      pDataPtr,
+                             SQLLEN      pDataSize,
+                             SQLLEN*         pDataSizePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLBindCol called, ColNum: %d, TgtType: %d, ValuePtr: %d, Capacity: %d",
+                              pColNum, pDataType, pDataPtr, pDataSize ) );
+    pODBCARD         ard;                            // application row descriptor
+    pARDItem     ardcol;                         // application row descriptor item
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    // extract the appl. row descriptor from stmt
+    ard = & ( ( ( pODBCStmt ) pStmt )->ARD );
+    // get the specified column if already bound
+    ardcol = _SQLGetARDItem ( ard, pColNum );
+    
+    // EXISTS
+    
+    if ( ardcol != NULL ) {
+        // check if total unbind is required
+        if ( pDataPtr == NULL && pDataSizePtr == NULL ) {
+            // detach it from ARD link list
+            _SQLDetachARDItem ( ard, ardcol );
+            // free
+            delete ardcol;
+        }
+        
+        else  {
+            // unbind/rebind col details
+            _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_DATA_PTR, pDataPtr, -1 );
+            _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_CONCISE_TYPE, ( void* ) pDataType, -1 );
+            _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_LENGTH, ( void* ) pDataSize, -1 );
+            _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_OCTET_LENGTH_PTR, pDataSizePtr, -1 );
+            // reset the source data type
+            ardcol->SrcDataType     = 0;
+        }
+        
+        return SQL_SUCCESS;
+    }
+    
+    // DOES NOT EXIST
+    
+    // check for bad params
+    if ( pDataPtr == NULL && pDataSizePtr == NULL ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLBindCol", "01000", -1, "Bad params" );
+        return SQL_ERROR;
+    }
+    
+    // check for bad params
+    else if ( pDataSize < 0 ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLBindCol", "01000", -1, "Invalid buffer length" );
+        return SQL_ERROR;
+    }
+    
+    // CREATE
+    // allocate a new col-item
+    ardcol = new ARDItem;
+    // reset
+    _SQLSetARDItemFieldsDefault ( ardcol, pColNum );
+    // set all values - bind
+    _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_DATA_PTR, pDataPtr, -1 );
+    _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_CONCISE_TYPE, ( void* ) pDataType, -1 );
+    _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_LENGTH, ( void* ) pDataSize, -1 );
+    _SQLSetARDItemField ( ard, ardcol, pColNum, SQL_DESC_OCTET_LENGTH_PTR, pDataSizePtr, -1 );
+    // attach it to link list
+    _SQLAttachARDItem ( ard, ardcol );
+    return SQL_SUCCESS;
+}
+
+
+// ---------------------------------------------------------------------
+// to get the number of columns in result --- COUNTING ELEMENTS IN IRD.ROWDESC
+// Kylin specific
+// ---------------------------------------------------------------------
+
+RETCODE SQL_API SQLNumResultCols ( SQLHSTMT pStmt, SQLSMALLINT*  pColCountPtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLNumResultCols called" ) );
+    SQLResponse* rowdesc;
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    // caller safe
+    * ( ( SQLSMALLINT* ) pColCountPtr ) = 0;
+    // get the row desciptor
+    rowdesc = ( ( pODBCStmt ) pStmt )->IRD.RowDesc.get();
+    
+    if ( rowdesc == NULL ) {
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "SQLNumResultCols", "01000", -1, "no resultset or IRD" );
+        return SQL_ERROR;
+    }
+    
+    // count the number of columns
+    * ( ( SQLSMALLINT* ) pColCountPtr ) = ( SQLSMALLINT ) ( rowdesc->columnMetas.size() );
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLNumResultCols called returned: %d",
+                              * ( ( SQLSMALLINT* ) pColCountPtr ) ) );
+    return SQL_SUCCESS;
+}
+
+
+// ----------------------------------------------------------------------
+// to count the number of rows in the current result --- COUNTING ELEMENTS IN IRD
+// ----------------------------------------------------------------------
+
+RETCODE SQL_API SQLRowCount ( HSTMT pStmt, SQLLEN* pDataPtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLRowCount called" ) );
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    *pDataPtr = ( ( pODBCStmt ) pStmt )->RowCount;
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLRowCount returned: %d", *pDataPtr ) );
+    return SQL_SUCCESS;
+}
+
+// -----------------------------------------------------------------------
+// to return the next row from the resultset
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLFetch ( HSTMT pStmt ) {
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    // all fetch occur thru the local function _SQLFetch
+    /*
+        RETCODE SQL_API _SQLFetch ( pODBCStmt    pStmt,
+        Word            pFetchOrientation,
+        Long            pFetchOffset,
+        ULong*          pRowCountPtr,
+        UWord*          pRowStatusArray )
+    */
+    RETCODE ret =  _SQLFetch ( ( pODBCStmt ) pStmt, SQL_FETCH_NEXT,
+                               ( ( pODBCStmt ) pStmt )->ARD.RowArraySize > 0 ? ( ( pODBCStmt ) pStmt )->ARD.RowArraySize : 1,
+                               ( ( pODBCStmt ) pStmt )->IRD.RowsProcessedPtr, ( ( pODBCStmt ) pStmt )->IRD.ArrayStatusPtr );
+                               
+    if ( ret == SQL_NO_DATA ) {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_INFO, "Last row of current query has been fetched" ) );
+    }
+    
+    return ret;
+}
+
+// -----------------------------------------------------------------------
+// to fetch the specified rowset of data from the result set
+// Version Introduced: ODBC 1.0 Standards Compliance: Deprecated  (from msdn)
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLExtendedFetch ( SQLHSTMT        pStmt,
+                                   SQLUSMALLINT    pFetchOrientation,
+                                   SQLINTEGER      pFetchOffset,
+                                   SQLUINTEGER*    pRowCountPtr,
+                                   SQLUSMALLINT*   pRowStatusArray ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG,
+                              "SQLExtendedFetch called, Stmt: %d, FO: %d, Offset: %d, Rcount: %d, RowStatus: %d", pStmt, pFetchOrientation,
+                              pFetchOffset, pRowCountPtr, pRowStatusArray ) );
+    __ODBCPOPMSG ( _ODBCPopMsg ( "SQLExtendedFetch is not implemented   " ) );
+    return SQL_ERROR;
+    Long n;
+    __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
+    // free diags
+    _SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
+    
+    // only fetch next supported
+    if ( pFetchOrientation != SQL_FETCH_NEXT ) {
+        __ODBCPOPMSG ( _ODBCPopMsg ( "SQLExtendedFetch option not supported, FetchOrientation: %d", pFetchOrientation ) );
+        return SQL_ERROR;
+    }
+    
+    // check if number of rows explicitly specified
+    if ( pFetchOffset <= 0 )
+    { n = ( ( pODBCStmt ) pStmt )->ARD.RowArraySize; }
+    
+    // use default rowset size as a fallback
+    if ( n <= 0 )
+    { n = 1; }
+    
+    return _SQLFetch ( ( pODBCStmt ) pStmt, pFetchOrientation, n, pRowCountPtr, pRowStatusArray );
+}
+
+
+// -----------------------------------------------------------------------
+// to fetch the specified rowset of data from the result set
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLFetchScroll ( SQLHSTMT        pStatementHandle,
+                                 SQLSMALLINT     pFetchOrientation,
+                                 SQLINTEGER      pFetchOffset ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLFetchScroll called" ) );
+    __ODBCPOPMSG ( _ODBCPopMsg ( "SQLFetchScroll not implemented" ) );
+    return SQL_ERROR;
+}
+
+// -----------------------------------------------------------------------
+// to retrieve long data for a single column in the result set using multiple calls
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLGetData ( SQLHSTMT        pStmt,
+                             SQLUSMALLINT    pColNum,
+                             SQLSMALLINT     pgtType,
+                             SQLPOINTER      pDataPtr,
+                             SQLINTEGER      pDataSize,
+                             SQLINTEGER*     pDataSizePtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetData called" ) );
+    __ODBCPOPMSG ( _ODBCPopMsg ( "SQLGetData not implemented" ) );
+    return SQL_ERROR;
+}
+
+
+// -----------------------------------------------------------------------
+// to send data for a parameter or column to the driver at statement execution time
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLPutData ( SQLHSTMT       pStmt,
+                             SQLPOINTER     pDataPtr,
+                             SQLINTEGER     pDataSize ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLPutData called" ) );
+    __ODBCPOPMSG ( _ODBCPopMsg ( "SQLPutData not implemented" ) );
+    return SQL_ERROR;
+}
+
+// -----------------------------------------------------------------------
+// to iterate through multiple resultsets
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLMoreResults ( HSTMT pStmt ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLMoreResults called" ) );
+    __ODBCPOPMSG ( _ODBCPopMsg ( "SQLMoreResults not implemented" ) );
+    return SQL_ERROR;
+}
+
+// -----------------------------------------------------------------------
+// to get a driver specific version of specified sql statement
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API SQLNativeSql ( SQLHDBC         pConn,
+                               SQLCHAR*        pInStmtText,
+                               SQLINTEGER      pInStmtTextLen,
+                               SQLCHAR*        pOutStmtText,
+                               SQLINTEGER      pOutStmtTextLen,
+                               SQLINTEGER*     pOutStmtTextLenPtr ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLNativeSql called" ) );
+    __ODBCPOPMSG ( _ODBCPopMsg ( "SQLNativeSql not implemented" ) );
+    return SQL_ERROR;
+}
+
+
+
+
+// -----------------------------------------------------------------------
+// to convert and transfer col data for application
+// -----------------------------------------------------------------------
+
+//mhb TODO, check if the sqltype defined here match from c#
+RETCODE SQL_API _SQLColConvert ( pODBCStmt       pStmt,
+                                 void*               pTgtDataPtr,
+                                 Long*               pTgtDataSizePtr,
+                                 const wchar_t*      pSrcColData,
+                                 pARDItem     pARDCol,
+                                 bool                isSigned ) {
+    //check out this for SQL data type to C data type mapping
+    //http://msdn.microsoft.com/en-us/library/ms714556(v=vs.85).aspx
+    // note
+    // this function actually determines the conversion
+    // required to transfer the data
+    Word    pSrcDataType = pARDCol->SrcDataType;
+    Word    pTgtDataType = pARDCol->DataConciseType;
+    Long    pTgtDataSize = pARDCol->DataSize;
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "_SQLColConvert called" ) );
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "The SrcDataType is %d, the TgtDataType is %d, the TgtDataSize is %d",
+                              pSrcDataType, pTgtDataType, pTgtDataSize ) );
+                              
+    // TARGET TYPE IS LEFT TO OUR DRIVER
+    // check if target type is open
+    if ( pTgtDataType == SQL_DEFAULT ) {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "pTgtDataType is SQL_DEFAULT, use default type mapping." ) );
+        
+        // determine targettype based on data-source type
+        // check out this http://msdn.microsoft.com/en-us/library/ms716298(v=vs.85).aspx for default type mapping
+        switch ( pSrcDataType ) {
+            case SQL_CHAR:
+                pTgtDataType = SQL_C_CHAR;
+                break;
+                
+            case SQL_VARCHAR:
+                pTgtDataType = SQL_C_CHAR;
+                break;
+                
+            case SQL_WCHAR:
+                pTgtDataType = SQL_C_WCHAR;
+                break;
+                
+            case SQL_WVARCHAR:
+                pTgtDataType = SQL_C_WCHAR;
+                break;
+                
+            case SQL_DECIMAL:
+                pTgtDataType = SQL_C_CHAR;
+                break;
+                
+            case SQL_BIT:
+                pTgtDataType = SQL_C_BIT;
+                break;
+                
+            case SQL_TINYINT:
+                if ( isSigned )
+                { pTgtDataType = SQL_C_STINYINT; }
+                
+                else
+                { pTgtDataType = SQL_C_UTINYINT; }
+                
+                break;
+                
+            case SQL_SMALLINT:
+                if ( isSigned )
+                { pTgtDataType = SQL_C_SSHORT; }
+                
+                else
+                { pTgtDataType = SQL_C_USHORT; }
+                
+                break;
+                
+            case SQL_INTEGER:
+                if ( isSigned )
+                { pTgtDataType = SQL_C_SLONG; }
+                
+                else
+                { pTgtDataType = SQL_C_ULONG; }
+                
+                break;
+                
+            case SQL_BIGINT:
+                if ( isSigned )
+                { pTgtDataType = SQL_C_SBIGINT; }
+                
+                else
+                { pTgtDataType = SQL_C_UBIGINT; }
+                
+                break;
+                
+            case SQL_FLOAT:
+                pTgtDataType = SQL_C_FLOAT;
+                break;
+                
+            case SQL_DOUBLE:
+                pTgtDataType = SQL_C_DOUBLE;
+                break;
+                
+            case SQL_TYPE_DATE:
+                pTgtDataType = SQL_C_CHAR;
+                break;
+                
+            case SQL_TYPE_TIME:
+                pTgtDataType = SQL_C_CHAR;
+                break;
+                
+            case SQL_TYPE_TIMESTAMP:
+                pTgtDataType = SQL_C_CHAR;
+                break;
+                
+            //case SQL_C_SLONG:
+            //case SQL_C_ULONG:               // unsigned long
+            //case SQL_C_USHORT:
+            //case SQL_C_SSHORT:
+            //case SQL_NUMERIC:
+            //case SQL_REAL:
+            //  pTgtDataType = pSrcDataType;
+            //  break;
+            
+            default:
+                __ODBCPOPMSG ( _ODBCPopMsg ( "The data type %d not implemented", pSrcDataType ) );
+                return SQL_ERROR;
+                break;
+        }
+    }
+    
+    else {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "pTgtDataType is NOT SQL_DEFAULT, it is %d",  pTgtDataType ) );
+    }
+    
+    // TARGET TYPE IS CHAR
+    // as an optimization, check if the application
+    // or target data type is char. since the data from
+    // server is already in char format. the data can
+    // easily be transferred without incurring any
+    // conversion overhead
+    unique_ptr<char[]> pTextInAnsi ( wchar2char ( pSrcColData ) );
+    
+    // check if char type
+    if ( pTgtDataType == SQL_CHAR || pTgtDataType == SQL_VARCHAR ) {
+        // only in case of src data being bool a conversion is required
+        if ( pSrcDataType == SQL_BIT ) {
+            // prepare a converted single char bool string
+            Char  src[2];
+            
+            if ( pTextInAnsi.get() == NULL )
+            { src[0] = '0'; }
+            
+            else
+            { src[0] = ( pTextInAnsi.get() [0] == 'T' || pTextInAnsi.get() [0] == '1' || pTextInAnsi.get() [0] == 't' ) ? '1' : '0'; }
+            
+            src[1] = 0;
+            // transfer the bool string
+            return _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, src, -1 );
+        }
+        
+        else {
+            // transfer the string as it is
+            return _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, pTextInAnsi.get(),
+                                      -1 );
+        }
+    }
+    
+    if ( pTgtDataType == SQL_WCHAR || pTgtDataType == SQL_WVARCHAR ) {
+        return _SQLCopyWCharDataW ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, pSrcColData, -1 );
+    }
+    
+    // TARGET TYPE IS NOT CHAR
+    
+    // try using a numeric conversion
+    switch ( _SQLCopyNumData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pTgtDataType, pTextInAnsi.get(), pSrcDataType ,
+                               pTgtDataSizePtr ) ) {
+        case -1:
+            return SQL_ERROR;
+            
+        case 0:
+            return SQL_SUCCESS;
+            
+        default:
+            break;
+    }
+    
+    // try using a date/time conversion
+    switch ( _SQLCopyDateTimeData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pTgtDataType, pTextInAnsi.get(), pSrcDataType ) ) {
+        case -1:
+            return SQL_ERROR;
+            
+        case 0:
+            return SQL_SUCCESS;
+            
+        default:
+            break;
+    }
+    
+    // try using SQL_BIT data type ie bool
+    if ( pTgtDataType == SQL_BIT ) {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "the target data type is SQL_C_BIT" ) );
+        
+        // prepare a converted single char bool string
+        if ( pTextInAnsi.get() == NULL )
+        { * ( ( char* ) pTgtDataPtr ) = 0; }
+        
+        else
+        { * ( ( char* ) pTgtDataPtr ) = ( pTextInAnsi.get() [0] == 'T' || pTextInAnsi.get() [0] == '1' || pTextInAnsi.get() [0] == 't' ) ? 1 : 0; }
+        
+        return SQL_SUCCESS;
+    }
+    
+    // error condition
+    __ODBCPOPMSG ( _ODBCPopMsg ( "_SQLColConvert - Unknown data type, Target: %d, Source: %d", pTgtDataType,
+                                 pSrcDataType ) );
+    _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLColConvert", "01000", -1, "Unknown data type, Target: %d, Source: %d",
+                     pTgtDataType, pSrcDataType );
+    return SQL_ERROR;
+}
+
+
+// -----------------------------------------------------------------------
+// to get the specified column data from
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API _SQLFetchCol ( pODBCStmt pStmt,
+                               pARDItem pARDCol, //ard
+                               SQLResponse* pRowDesc,// ird
+                               SQLRowContent* pRowData ) { //content
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "_SQLFetchCol called" ) );
+    // note
+    // this function checks the binding type and positions the pointer
+    // for copying the data accordingly. It takes into account the
+    // current row position in rowset, the initial min increment specified
+    // by client and the size of the row or col buffer
+    Long        i;
+    Long        j;
+    Long*       tgtsizeptr;                                         // target size ptr
+    void*       tgtdataptr;                                         // target data ptr
+    const wchar_t*     srcdata;                                            // source data
+    SelectedColumnMeta*    coldesc;
+    // COMPUTE DATA AND SIZE PTR
+    // get the row pos in current rowset
+    i = ( pStmt->CurRowsetEndRowPos - pStmt->CurRowsetStartRowPos );
+    // compute min increment
+    j = ( pStmt->ARD.BindOffsetPtr ) ? * ( pStmt->ARD.BindOffsetPtr ) : 0;
+    
+    // check the binding type
+    if ( pStmt->ARD.BindTypeOrSize != SQL_BIND_BY_COLUMN ) {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "ARD bindtypeorsize not euqal to SQL_BIND_BY_COLUMN" ) );
+        // note
+        Long k;
+        // compute row-size increment
+        k = ( pStmt->ARD.BindTypeOrSize );
+        // compute target col and size ptr
+        tgtdataptr = ( void* ) ( ( ( Char* ) ( pARDCol->DataPtr ) ) + j + ( i * k ) );
+        tgtsizeptr = ( Long* ) ( ( ( Char* ) ( pARDCol->SizePtr ) ) + j + ( i * k ) );
+    }
+    
+    // column-wise binding
+    else {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "ARD bindtypeorsize euqal to SQL_BIND_BY_COLUMN" ) );
+        // move both data and size ptr in the array
+        //TODO find out where the pARDCol->DataSize if set
+        tgtdataptr = ( void* ) ( ( ( Char* ) ( pARDCol->DataPtr ) ) + j + ( i * pARDCol->DataSize ) ); // use based on data type
+        tgtsizeptr = ( Long* ) ( ( ( Char* ) ( pARDCol->SizePtr ) ) + j + ( i * sizeof ( Long ) ) );
+    }
+    
+    // PRECAUTION
+    
+    if ( tgtdataptr )   { * ( ( Char* ) tgtdataptr ) = 0; }
+    
+    if ( tgtsizeptr )   { * ( ( Long* ) tgtsizeptr ) = 0; }
+    
+    // COLLECT AND CHECK
+    // get col desc for specified col ( response )
+    coldesc = pRowDesc->columnMetas.at ( pARDCol->ColNum - 1 );
+    //if ( coldesc == NULL ) {
+    //  _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLFetchCol", "01000", -1, pStmt->CurRowsetEndRowPos, pARDCol->ColNum, "column not found in resultset for specified index" );
+    //  return SQL_SUCCESS_WITH_INFO;                 // no col for specified index
+    //}
+    // get the col data for specfied col ( response )
+    srcdata = pRowData->contents.at ( pARDCol->ColNum - 1 ).c_str();
+    
+    //coldata = SOAPGetChildElemX ( pRowData, pARDCol->ColNum );
+    //if ( coldata == NULL ) {
+    
+    //  _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLFetchCol", "01000", -1, pStmt->CurRowsetEndRowPos, pARDCol->ColNum, "column not found in resultset for specified index" );
+    //  return SQL_SUCCESS_WITH_INFO;                 // no col for specified index
+    //}
+    
+    // get col value as string
+    //srcdata = SOAPGetElemText ( coldata );
+    
+    // NULL DATA                                            // note: a text of NULL indicates NULL data from server
+    
+    // check if data is NULL
+    if ( srcdata == NULL || _wcsicmp ( srcdata, L"NULL" ) == 0 ) {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "srcdata is null" ) );
+        
+        // check if a size indicator is available
+        if ( tgtsizeptr == NULL ) {
+            _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLFetchCol", "22002", -1, pStmt->CurRowsetEndRowPos, pARDCol->ColNum,
+                             "Indicator variable required but not supplied" );
+            return SQL_SUCCESS_WITH_INFO;
+        }
+        
+        // set to SQL_NULL_DATA
+        else {
+            // indicate null data
+            * ( ( Long* ) tgtsizeptr ) = SQL_NULL_DATA;
+            // added precaution for bad appl design
+            /*  if ( tgtdataptr )
+                memset ( tgtdataptr, 0, pARDCol->MaxSize );*/
+            return SQL_SUCCESS;
+        }
+    }
+    
+    // check if info about src is also available in ARD col
+    if ( pARDCol->SrcDataType == 0 )
+    { GetIRDColDescInfo ( coldesc, & ( pARDCol->SrcDataType ), & ( pARDCol->SrcDataPrecision ), & ( pARDCol->SrcDataScale ), & ( pARDCol->SrcDataSize ) ); } // collect source data information in form comparable to appl
+    
+    // CONVERT AND TRANSFER
+    //Important!!!
+    //Notice the specification of different types
+    //http://publib.boulder.ibm.com/infocenter/idshelp/v10/index.jsp?topic=/com.ibm.odbc.doc/odbc72.htm
+    RETCODE ret = _SQLColConvert ( pStmt, tgtdataptr, tgtsizeptr, srcdata, pARDCol, coldesc->isSigned );
+    //char buffer[1024];
+    //hexDump((char*)tgtdataptr,4,buffer,false);
+    //__ODBCLOG(_ODBCLogMsg(LogLevel_DEBUG,buffer));
+    //hexDump((char*)tgtdataptr,4,buffer,true);
+    //__ODBCLOG(_ODBCLogMsg(LogLevel_DEBUG,buffer));
+    return ret;
+}
+
+
+// -----------------------------------------------------------------------
+// to move to the next row with relevant checks
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API _SQLFetchMoveNext ( pODBCStmt pStmt ) {
+    __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "_SQLFetch MoveNext is called" ) );
+    
+    // check if there is some response of type resultset
+    if (
+        pStmt->IRD.RowDesc != NULL ) {
+        // ------- THIS CASE SHOULD NOT OCCUR ----------
+        
+        // check if position is currently unknown
+        if ( pStmt->CurRowsetStartRow == NULL && pStmt->CurRowsetStartRowPos == 0 ) {
+            // position to first row ( both the pointers )
+            pStmt->CurRowsetStartRowPos = 1;
+            pStmt->CurRowsetStartRow    = GetIfExist ( pStmt->IRD.RowDesc->results, 1 );
+            pStmt->CurRowsetEndRowPos   = 1;
+            pStmt->CurRowsetEndRow      = GetIfExist ( pStmt->IRD.RowDesc->results, 1 );
+        }
+        
+        // -----------------------------------------------
+        
+        // position to next row if already position is known
+        else if ( pStmt->CurRowsetEndRow != NULL ) {
+            // position to next row
+            pStmt->CurRowsetEndRowPos  += 1;
+            pStmt->CurRowsetEndRow      = GetIfExist ( pStmt->IRD.RowDesc->results, pStmt->CurRowsetEndRowPos );
+        }
+        
+        // finally check if there is some data found
+        if ( pStmt->CurRowsetEndRow == NULL ) {
+            // put in diag
+            _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "", "01000", -1, "SQLFetch - no data" );
+            return SQL_NO_DATA;
+        }
+        
+        else
+        { return SQL_SUCCESS; }
+    }
+    
+    else {
+        // error situation
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLFetchMoveNext", "01000", -1, "no resultset" );
+        return SQL_ERROR;
+    }
+}
+
+SQLRowContent* GetIfExist ( std::vector<SQLRowContent*>& container, int index ) {
+    index = index - 1; //sql cardinals start at 1
+    
+    if ( index >= ( int ) container.size() )
+    { return NULL; }
+    
+    else
+    { return container.at ( index ); }
+}
+
+// -----------------------------------------------------------------------
+// to set the initial row positions for a fetch
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API _SQLResetRowPos ( pODBCStmt pStmt ) {
+    // note
+    // there r 2 row pointers one is the start row for the current fetch and
+    // the other is the end row after the current fetch
+    // this function brings them together and moves them to the first row
+    // after the cur end row
+    // a block of rows which is fetched in one go is ROWSET while the full
+    // result is called RESULTSET
+    
+    // check if there is some response of type resultset
+    if (
+        pStmt->IRD.RowDesc != NULL ) {
+        // check if position is currently unknown
+        if ( pStmt->CurRowsetEndRow == NULL && pStmt->CurRowsetEndRowPos == 0 ) {
+            // position to first row ( both the pointers )
+            pStmt->CurRowsetEndRowPos   = 1;
+            pStmt->CurRowsetEndRow = GetIfExist ( pStmt->IRD.RowDesc->results, pStmt->CurRowsetEndRowPos );
+        }
+        
+        // already positioned somewhere
+        else if ( pStmt->CurRowsetEndRow != NULL ) {
+            // position to next row
+            pStmt->CurRowsetEndRowPos  += 1;
+            pStmt->CurRowsetEndRow = GetIfExist ( pStmt->IRD.RowDesc->results, pStmt->CurRowsetEndRowPos );
+        }
+        
+        // calibrate the first row with end row
+        pStmt->CurRowsetStartRow    = pStmt->CurRowsetEndRow;
+        pStmt->CurRowsetStartRowPos = pStmt->CurRowsetEndRowPos;
+        
+        // finally check if there is some data found
+        if ( pStmt->CurRowsetStartRow == NULL ) {
+            // put in diag
+            _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "", "01000", -1, "SQLFetch - no data" );
+            return SQL_NO_DATA;
+        }
+        
+        else
+        { return SQL_SUCCESS; }
+    }
+    
+    else {
+        // error situation
+        _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLResetRowPos", "01000", -1, "no resultset" );
+        return SQL_ERROR;
+    }
+}
+
+
+// -----------------------------------------------------------------------
+// to return the next row from the resultset
+// -----------------------------------------------------------------------
+
+RETCODE SQL_API _SQLFetch ( pODBCStmt    pStmt,
+                            Word            pFetchOrientation,
+                            Long            pFetchOffset, //ARD.RowArraySize
+                            ULong*          pRowCountPtr, //IRD.RowsProcessedPtr
+                            UWord*          pRowStatusArray ) { //ArrayStatusPtr
+    // note
+    // fetchoffset is treated as the number of rows to fetch
+    bool                flgNoData;
+    Long                i, n1, n2;
+    RETCODE             s;
+    SQLRowContent*      rowdata;
+    SQLResponse*        rowdesc;
+    pODBCARD            ard;
+    pARDItem            ardcol;
+    
+    // CALLER SAFE
+    
+    // caller safe for row fetched
+    if ( pRowCountPtr )
+    { *pRowCountPtr = 0; }
+    
+    // caller safe for each row status
+    if ( pRowStatusArray )
+        for ( i = 0; i < pFetchOffset; i ++ )   { pRowStatusArray[i] = SQL_ROW_NOROW; }
+        
+    // RESET POSITION OR SET INITIAL POSITIONS
+    
+    // postions the row counter for fetch start
+    if ( ( s = _SQLResetRowPos ( ( pODBCStmt ) pStmt ) ) != SQL_SUCCESS )
+    { return s; }
+    
+    // COLLECT INFO to START
+    // get the row desc - ird
+    rowdesc = ( ( pODBCStmt ) pStmt )->IRD.RowDesc.get();
+    // get the row desc - ard
+    ard = & ( ( ( pODBCStmt ) pStmt )->ARD );
+    
+    // MAIN LOOP to fetch rowset number of rows
+    // loop to fetch the rows
+    for ( i = 0, n1 = 0, n2 = 0, flgNoData = FALSE; i < pFetchOffset && flgNoData == FALSE; i ++ ) {
+        __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "Get One Row:" ) );
+        
+        // check if first row or not
+        if ( i != 0 ) {
+            // move to next row if not first time
+            switch ( _SQLFetchMoveNext ( pStmt ) ) {
+                case SQL_NO_DATA:
+                    flgNoData = TRUE;           // can continue
+                    continue;
+                    
+                case SQL_ERROR:
+                    return SQL_ERROR;           // not continuing
+                    
+                default:                        // case SQL_SUCCESS:
+                    break;
+            }
+        }
+        
+        // get the current row data
+        rowdata = pStmt->CurRowsetEndRow;
+        
+        // LOOP to fetch cols of one row
+        
+        // loop to put data in all bound cols
+        for ( ardcol = ard->BindCols; ardcol != NULL; ardcol = ardcol->Next ) {
+            __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "Get one column:" ) );
+            // get data using _SQLFetchCol
+            s = _SQLFetchCol ( pStmt, ardcol, rowdesc, rowdata );
+            
+            // update row status
+            switch ( s ) {
+                case SQL_SUCCESS:
+                    if ( pRowStatusArray && pRowStatusArray[i] == SQL_ROW_NOROW ) { pRowStatusArray[i] = SQL_ROW_SUCCESS_WITH_INFO; }
+                    
+                    break;
+                    
+                case SQL_SUCCESS_WITH_INFO:
+                    ++ n1;                  // rows with info
+                    
+                    if ( pRowStatusArray ) { pRowStatusArray[i - 1] = SQL_ROW_SUCCESS_WITH_INFO; }
+                    
+                    break;
+                    
+                default:
+                    ++ n2;                   // no. of rows with error
+                    
+                    if ( pRowStatusArray ) { pRowStatusArray[i - 1] = SQL_ROW_ERROR; }
+            }
+        }
+        
+        // update the number of rows fetched
+        if ( pRowCountPtr ) { *pRowCountPtr = i + 1; }
+    }
+    
+    // check if no data
+    if ( flgNoData == TRUE && i <= 0 )
+    { return SQL_NO_DATA; }
+    
+    // check if all error
+    else if ( i > 0 && n2 == i )
+    { return SQL_ERROR; }
+    
+    // check if any success with info
+    else if ( i > 0 && n1 > 0 )
+    { return SQL_SUCCESS_WITH_INFO; }
+    
+    // all success
+    else {
+        return SQL_SUCCESS;
+    }
+}
+